Index: drivers/storage/ide/uniata/atapi.h =================================================================== --- drivers/storage/ide/uniata/atapi.h (revision 57044) +++ drivers/storage/ide/uniata/atapi.h (working copy) @@ -502,6 +502,7 @@ #define ATA_F_DMA 0x01 /* enable DMA */ #define ATA_F_OVL 0x02 /* enable overlap */ +#define ATA_F_DMAREAD 0x04 /* DMA Packet (ATAPI) read */ #define ATA_C_F_SETXFER 0x03 /* set transfer mode */ @@ -628,8 +629,19 @@ ULONG UserAddressableSectors; // 60-61 - USHORT SingleWordDMASupport : 8; // 62 \- obsolete - USHORT SingleWordDMAActive : 8; // /- + union { + struct { + USHORT SingleWordDMASupport : 8; // 62 ATA, obsolete + USHORT SingleWordDMAActive : 8; // + }; + struct { + USHORT UDMASupport : 7; // 62 ATAPI + USHORT MultiWordDMASupport : 3; + USHORT DMASupport : 1; + USHORT Reaseved62_11_14 : 4; + USHORT DMADirRequired : 1; + } AtapiDMA; + }; USHORT MultiWordDMASupport : 8; // 63 USHORT MultiWordDMAActive : 8; Index: drivers/storage/ide/uniata/bsmaster.h =================================================================== --- drivers/storage/ide/uniata/bsmaster.h (revision 57044) +++ drivers/storage/ide/uniata/bsmaster.h (working copy) @@ -187,11 +187,14 @@ } CAP; #define AHCI_CAP_NOP_MASK 0x0000001f +#define AHCI_CAP_CCC 0x00000080 #define AHCI_CAP_NCS_MASK 0x00001f00 #define AHCI_CAP_PMD 0x00008000 #define AHCI_CAP_SPM 0x00020000 #define AHCI_CAP_SAM 0x00040000 #define AHCI_CAP_SCLO 0x01000000 +#define AHCI_CAP_SNTF 0x20000000 +#define AHCI_CAP_NCQ 0x40000000 #define AHCI_CAP_S64A 0x80000000 // Global HBA Control @@ -619,6 +622,7 @@ #define IDX_AHCI_P_TFD (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD)) #define IDX_AHCI_P_SIG (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG)) #define IDX_AHCI_P_CMD (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, CMD)) +#define IDX_AHCI_P_ACT (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SACT)) #define IDX_AHCI_P_SNTF (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SNTF)) @@ -1160,8 +1164,8 @@ HW_LU_EXTENSION lun[IDE_MAX_LUN]; HW_CHANNEL chan[AHCI_MAX_PORT/*IDE_MAX_CHAN*/]; #else - PHW_LU_EXTENSION lun; - PHW_CHANNEL chan; + PHW_LU_EXTENSION lun; // lun array + PHW_CHANNEL chan; // channel array #endif UCHAR LastInterruptedChannel; // Indicates the number of blocks transferred per int. according to the Index: drivers/storage/ide/uniata/id_ata.cpp =================================================================== --- drivers/storage/ide/uniata/id_ata.cpp (revision 57044) +++ drivers/storage/ide/uniata/id_ata.cpp (working copy) @@ -773,7 +773,7 @@ IN ULONG wait_flags ) { - PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); UCHAR statusByte; ULONG i; PUCHAR plba; @@ -1089,7 +1089,7 @@ KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no items\n")); return; } - chan = &deviceExtension->chan[lChannel]; + chan = &(deviceExtension->chan[lChannel]); while(TRUE) { @@ -1178,13 +1178,13 @@ chan = prev_chan = NULL; while(i != CHAN_NOT_SPECIFIED) { prev_chan = chan; - chan = &deviceExtension->chan[i]; + chan = &(deviceExtension->chan[i]); if(chan->DpcTime > time.QuadPart) { break; } i = chan->NextDpcChan; } - chan = &deviceExtension->chan[lChannel]; + chan = &(deviceExtension->chan[lChannel]); if(!prev_chan) { deviceExtension->FirstDpcChan = lChannel; } else { @@ -1271,7 +1271,7 @@ ) { PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; - PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); ULONG waitCount = 50000; ULONG j; UCHAR statusByte; @@ -1424,6 +1424,7 @@ // Send IDENTIFY command. // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer. + statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, (j < 4) ? DEV_BSIZE : 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR); // Clear interrupt @@ -2066,10 +2067,10 @@ for (; j < numberChannels; j++) { KdPrint2((PRINT_PREFIX "AtapiResetController: Reset channel %d\n", j)); - chan = &deviceExtension->chan[j]; - KdPrint2((PRINT_PREFIX " CompleteType %#x\n", CompleteType)); + chan = &(deviceExtension->chan[j]); + MaxLuns = chan->NumberLuns; + KdPrint2((PRINT_PREFIX " CompleteType %#x, Luns %d, chan %#x\n", CompleteType, MaxLuns, chan)); //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2; - MaxLuns = chan->NumberLuns; if(CompleteType != RESET_COMPLETE_NONE) { #ifndef UNIATA_CORE while((CurSrb = UniataGetCurRequest(chan))) { @@ -2283,11 +2284,14 @@ // all these shall be performed inside AtapiHwInitialize__() ? #if 1 - KdPrint2((PRINT_PREFIX " process connected devices\n")); + KdPrint2((PRINT_PREFIX " process connected devices 0 - %d\n", MaxLuns-1)); // Do special processing for ATAPI and IDE disk devices. for (i = 0; i < MaxLuns; i++) { // Check if device present. + KdPrint2((PRINT_PREFIX " Chan %#x\n", chan)); + KdPrint2((PRINT_PREFIX " Lun %#x\n", i)); + KdPrint2((PRINT_PREFIX " Lun ptr %#x\n", chan->lun[i])); if (!(chan->lun[i]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { if(ChipFlags & UNIATA_AHCI) { // everything is done in UniataAhciReset() @@ -2429,7 +2433,7 @@ ULONG lChannel = GET_CHANNEL(Srb); PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); // ULONG i; - UCHAR errorByte; + UCHAR errorByte = 0; UCHAR srbStatus = SRB_STATUS_SUCCESS; UCHAR scsiStatus; ULONG DeviceNumber = GET_CDEV(Srb); @@ -2437,7 +2441,15 @@ // Read the error register. - errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); + if(deviceExtension->HwFlags & UNIATA_AHCI) { + PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); + if(AtaReq) { + errorByte = AtaReq->ahci.in_error; + } else { + } + } else { + errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); + } KdPrint2((PRINT_PREFIX "MapError: Error register is %#x\n", errorByte)); @@ -3803,7 +3815,7 @@ if(deviceExtension->HwFlags & UNIATA_AHCI) { UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | - ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | + ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_INF | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) | ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | /* DEBUG */ ATA_AHCI_P_IX_DI | @@ -4576,6 +4588,29 @@ if(deviceExtension->HwFlags & UNIATA_AHCI) { UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, srb); statusByte = (UCHAR)(AtaReq->ahci.in_status & IDE_STATUS_MASK); + + if(chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB)) { + KdPrint3((PRINT_PREFIX "Err intr (%#x)\n", chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB))); + if(chan->AhciLastIS & ~ATA_AHCI_P_IX_OF) { + //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF)); + // We have some other error except Overflow + // Just signal ERROR, operation will be aborted in ERROR branch. + statusByte |= IDE_STATUS_ERROR; + } else { + // We have only Overflow. Abort operation and continue +#if DBG + UniataDumpAhciPortRegs(chan); +#endif + if(!UniataAhciAbortOperation(chan)) { + KdPrint2((PRINT_PREFIX "need UniataAhciReset\n")); + } +#if DBG + UniataDumpAhciPortRegs(chan); +#endif + UniataAhciWaitCommandReady(chan, 10); + } + } + } else { GetBaseStatus(chan, statusByte); } @@ -4738,16 +4773,16 @@ (dma_status & BM_STATUS_ERR)) { if(deviceExtension->HwFlags & UNIATA_AHCI) { - error = (UCHAR)((AtaReq->ahci.in_status >> 8) & 0xff); + error = AtaReq->ahci.in_error; // wait ready #if DBG UniataDumpAhciPortRegs(chan); #endif - UniataAhciStop(chan); - UniataAhciStart(chan); - + if(!UniataAhciAbortOperation(chan)) { + KdPrint2((PRINT_PREFIX "need UniataAhciReset\n")); + } + // clear interrupts again UniataAhciWaitCommandReady(chan, 10); - // clear interrupts again #if DBG UniataDumpAhciPortRegs(chan); #endif @@ -5199,8 +5234,19 @@ if(DataOverrun) { KdPrint2((PRINT_PREFIX " DataOverrun\n")); AtapiSuckPort2(chan); + GetBaseStatus(chan, statusByte); } + if(statusByte & IDE_STATUS_BUSY) { + for (i = 0; i < 2; i++) { + AtapiStallExecution(10); + GetBaseStatus(chan, statusByte); + if (!(statusByte & IDE_STATUS_BUSY)) { + break; + } + } + } + } else { KdPrint2((PRINT_PREFIX "IdeIntr: Read %#x Dwords\n", wordCount/2)); @@ -5361,7 +5407,7 @@ CompleteRequest: - KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest\n")); + KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, srbstatus %x\n", status)); // Check and see if we are processing our secret (mechanism status/request sense) srb if (AtaReq->OriginalSrb) { @@ -5790,6 +5836,13 @@ interruptReason, statusByte)); + if(OldReqState == REQ_STATE_DPC_WAIT_BUSY0 && + AtaReq->WordsLeft == 0) { + KdPrint2((PRINT_PREFIX "AtapiInterrupt: pending WAIT_BUSY0. Complete.\n")); + status = SRB_STATUS_SUCCESS; + chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; + goto CompleteRequest; + } } ReturnEnableIntr: @@ -5980,7 +6033,7 @@ NTAPI UniAtaCalculateLBARegs( PHW_LU_EXTENSION LunExt, - ULONG startingSector, + ULONGLONG startingSector, PULONG max_bcount ) { @@ -6077,7 +6130,7 @@ PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); //ULONG ldev = GET_LDEV(Srb); UCHAR DeviceNumber = GET_CDEV(Srb);; - ULONG startingSector; + ULONGLONG startingSector=0; ULONG max_bcount; ULONG wordCount = 0; UCHAR statusByte,statusByte2; @@ -6108,9 +6161,9 @@ if(AtaReq->WordsTransfered) { AtaReq->DataBuffer = ((PUSHORT)(Srb->DataBuffer)) + AtaReq->WordsTransfered; - startingSector = (ULONG)(UniAtaCalculateLBARegsBack(LunExt, AtaReq->lba)) /* latest lba */ + AtaReq->bcount /* previous bcount */; + startingSector = (UniAtaCalculateLBARegsBack(LunExt, AtaReq->lba)) /* latest lba */ + AtaReq->bcount /* previous bcount */; AtaReq->bcount = (AtaReq->TransferLength - AtaReq->WordsTransfered*2 + DEV_BSIZE-1) / DEV_BSIZE; - KdPrint2((PRINT_PREFIX "IdeReadWrite (Chained REQ): Starting sector %#x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n", + KdPrint2((PRINT_PREFIX "IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n", startingSector, AtaReq->TransferLength/2, AtaReq->WordsTransfered, @@ -6119,9 +6172,24 @@ AtaReq->DataBuffer = (PUSHORT)(Srb->DataBuffer); AtaReq->TransferLength = Srb->DataTransferLength; // Set up 1st block. - MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA); - MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks); - KdPrint2((PRINT_PREFIX "IdeReadWrite (Orig REQ): Starting sector %#x, OrigWordsRequested %#x, DevSize %#x\n", + switch(Srb->Cdb[0]) { + case SCSIOP_READ: + case SCSIOP_WRITE: + MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA); + MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks); + break; + case SCSIOP_READ12: + case SCSIOP_WRITE12: + MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA); + MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks); + break; + case SCSIOP_READ16: + case SCSIOP_WRITE16: + MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA); + MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks); + break; + } + KdPrint2((PRINT_PREFIX "IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n", startingSector, AtaReq->TransferLength/2, AtaReq->bcount)); @@ -6134,7 +6202,7 @@ AtaReq->WordsLeft = min(AtaReq->TransferLength - AtaReq->WordsTransfered*2, AtaReq->bcount * DEV_BSIZE) / 2; - KdPrint2((PRINT_PREFIX "IdeReadWrite (REQ): Starting sector is %#x, Number of WORDS %#x, DevSize %#x\n", + KdPrint2((PRINT_PREFIX "IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n", startingSector, AtaReq->WordsLeft, AtaReq->bcount)); @@ -6380,11 +6448,11 @@ //ULONG ldev = GET_LDEV(Srb); ULONG DeviceNumber = GET_CDEV(Srb); UCHAR statusByte; - ULONG startingSector; + ULONGLONG startingSector=0; ULONG max_bcount; - ULONG sectors; - ULONG endSector; - USHORT sectorCount; + ULONGLONG sectors; + ULONGLONG endSector; + ULONG sectorCount=0; ULONGLONG lba; LunExt = chan->lun[DeviceNumber]; @@ -6400,18 +6468,30 @@ sectors)); // Get starting sector number from CDB. - MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA); - MOV_DW_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks); + switch(Srb->Cdb[0]) { + case SCSIOP_VERIFY: + MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA); + MOV_SWP_DW2DD(sectorCount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks); + break; + case SCSIOP_VERIFY12: + MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA); + MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks); + break; + case SCSIOP_VERIFY16: + MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA); + MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks); + break; + } KdPrint2((PRINT_PREFIX - "IdeVerify: Starting sector %#x. Number of blocks %#x\n", + "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n", startingSector, sectorCount)); endSector = startingSector + sectorCount; KdPrint2((PRINT_PREFIX - "IdeVerify: Ending sector %#x\n", + "IdeVerify: Ending sector %#I64x\n", endSector)); if (endSector > sectors) { @@ -6421,7 +6501,7 @@ "IdeVerify: Truncating request to %#x blocks\n", sectors - startingSector - 1)); - sectorCount = (USHORT)(sectors - startingSector - 1); + sectorCount = (ULONG)(sectors - startingSector - 1); } else { @@ -6443,7 +6523,7 @@ statusByte = AtaCommand48(deviceExtension, LunExt->Lun, GET_CHANNEL(Srb), IDE_COMMAND_VERIFY, lba, - sectorCount, + (USHORT)sectorCount, 0, ATA_IMMEDIATE); if(!(statusByte & IDE_STATUS_ERROR)) { @@ -6490,6 +6570,7 @@ BOOLEAN dma_reinited = FALSE; BOOLEAN retried = FALSE; ULONG fis_size; + UCHAR FeatureReg=0; LunExt = chan->lun[DeviceNumber]; @@ -6540,6 +6621,18 @@ Cdb->CDB12READWRITE.LBA[3] )); } else + if(ScsiCommand == SCSIOP_WRITE16) { + KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", + Cdb->CDB16READWRITE.LBA[0], + Cdb->CDB16READWRITE.LBA[1], + Cdb->CDB16READWRITE.LBA[2], + Cdb->CDB16READWRITE.LBA[3], + Cdb->CDB16READWRITE.LBA[4], + Cdb->CDB16READWRITE.LBA[5], + Cdb->CDB16READWRITE.LBA[6], + Cdb->CDB16READWRITE.LBA[7] + )); + } else if(ScsiCommand == SCSIOP_MODE_SELECT) { KdPrint(("ModeSelect 6\n")); PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData; @@ -6571,6 +6664,8 @@ case SCSIOP_WRITE: case SCSIOP_READ12: case SCSIOP_WRITE12: + case SCSIOP_READ16: + case SCSIOP_WRITE16: // all right break; default: @@ -6638,6 +6733,13 @@ // check if reorderable switch(Srb->Cdb[0]) { + case SCSIOP_READ16: + case SCSIOP_WRITE16: + + MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks); + MOV_QD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA); + goto GetLba2; + case SCSIOP_READ12: case SCSIOP_WRITE12: @@ -6650,15 +6752,36 @@ MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks); GetLba: MOV_DD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB10.LBA); - +GetLba2: AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD; AtaReq->Flags &= ~REQ_FLAG_RW_MASK; - AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE || Srb->Cdb[0] == SCSIOP_WRITE12) ? + AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE || + Srb->Cdb[0] == SCSIOP_WRITE12 || + Srb->Cdb[0] == SCSIOP_WRITE16) ? REQ_FLAG_WRITE : REQ_FLAG_READ; break; + default: + AtaReq->Flags &= ~REQ_FLAG_RW_MASK; + if(!AtaReq->TransferLength) { + KdPrint((" assume 0-transfer\n")); + } else + if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { + KdPrint((" assume OUT\n")); + AtaReq->Flags |= REQ_FLAG_WRITE; + } else + if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) { + KdPrint((" assume IN\n")); + AtaReq->Flags |= REQ_FLAG_READ; + } + break; } // check if DMA read/write + if(deviceExtension->HwFlags & UNIATA_SATA) { + // DEBUG !!!! for TEST ONLY + KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (ahci)\n")); + use_dma = TRUE; + } else if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) { KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n")); } else @@ -6667,6 +6790,7 @@ switch(Srb->Cdb[0]) { case SCSIOP_WRITE: case SCSIOP_WRITE12: + case SCSIOP_WRITE16: case SCSIOP_SEND: if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) break; @@ -6674,6 +6798,7 @@ case SCSIOP_RECEIVE: case SCSIOP_READ: case SCSIOP_READ12: + case SCSIOP_READ16: if(deviceExtension->opt_AtapiDmaReadWrite) { call_dma_setup: @@ -6734,8 +6859,13 @@ if(deviceExtension->HwFlags & UNIATA_AHCI) { + UniataAhciSetupCmdPtr(AtaReq); + if(!Srb->DataTransferLength) { + KdPrint2((PRINT_PREFIX "zero-transfer\n")); + use_dma = FALSE; + } else if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, (PUCHAR)(AtaReq->DataBuffer), Srb->DataTransferLength)) { @@ -6744,18 +6874,25 @@ } if(!use_dma) { AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; + } else { + FeatureReg |= ATA_F_DMA; + if(LunExt->IdentifyData.AtapiDMA.DMADirRequired && + (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) { + FeatureReg |= ATA_F_DMAREAD; + } } KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n")); - RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis)); - RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, 16); + // this is done in UniataAhciSetupFIS_H2D() + //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis)); + RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, Srb->CdbLength); fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel, &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]), IDE_COMMAND_ATAPI_PACKET /* command */, 0 /* lba */, (Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength), - use_dma ? ATA_F_DMA : 0/* feature */ + FeatureReg/* feature */ ); if(!fis_size) { @@ -6764,16 +6901,10 @@ } AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0, - ((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) | + ((Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) ? ATA_AHCI_CMD_WRITE : 0) | (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH), fis_size, DeviceNumber); -#if 0 - AtaReq->ahci.io_cmd_flags = (USHORT)(((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) | - /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/ - (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) | - (fis_size / sizeof(ULONG)) | - (DeviceNumber << 12)); -#endif + KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags)); } @@ -6805,7 +6936,7 @@ KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n")); } - if((Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) /*&& !(deviceExtension->HwFlags & UNIATA_AHCI)*/) { + if((Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) && !(deviceExtension->HwFlags & UNIATA_SATA)) { KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n")); use_dma = FALSE; AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; @@ -6826,7 +6957,7 @@ KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer\n")); use_dma = FALSE; AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; - if(!deviceExtension->opt_AtapiDmaZeroTransfer) { + if(!deviceExtension->opt_AtapiDmaZeroTransfer && !(deviceExtension->HwFlags & UNIATA_SATA)) { KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() to PIO\n")); AtapiDmaReinit(deviceExtension, LunExt, AtaReq); } @@ -7003,9 +7134,16 @@ KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n", statusByte)); - AtapiWritePort1(chan, IDX_IO1_o_Feature, - use_dma ? ATA_F_DMA : 0); + if(use_dma) { + FeatureReg |= ATA_F_DMA; + if(LunExt->IdentifyData.AtapiDMA.DMADirRequired && + (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) { + FeatureReg |= ATA_F_DMAREAD; + } + } + AtapiWritePort1(chan, IDX_IO1_o_Feature, FeatureReg); + // Write transfer byte count to registers. byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF); byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8); @@ -7153,6 +7291,7 @@ UCHAR statusByte,errorByte; ULONG status; ULONG i; + ULONGLONG lba; PMODE_PARAMETER_HEADER modeData; //ULONG ldev; ULONG DeviceNumber; @@ -7196,27 +7335,39 @@ if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER) AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER; + cdb = (PCDB)(Srb->Cdb); + if(CmdAction == CMD_ACTION_PREPARE) { switch (Srb->Cdb[0]) { + case SCSIOP_SERVICE_ACTION16: + if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) { + // ok + } else { + goto default_no_prep; + } #ifdef NAVO_TEST case SCSIOP_INQUIRY: // now it requires device access #endif //NAVO_TEST case SCSIOP_READ_CAPACITY: case SCSIOP_READ: case SCSIOP_WRITE: + case SCSIOP_READ12: + case SCSIOP_WRITE12: + case SCSIOP_READ16: + case SCSIOP_WRITE16: case SCSIOP_REQUEST_SENSE: // all right KdPrint2((PRINT_PREFIX "** Ide: Command continue prep\n")); SetCheckPoint(50); break; default: +default_no_prep: SetCheckPoint(0); KdPrint2((PRINT_PREFIX "** Ide: Command break prep\n")); return SRB_STATUS_BUSY; } } - cdb = (PCDB)(Srb->Cdb); SetCheckPoint(0x100 | Srb->Cdb[0]); switch (Srb->Cdb[0]) { case SCSIOP_INQUIRY: @@ -7427,6 +7578,7 @@ // Claim 512 byte blocks (big-endian). //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000; i = DEV_BSIZE; + RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY_DATA)); MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i ); // Calculate last sector. @@ -7454,7 +7606,48 @@ status = SRB_STATUS_SUCCESS; break; + case SCSIOP_SERVICE_ACTION16: + + if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) { + KdPrint2((PRINT_PREFIX + "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n", + Srb->PathId, Srb->Lun, Srb->TargetId)); + // Claim 512 byte blocks (big-endian). + //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000; + i = DEV_BSIZE; + RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY16_DATA)); + MOV_DD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->BytesPerBlock, i ); + + // Calculate last sector. + if(!(lba = LunExt->NumOfSectors)) { + lba = LunExt->IdentifyData.SectorsPerTrack * + LunExt->IdentifyData.NumberOfHeads * + LunExt->IdentifyData.NumberOfCylinders; + } + i--; + + //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress = + // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) | + // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3]; + + MOV_QD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->LogicalBlockAddress, i ); + + KdPrint2((PRINT_PREFIX + "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n", + Srb->TargetId, + LunExt->IdentifyData.SectorsPerTrack, + LunExt->IdentifyData.NumberOfHeads, + LunExt->IdentifyData.NumberOfCylinders)); + + status = SRB_STATUS_SUCCESS; + } else { + goto default_abort; + } + break; + case SCSIOP_VERIFY: + case SCSIOP_VERIFY12: + case SCSIOP_VERIFY16: KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n", @@ -7465,13 +7658,19 @@ case SCSIOP_READ: case SCSIOP_WRITE: + case SCSIOP_READ12: + case SCSIOP_WRITE12: + case SCSIOP_READ16: + case SCSIOP_WRITE16: KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n", (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ", Srb->PathId, Srb->Lun, Srb->TargetId)); AtaReq->Flags &= ~REQ_FLAG_RW_MASK; - AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE) ? REQ_FLAG_WRITE : REQ_FLAG_READ; + AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE || + Srb->Cdb[0] == SCSIOP_WRITE12 || + Srb->Cdb[0] == SCSIOP_WRITE16) ? REQ_FLAG_WRITE : REQ_FLAG_READ; status = IdeReadWrite(HwDeviceExtension, Srb, CmdAction); break; @@ -7717,7 +7916,7 @@ } default: - +default_abort: KdPrint2((PRINT_PREFIX "IdeSendCommand: Unsupported command %#x\n", Srb->Cdb[0])); @@ -8128,6 +8327,9 @@ break; //} } + } else { + KdPrint2((PRINT_PREFIX + " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb, &(Srb->Cdb), Srb->SrbExtension, Srb->Cdb[0])); } /* __try { @@ -8177,7 +8379,7 @@ } else { // Send command to device. - KdPrint2((PRINT_PREFIX "Send to device\n")); + KdPrint2((PRINT_PREFIX "Send to device %x\n", Srb->Cdb[0])); if(TopLevel) { KdPrint2((PRINT_PREFIX "TopLevel (2), srb %#x\n", Srb)); AtaReq = (PATA_REQ)(Srb->SrbExtension); @@ -8216,7 +8418,7 @@ if(atapiDev && (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) { - KdPrint3((PRINT_PREFIX "Try ATAPI send\n")); + KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0])); status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL); } else { KdPrint2((PRINT_PREFIX "Try IDE send\n")); @@ -9526,7 +9728,8 @@ hwInitializationData.comm.DeviceIdLength = 0; if(!BMListLen) { - hwInitializationData.comm.SrbExtensionSize = FIELD_OFFSET(ATA_REQ, ata); + hwInitializationData.comm.SrbExtensionSize = //FIELD_OFFSET(ATA_REQ, ata); + sizeof(ATA_REQ); KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", hwInitializationData.comm.SrbExtensionSize)); } @@ -9904,7 +10107,9 @@ status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/, paramPath.Buffer, parameters, NULL, NULL); - KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun)); + if(NT_SUCCESS(status)) { + KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun)); + } ExFreePool(paramPath.Buffer); Index: drivers/storage/ide/uniata/id_dma.cpp =================================================================== --- drivers/storage/ide/uniata/id_dma.cpp (revision 57044) +++ drivers/storage/ide/uniata/id_dma.cpp (working copy) @@ -803,7 +803,8 @@ IN PHW_LU_EXTENSION LunExt ) { - if(LunExt->IdentifyData.SupportDma) { + if(LunExt->IdentifyData.SupportDma || + (LunExt->IdentifyData.AtapiDMA.DMASupport && (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE))) { KdPrint2((PRINT_PREFIX "AtapiDmaInit__: Set (U)DMA on Device %d\n", LunExt->Lun)); /* for(i=AtaUmode(&(LunExt->IdentifyData)); i>=0; i--) { Index: drivers/storage/ide/uniata/id_init.cpp =================================================================== --- drivers/storage/ide/uniata/id_init.cpp (revision 57044) +++ drivers/storage/ide/uniata/id_init.cpp (working copy) @@ -2368,11 +2368,14 @@ KdPrint2((PRINT_PREFIX "Achtung !deviceExtension->NumberLuns \n")); deviceExtension->NumberLuns = IDE_MAX_LUN_PER_CHAN; } + KdPrint2((PRINT_PREFIX " Chan %#x\n", chan)); chan->DeviceExtension = deviceExtension; chan->lChannel = c; chan->NumberLuns = deviceExtension->NumberLuns; for(i=0; iNumberLuns; i++) { chan->lun[i] = &(deviceExtension->lun[c*deviceExtension->NumberLuns+i]); + KdPrint2((PRINT_PREFIX " Lun %#x\n", i)); + KdPrint2((PRINT_PREFIX " Lun ptr %#x\n", chan->lun[i])); } chan->AltRegMap = deviceExtension->AltRegMap; chan->NextDpcChan = -1; @@ -2403,7 +2406,7 @@ PHW_LU_EXTENSION old_luns = NULL; PHW_CHANNEL old_chans = NULL; - KdPrint2((PRINT_PREFIX "allocate %d Luns for %d channels\n", deviceExtension->lun, deviceExtension->NumberChannels)); + KdPrint2((PRINT_PREFIX "allocate %d Luns for %d channels\n", deviceExtension->NumberLuns, deviceExtension->NumberChannels)); old_luns = deviceExtension->lun; old_chans = deviceExtension->chan; Index: drivers/storage/ide/uniata/id_probe.cpp =================================================================== --- drivers/storage/ide/uniata/id_probe.cpp (revision 57044) +++ drivers/storage/ide/uniata/id_probe.cpp (working copy) @@ -1385,11 +1385,11 @@ KdPrint2((PRINT_PREFIX "update ConfigInfo->nt4\n")); _ConfigInfo->nt4.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); _ConfigInfo->nt4.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION); - if(deviceExtension->HwFlags & UNIATA_AHCI) { + //if(deviceExtension->HwFlags & UNIATA_AHCI) { _ConfigInfo->nt4.SrbExtensionSize = sizeof(ATA_REQ); - } else { - _ConfigInfo->nt4.SrbExtensionSize = FIELD_OFFSET(ATA_REQ, dma_tab) + sizeof(BM_DMA_ENTRY)*ATA_DMA_ENTRIES; - } + //} else { + // _ConfigInfo->nt4.SrbExtensionSize = FIELD_OFFSET(ATA_REQ, dma_tab) + sizeof(BM_DMA_ENTRY)*ATA_DMA_ENTRIES; + //} KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", _ConfigInfo->nt4.SrbExtensionSize)); } if((WinVer_Id() > WinVer_2k) || Index: drivers/storage/ide/uniata/id_sata.cpp =================================================================== --- drivers/storage/ide/uniata/id_sata.cpp (revision 57044) +++ drivers/storage/ide/uniata/id_sata.cpp (working copy) @@ -772,13 +772,23 @@ CAP2 = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP2); KdPrint2((PRINT_PREFIX " AHCI CAP %#x, CAP2 %#x\n", CAP, CAP2)); if(CAP & AHCI_CAP_S64A) { - KdPrint2((PRINT_PREFIX " AHCI 64bit\n")); + KdPrint2((PRINT_PREFIX " 64bit")); //deviceExtension->Host64 = TRUE; } if(CAP2 & AHCI_CAP2_BOH) { BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC); - KdPrint2((PRINT_PREFIX " AHCI BOHC %#x\n", BOHC)); + KdPrint2((PRINT_PREFIX " BOHC %#x", BOHC)); } + if(CAP & AHCI_CAP_NCQ) { + KdPrint2((PRINT_PREFIX " NCQ")); + } + if(CAP & AHCI_CAP_SNTF) { + KdPrint2((PRINT_PREFIX " SNTF")); + } + if(CAP & AHCI_CAP_CCC) { + KdPrint2((PRINT_PREFIX " CCC")); + } + KdPrint2((PRINT_PREFIX "\n")); /* get the number of HW channels */ PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI); @@ -787,6 +797,7 @@ NumberChannels = max((CAP & AHCI_CAP_NOP_MASK)+1, n); + KdPrint2((PRINT_PREFIX " CommandSlots %d\n", (CAP & AHCI_CAP_NCS_MASK)>>8 )); KdPrint2((PRINT_PREFIX " Channels %d\n", n)); switch(deviceExtension->DevID) { @@ -871,7 +882,7 @@ PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; ULONG Channel = deviceExtension->Channel + lChannel; ULONG hIS; - ULONG CI; + ULONG CI, ACT; AHCI_IS_REG IS; SATA_SSTATUS_REG SStatus; SATA_SERROR_REG SError; @@ -888,6 +899,7 @@ } IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI); + ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT); SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus); SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError); @@ -896,8 +908,8 @@ UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg); AtapiWritePort4(chan, IDX_SATA_SError, SError.Reg); - KdPrint((" AHCI: istatus=%08x sstatus=%08x serror=%08x CI=%08x\n", - IS.Reg, SStatus.Reg, SError.Reg, CI)); + KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n", + IS.Reg, SStatus.Reg, SError.Reg, CI, ACT)); /* do we have cold connect surprise */ if(IS.CPDS) { @@ -1059,6 +1071,7 @@ ) { AHCI_IS_REG IS; + //ULONG ACT; ULONG CI=0; ULONG i; ULONG SError; @@ -1068,7 +1081,8 @@ for (i=0; i> tag) & 0x01)) { + //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT); + if (!(( CI >> tag) & 0x01)) { break; } IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); @@ -1146,6 +1160,7 @@ KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK)); } + //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag); UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 1 << tag); return UniataAhciWaitCommandReady(chan, timeout); @@ -1269,6 +1284,28 @@ } // end UniataAhciSendPIOCommand() +BOOLEAN +NTAPI +UniataAhciAbortOperation( + IN PHW_CHANNEL chan + ) +{ + /* kick controller into sane state */ + if(!UniataAhciStop(chan)) { + return FALSE; + } + if(!UniataAhciStopFR(chan)) { + return FALSE; + } + if(!UniataAhciCLO(chan)) { + return FALSE; + } + UniataAhciStartFR(chan); + UniataAhciStart(chan); + + return TRUE; +} // end UniataAhciAbortOperation() + ULONG NTAPI UniataAhciSoftReset( @@ -1290,19 +1327,12 @@ PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); -#ifdef DBG -// UniataDumpAhciPortRegs(chan); -#endif // DBG - /* kick controller into sane state */ - UniataAhciStop(chan); - UniataAhciCLO(chan); - UniataAhciStart(chan); + if(!UniataAhciAbortOperation(chan)) { + KdPrint2((" abort failed\n")); + return (ULONG)(-1); + } -#ifdef DBG -// UniataDumpAhciPortRegs(chan); -#endif // DBG - /* pull reset active */ RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; @@ -1523,7 +1553,7 @@ return; } // end UniataAhciStartFR() -VOID +BOOLEAN NTAPI UniataAhciStopFR( IN PHW_CHANNEL chan @@ -1542,14 +1572,14 @@ CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); if(!(CMD & ATA_AHCI_P_CMD_FR)) { KdPrint2((" final CMD %#x\n", CMD)); - return; + return TRUE; } AtapiStallExecution(1000); } KdPrint2((" CMD %#x\n", CMD)); KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError))); KdPrint2(("UniataAhciStopFR: timeout\n")); - return; + return FALSE; } // end UniataAhciStopFR() VOID @@ -1582,7 +1612,7 @@ return; } // end UniataAhciStart() -VOID +BOOLEAN NTAPI UniataAhciCLO( IN PHW_CHANNEL chan @@ -1600,7 +1630,7 @@ //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); CAP = chan->DeviceExtension->AHCI_CAP; if(!(CAP & AHCI_CAP_SCLO)) { - return; + return TRUE; } KdPrint2((" send CLO\n")); CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); @@ -1611,16 +1641,16 @@ CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); if(!(CMD & ATA_AHCI_P_CMD_CLO)) { KdPrint2((" final CMD %#x\n", CMD)); - return; + return TRUE; } AtapiStallExecution(1000); } KdPrint2((" CMD %#x\n", CMD)); KdPrint2(("UniataAhciCLO: timeout\n")); - return; + return FALSE; } // end UniataAhciCLO() -VOID +BOOLEAN NTAPI UniataAhciStop( IN PHW_CHANNEL chan @@ -1641,14 +1671,14 @@ CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); if(!(CMD & ATA_AHCI_P_CMD_CR)) { KdPrint2((" final CMD %#x\n", CMD)); - return; + return TRUE; } AtapiStallExecution(1000); } KdPrint2((" CMD %#x\n", CMD)); KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError))); KdPrint2(("UniataAhciStop: timeout\n")); - return; + return FALSE; } // end UniataAhciStop() UCHAR @@ -1664,7 +1694,7 @@ PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; //ULONG Channel = deviceExtension->Channel + lChannel; //ULONG hIS; - ULONG CMD; + ULONG CMD, CMD0; //AHCI_IS_REG IS; PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); //SATA_SSTATUS_REG SStatus; @@ -1712,20 +1742,24 @@ AHCI_CL->cmd_table_phys)); #endif // DBG - CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); + CMD0 = CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); KdPrint2((" CMD %#x\n", CMD)); // switch controller to ATAPI mode for ATA_PACKET commands only if(ATAPI_DEVICE(chan, DeviceNumber) && AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_PACKET) { KdPrint2((" ATAPI\n")); CMD |= ATA_AHCI_P_CMD_ATAPI; + KdDump(&(AtaReq->ahci.ahci_cmd_ptr->acmd), 16); } else { CMD &= ~ATA_AHCI_P_CMD_ATAPI; } - KdPrint2((" send CMD %#x, entries %#x\n", CMD, AHCI_CL->prd_length)); - UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); + if(CMD0 != CMD) { + KdPrint2((" send CMD %#x, entries %#x\n", CMD, AHCI_CL->prd_length)); + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); + } /* issue command to controller */ + //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag); UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 0x01 << tag); chan->AhciPrevCI |= 0x01 << tag; @@ -1770,7 +1804,7 @@ PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; //ULONG Channel = deviceExtension->Channel + lChannel; //ULONG hIS; - ULONG CI; + ULONG CI, ACT; PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); ULONG TFD; PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); @@ -1809,7 +1843,7 @@ ((ULONGLONG)(RCV_FIS[7] & 0x0f) << 24); } AtaReq->WordsTransfered = AHCI_CL->bytecount/2; - +/* if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { KdPrint2(("RCV:\n")); KdDump(RCV_FIS, 24); @@ -1821,18 +1855,20 @@ AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2; } } - +*/ + ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT); CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI); if(CI & (1 << tag)) { // clear CI - KdPrint2((" Incomplete command, CI %#x\n", CI)); + KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI, ACT)); KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS[2], RCV_FIS[3])); #if DBG UniataDumpAhciPortRegs(chan); #endif - UniataAhciStop(chan); - UniataAhciStart(chan); + if(!UniataAhciAbortOperation(chan)) { + KdPrint2((" Abort failed, need RESET\n")); + } #if DBG UniataDumpAhciPortRegs(chan); #endif Index: drivers/storage/ide/uniata/id_sata.h =================================================================== --- drivers/storage/ide/uniata/id_sata.h (revision 57044) +++ drivers/storage/ide/uniata/id_sata.h (working copy) @@ -195,6 +195,12 @@ IN ULONG timeout ); +BOOLEAN +NTAPI +UniataAhciAbortOperation( + IN PHW_CHANNEL chan + ); + ULONG NTAPI UniataAhciSoftReset( @@ -231,7 +237,7 @@ IN PHW_CHANNEL chan ); -VOID +BOOLEAN NTAPI UniataAhciStopFR( IN PHW_CHANNEL chan @@ -243,13 +249,13 @@ IN PHW_CHANNEL chan ); -VOID +BOOLEAN NTAPI UniataAhciCLO( IN PHW_CHANNEL chan ); -VOID +BOOLEAN NTAPI UniataAhciStop( IN PHW_CHANNEL chan Index: drivers/storage/ide/uniata/inc/misc.h =================================================================== --- drivers/storage/ide/uniata/inc/misc.h (revision 57044) +++ drivers/storage/ide/uniata/inc/misc.h (working copy) @@ -8,6 +8,7 @@ #define MOV_DD_SWP(a,b) ((a) = RtlUlongByteSwap(*(PULONG)&(b))) #define MOV_DW_SWP(a,b) ((a) = RtlUshortByteSwap(*(PUSHORT)&(b))) #define MOV_SWP_DW2DD(a,b) ((a) = RtlUshortByteSwap(*(PUSHORT)&(b))) +#define MOV_QD_SWP(a,b) { ((PULONG)&(a))[0] = RtlUlongByteSwap( ((PULONG)&(b))[1]); ((PULONG)&(a))[1] = RtlUlongByteSwap( ((PULONG)&(b))[0]); } #else @@ -37,9 +38,35 @@ /********************/ +typedef void +(__fastcall *ptrMOV_QD_SWP)( + void* a, // ECX + void* b // EDX + ); +extern "C" ptrMOV_QD_SWP _MOV_QD_SWP; + extern "C" void __fastcall +_MOV_QD_SWP_i486( + void* a, // ECX + void* b // EDX + ); + +extern "C" +void +__fastcall +_MOV_QD_SWP_i386( + void* a, // ECX + void* b // EDX + ); +#define MOV_QD_SWP(a,b) _MOV_QD_SWP(&(a),&(b)) + +/********************/ + +extern "C" +void +__fastcall _MOV_DW_SWP( void* a, // ECX void* b // EDX Index: drivers/storage/ide/uniata/scsi.h =================================================================== --- drivers/storage/ide/uniata/scsi.h (revision 57044) +++ drivers/storage/ide/uniata/scsi.h (working copy) @@ -145,6 +145,14 @@ UCHAR Control; } CDB10, *PCDB10; + // Service Action 16-byte CDB + struct _SERVICE_ACTION16 { + UCHAR OperationCode; // 0x9E + UCHAR ServiceAction : 5; + UCHAR Reserved1 : 3; + UCHAR Data[14]; + } SERVICE_ACTION16, *PSERVICE_ACTION16; + // CD Rom Audio CDBs #define PauseResume_Pause 0x00 @@ -723,6 +731,26 @@ UCHAR Reserved1[2]; } CDB12READWRITE, *PCDB12READWRITE; + struct _CDB16READWRITE { + UCHAR OperationCode; + union { + UCHAR Flags; + struct { + UCHAR RELADR : 1; + UCHAR Reserved0 : 2; + UCHAR FUA : 1; + UCHAR DPO : 1; + UCHAR Reserved1 : 3; + } Fields; + } Byte1; + UCHAR LBA [8]; + UCHAR NumOfBlocks [4]; + UCHAR GroupNumber:5; + UCHAR Reserved14_5_6:2; + UCHAR Restricted:1; // MMC-4 + UCHAR Reserved1[1]; + } CDB16READWRITE, *PCDB16READWRITE; + // Plextor Read CD-DA struct _PLXTR_READ_CDDA { UCHAR OperationCode; @@ -866,6 +894,13 @@ #define SCSIOP_CLOSE_TRACK_SESSION 0x5B #define SCSIOP_READ_BUFFER_CAPACITY 0x5C #define SCSIOP_SEND_CUE_SHEET 0x5D +#define SCSIOP_READ16 0x88 +#define SCSIOP_WRITE16 0x8A +#define SCSIOP_VERIFY16 0x8F +#define SCSIOP_SERVICE_ACTION16 0x9E + + #define SCSIOP_SA_READ_CAPACITY16 0x10 + #define SCSIOP_BLANK 0xA1 #define SCSIOP_SEND_KEY 0xA3 #define SCSIOP_REPORT_KEY 0xA4 @@ -874,6 +909,7 @@ #define SCSIOP_SET_READ_AHEAD 0xA7 #define SCSIOP_READ12 0xA8 #define SCSIOP_WRITE12 0xAA +#define SCSIOP_VERIFY12 0xAF #define SCSIOP_SEEK12 0xAB #define SCSIOP_GET_PERFORMANCE 0xAC #define SCSIOP_READ_DVD_STRUCTURE 0xAD @@ -1365,6 +1401,15 @@ ULONG BytesPerBlock; } READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA; +typedef struct _READ_CAPACITY16_DATA { + ULONGLONG LogicalBlockAddress; + ULONG BytesPerBlock; + UCHAR Prot_EN:1; + UCHAR RTO_EN:1; + UCHAR Reserved:6; + UCHAR Reserved1[20]; +} READ_CAPACITY16_DATA, *PREAD_CAPACITY16_DATA; + // CD ROM Read Table Of Contents (TOC) structures // Format 0 - Get table of contents Index: drivers/storage/ide/uniata/uniata_ver.h =================================================================== --- drivers/storage/ide/uniata/uniata_ver.h (revision 57044) +++ drivers/storage/ide/uniata/uniata_ver.h (working copy) @@ -1,10 +1,10 @@ -#define UNIATA_VER_STR "42e2" -#define UNIATA_VER_DOT 0.42.5.2 +#define UNIATA_VER_STR "42h" +#define UNIATA_VER_DOT 0.42.8.0 #define UNIATA_VER_MJ 0 #define UNIATA_VER_MN 42 -#define UNIATA_VER_SUB_MJ 5 -#define UNIATA_VER_SUB_MN 2 -#define UNIATA_VER_DOT_COMMA 0,42,5,2 -#define UNIATA_VER_DOT_STR "0.42.5.2" +#define UNIATA_VER_SUB_MJ 8 +#define UNIATA_VER_SUB_MN 0 +#define UNIATA_VER_DOT_COMMA 0,42,8,0 +#define UNIATA_VER_DOT_STR "0.42.8.0" #define UNIATA_VER_YEAR 2012 #define UNIATA_VER_YEAR_STR "2012"