Skip to content

Commit b29f171

Browse files
kbloodclaude
andauthored
ide: fix ATAPI CD in Win9x (UNIT ATTENTION root cause) without breaking OAKCDROM (MiSTer-devel#1224)
PR MiSTer-devel#1221 fixed the Win9x protected-mode "Code 10" on the ATAPI CD's IDE controller by globally stripping the DSC/SERVICE status bit (0x10) for CD drives. That approach had two problems: 1. It broke real-mode CD detection. OAKCDROM.SYS (the DOS / Win9x-setup ATAPI driver) keys off an explicit status byte after the ATAPI DEVICE RESET to detect the drive; the blanket strip clobbered it -> "No drives found". 2. The Code 10 it "fixed" was never a DSC problem. The strip only masked the real bug. Real root cause of the Code 10: a successful ATAPI INQUIRY was completing with a spurious UNIT ATTENTION. INQUIRY / REQUEST SENSE are exempt from the media-change gate so they deliver their data even with a pending media change, but the WAIT_PKT_RD completion called cdrom_reply() with the default unit_attention=true, stamping CHECK CONDITION / err=0x60 onto the finished transfer. Win9x's ESDI_506 reads "INQUIRY returned its data AND failed" as a dead controller and refuses to start the channel -> Device Manager Code 10. Bochs and 86Box both return GOOD for INQUIRY. Fixes: - ide_set_regs: replace the global DSC strip with "auto-assert DSC for non-CD drives only", letting each ATAPI command publish its own (DSC-free) status. Satisfies both OAK and Win9x without any blanket bit-4 policy. - ATAPI DEVICE RESET (cmd 0x08): present status 0x00 (no DRDY/DSC), matching real ATAPI hardware, which routes OAKCDROM to its signature-detect path. - WAIT_PKT_RD completion: pass unit_attention=false so a successful data phase reports GOOD. The pending media-change UA is still delivered on the first non-exempt command (TEST UNIT READY -> cdrom_nodisk). - Post ATAPI diagnostic code 01h in the error register after a bus reset; a stale ABRT was otherwise read by ESDI_506 as a failed power-on self-test. Tested on DE10-Nano: Win98 SE enumerates "MiSTer CDROM" with both Standard IDE/ESDI controllers clean (no Code 10), and real-mode OAKCDROM.SYS detects the CD (MSCDEX assigns drive D:). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 105b013 commit b29f171

2 files changed

Lines changed: 14 additions & 12 deletions

File tree

ide.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,11 @@ void ide_get_regs(ide_config *ide)
160160

161161
void ide_set_regs(ide_config *ide)
162162
{
163-
if (!(ide->regs.status & (ATA_STATUS_BSY | ATA_STATUS_ERR))) ide->regs.status |= ATA_STATUS_DSC;
164-
165-
// For ATAPI (packet) devices, status bit 4 is the SERVICE bit, not DSC. We never run
166-
// overlapped commands, so SERVICE must read 0. Force it low for CD drives, matching 86Box
167-
// ide_status() which masks DSC out of every ATAPI status read (hdc_ide.c). Win9x ESDI_506
168-
// otherwise reads the permanent bit-4 as "overlapped-command SERVICE pending", rejects the
169-
// channel, and the device fails to start (Device Manager Code 10).
170-
if (ide->drive[ide->regs.drv].cd) ide->regs.status &= ~ATA_STATUS_DSC;
163+
// Auto-assert DSC for non-CD drives only; let each ATAPI command set its own status.
164+
if (!ide->drive[ide->regs.drv].cd && !(ide->regs.status & (ATA_STATUS_BSY | ATA_STATUS_ERR)))
165+
{
166+
ide->regs.status |= ATA_STATUS_DSC;
167+
}
171168

172169
uint8_t data[12] =
173170
{
@@ -1016,7 +1013,8 @@ void ide_io(int num, int req)
10161013
else if (ide->state == IDE_STATE_WAIT_PKT_RD)
10171014
{
10181015
if (ide->regs.pkt_cnt) cdrom_read(ide);
1019-
else cdrom_reply(ide, 0);
1016+
// A successful data-phase completion must report GOOD, not UNIT ATTENTION.
1017+
else cdrom_reply(ide, 0, 0, 0, false);
10201018
}
10211019
else if (ide->state == IDE_STATE_WAIT_PKT_MODE)
10221020
{
@@ -1049,7 +1047,8 @@ void ide_io(int num, int req)
10491047

10501048
ide_get_regs(ide);
10511049
ide->regs.head = 0;
1052-
ide->regs.error = 0;
1050+
// ATAPI posts diagnostic code 01h after a bus reset; an ATA HDD posts 0.
1051+
ide->regs.error = ide->drive[ide->regs.drv].cd ? 1 : 0;
10531052
ide->regs.sector = 1;
10541053
ide->regs.sector_count = 1;
10551054
ide->regs.cylinder = (!ide->drive[ide->regs.drv].present) ? 0xFFFF : ide->drive[ide->regs.drv].cd ? 0xEB14 : 0x0000;

ide_cdrom.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,11 +1579,14 @@ int cdrom_handle_cmd(ide_config *ide)
15791579
ide->regs.sector_count = 1;
15801580
ide->regs.cylinder = 0xEB14;
15811581
ide->regs.head = 0;
1582+
// ATAPI diagnostic code 01h after DEVICE RESET.
1583+
ide->regs.error = 1;
15821584
ide->regs.io_size = 0;
1583-
ide->regs.status = ATA_STATUS_RDY | ATA_STATUS_DSC;
1585+
// Present status 0x00 (no DRDY/DSC), matching real ATAPI HW; routes OAKCDROM to signature detect.
1586+
ide->regs.status = 0;
15841587
ide_set_regs(ide);
15851588
break;
1586-
1589+
15871590
case 0xEF: // set features
15881591
switch(ide->regs.features)
15891592
{

0 commit comments

Comments
 (0)