diff --git a/drivers/storage/ide/uniata/id_ata.cpp b/drivers/storage/ide/uniata/id_ata.cpp index 0a0c586a7ce..a49811ba90d 100644 --- a/drivers/storage/ide/uniata/id_ata.cpp +++ b/drivers/storage/ide/uniata/id_ata.cpp @@ -9499,6 +9499,82 @@ reject_srb: (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)/* && (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) { KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0])); +#ifdef __REACTOS__ + status = SRB_STATUS_BUSY; + + if (Srb->Cdb[0] == SCSIOP_INQUIRY && + (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) && + (LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM || + LunExt->IdentifyData.DeviceType == ATAPI_TYPE_OPTICAL) && + LunExt->IdentifyData.ModelNumber[0]) + { + ULONG j; + CCHAR vendorId[26]; + + // Attempt to identify known broken CD/DVD drives + for (j = 0; j < sizeof(vendorId); j += 2) + { + // Build a buffer based on the identify data. + MOV_DW_SWP(vendorId[j], ((PUCHAR)LunExt->IdentifyData.ModelNumber)[j]); + } + + // Emulate INQUIRY support for broken CD/DVD drives (e.g. Microsoft Xbox). + // Currently we implement it by explicitly checking the drive name from ATA IDENTIFY PACKET. + if (!AtapiStringCmp(vendorId, "THOMSON-DVD", 11) || + !AtapiStringCmp(vendorId, "PHILIPS XBOX DVD DRIVE", 22) || + !AtapiStringCmp(vendorId, "PHILIPS J5 3235C", 16) || + !AtapiStringCmp(vendorId, "SAMSUNG DVD-ROM SDG-605B", 24)) + { + // TODO: + // Better send INQUIRY and then check for chan->ReturningMediaStatus >> 4 == SCSI_SENSE_ILLEGAL_REQUEST + // in AtapiInterrupt__() and emulate the response only in this case. + + // If this hack stays for long enough, consider adding Xbox 360 drive names to the condition, + // as they are affected by the same problem. + + // See https://jira.reactos.org/browse/CORE-16692 + ULONG i; + PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer); + PIDENTIFY_DATA2 identifyData = &(LunExt->IdentifyData); + + // Zero INQUIRY data structure. + RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength); + + // This is ATAPI CD- or DVD-ROM. + inquiryData->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE; + + // Set the removable bit, if applicable. + if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) { + KdPrint2((PRINT_PREFIX + "RemovableMedia\n")); + inquiryData->RemovableMedia = 1; + } + // Set the Relative Addressing (LBA) bit, if applicable. + if (LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) { + inquiryData->RelativeAddressing = 1; + KdPrint2((PRINT_PREFIX + "RelativeAddressing\n")); + } + // Set the CommandQueue bit + inquiryData->CommandQueue = 1; + + // Fill in vendor identification fields. + for (i = 0; i < 24; i += 2) { + MOV_DW_SWP(inquiryData->DeviceIdentificationString[i], ((PUCHAR)identifyData->ModelNumber)[i]); + } + + // Move firmware revision from IDENTIFY data to + // product revision in INQUIRY data. + for (i = 0; i < 4; i += 2) { + MOV_DW_SWP(inquiryData->ProductRevisionLevel[i], ((PUCHAR)identifyData->FirmwareRevision)[i]); + } + + status = SRB_STATUS_SUCCESS; + } + } + + if (status != SRB_STATUS_SUCCESS) +#endif status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL); } else { KdPrint2((PRINT_PREFIX "Try IDE send\n"));