/*++
-Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2014 Alexandr A. Telyatnikov (Alter)
Module Name:
id_ata.cpp
Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
Søren Schmidt, Copyright (c) 1998-2007
- All parts of code are greatly changed/updated by
- Alter, Copyright (c) 2002-2007:
+ All parts of code are significantly changed/updated by
+ Alter, Copyright (c) 2002-2014:
1. Internal command queueing/reordering
2. Drive identification
5. W2k support (binary compatibility)
6. HDD hot swap under NT4
7. XP support (binary compatibility)
- 8. Serial ATA (SATA/SATA2) support
+ 8. Serial ATA (SATA/SATA2/SATA3) support
9. NT 3.51 support (binary compatibility)
etc. (See todo.txt)
IN ULONG lChannel
);
+VOID
+NTAPI
+UniataUserDeviceReset(
+ PHW_DEVICE_EXTENSION deviceExtension,
+ PHW_LU_EXTENSION LunExt,
+ ULONG lChannel
+ );
+
#define RESET_COMPLETE_CURRENT 0x00
#define RESET_COMPLETE_ALL 0x01
#define RESET_COMPLETE_NONE 0x02
UCHAR statusByte;
ULONG i;
+ // Assume, proper drive is already seleted
WaitOnBusyLong(chan);
for (i = 0; i < 0x10000; i++) {
}
} else {
AtapiStallExecution(500);
+ GetBaseStatus(chan, statusByte2);
AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
- AtapiStallExecution(30);
- // Wait for BUSY assertion, in some cases delay may occure
- while (!(AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
- i--)
- {
- AtapiStallExecution(30);
+ // Do not wait for BUSY assertion if it was initially set, jump to
+ // BUSY release wait loop
+ if(!(statusByte2 & IDE_STATUS_BUSY)) {
+ // Wait for BUSY assertion, in some cases delay may occure
+ // 100ms should be enough
+ i = 10*1000;
+ while (!(AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
+ i--)
+ {
+ AtapiStallExecution(10);
+ }
}
+ i = 30 * 1000;
// ReactOS modification: Already stop looping when we know that the drive has finished resetting.
// Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
// the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
} // end UniataDumpATARegs()
#endif
+VOID
+NTAPI
+UniataSnapAtaRegs(
+ IN PHW_CHANNEL chan,
+ IN ULONG DeviceNumber,
+ IN OUT PIDEREGS_EX regs
+ )
+{
+ if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
+ // AHCI
+ UniataAhciSnapAtaRegs(chan, DeviceNumber, regs);
+ } else {
+ // SATA/PATA, assume drive is selected
+ ULONG j;
+ UCHAR statusByteAlt;
+
+ if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {
+ for(j=IDX_IO1_i_Error; j<=IDX_IO1_i_Status; j++) {
+ statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
+ ((PUCHAR)regs)[j-1] = statusByteAlt;
+ }
+ regs->bOpFlags = 0;
+ } else {
+ regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
+ for(j=IDX_IO1_i_Error; j<IDX_IO1_i_DriveSelect; j++) {
+ statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
+ ((PUCHAR)regs)[j-1] = statusByteAlt;
+ statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
+ ((PUCHAR)regs)[j+8-1] = statusByteAlt;
+ }
+ regs->bCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status);
+ }
+ }
+ return;
+} // end UniataSnapAtaRegs()
+
/*++
Routine Description:
ULONG waitCount = 50000;
ULONG j;
UCHAR statusByte;
- UCHAR statusByte2;
+ //UCHAR statusByte2;
UCHAR signatureLow,
signatureHigh;
BOOLEAN atapiDev = FALSE;
AtapiStallExecution(10);
statusByte = WaitOnBusyLong(chan);
// Check that the status register makes sense.
- GetBaseStatus(chan, statusByte2);
+ GetBaseStatus(chan, statusByte);
}
if (Command == IDE_COMMAND_IDENTIFY) {
}
} while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
- GetBaseStatus(chan, statusByte2);
+ GetBaseStatus(chan, statusByte);
SelectDrive(chan, DeviceNumber);
} else {
- GetBaseStatus(chan, statusByte2);
+ GetBaseStatus(chan, statusByte);
}
// Another check for signature, to deal with one model Atapi that doesn't assert signature after
// a soft reset.
break;
}
}
- // Device didn't respond correctly. It will be given one more chances.
+ // Device didn't respond correctly. It will be given one more chance.
KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error)));
GetBaseStatus(chan, statusByte);
if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
-#if 0
- USHORT w;
- ULONG i;
+
// ATI/SII chipsets with memory-mapped IO hangs when
// I call ReadBuffer(), probably due to PCI burst/prefetch enabled
- // Unfortunately, I don't know yet how to workaround it except the way you see below.
- KdPrint2((PRINT_PREFIX
- " IO_%#x (%#x), %s:\n",
- IDX_IO1_i_Data,
- chan->RegTranslation[IDX_IO1_i_Data].Addr,
- chan->RegTranslation[IDX_IO1_i_Data].MemIo ? "Mem" : "IO"));
- for(i=0; i<256; i++) {
- /*
- KdPrint2((PRINT_PREFIX
- " IO_%#x (%#x):\n",
- IDX_IO1_i_Data,
- chan->RegTranslation[IDX_IO1_i_Data].Addr));
- */
- w = AtapiReadPort2(chan, IDX_IO1_i_Data);
- KdPrint2((PRINT_PREFIX
- " %x\n", w));
- AtapiStallExecution(1);
- ((PUSHORT)&deviceExtension->FullIdentifyData)[i] = w;
- }
-#else
+ // Unfortunately, I don't know yet how to workaround it except
+ // spacifying manual delay in the way you see below.
ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
-#endif
+
// Work around for some IDE and one model Atapi that will present more than
// 256 bytes for the Identify data.
KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive));
KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive));
if(deviceExtension->FullIdentifyData.UdmaModesValid) {
- KdPrint2((PRINT_PREFIX "UDMA: %x\n", deviceExtension->FullIdentifyData.UltraDMAActive));
+ KdPrint2((PRINT_PREFIX "UDMA: %x/%x\n", deviceExtension->FullIdentifyData.UltraDMAActive, deviceExtension->FullIdentifyData.UltraDMASupport));
}
KdPrint2((PRINT_PREFIX "SATA: %x\n", deviceExtension->FullIdentifyData.SataEnable));
KdPrint2((PRINT_PREFIX "SATA support: %x, CAPs %#x\n",
LunExt->LimitedTransferMode =
LunExt->OrigTransferMode =
- (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData));
-
- KdPrint2((PRINT_PREFIX "OrigTransferMode: %x\n", LunExt->OrigTransferMode));
+ (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_MAX);
+ LunExt->TransferMode =
+ (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_ACTIVE);
+
+ KdPrint2((PRINT_PREFIX "OrigTransferMode: %x, Active: %x\n", LunExt->OrigTransferMode, LunExt->TransferMode));
+ KdPrint2((PRINT_PREFIX "Accoustic %d, cur %d\n",
+ deviceExtension->FullIdentifyData.VendorAcoustic,
+ deviceExtension->FullIdentifyData.CurrentAcoustic
+ ));
+ KdPrint2((PRINT_PREFIX "AdvPowerMode %d, cur %d\n",
+ deviceExtension->FullIdentifyData.CfAdvPowerMode
+ ));
// Check out a few capabilities / limitations of the device.
if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
}
}
}
- KdPrint2((PRINT_PREFIX "final LunExt->opt_GeomType=%x\n", LunExt->opt_GeomType));
if(LunExt->opt_GeomType == GEOM_STD) {
deviceExtension->FullIdentifyData.CurrentSectorsPerTrack =
PHW_LU_EXTENSION LunExt
)
{
+ // keep only DFLAGS_HIDDEN flag
LunExt->DeviceFlags &= DFLAGS_HIDDEN;
LunExt->AtapiReadyWaitDelay = 0;
} // end UniataForgetDevice()
Routine Description:
Reset IDE controller and/or Atapi device.
+ ->HwResetBus
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
} // end AtapiResetController()
-
BOOLEAN
NTAPI
AtapiResetController__(
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
+ for (i = 0; i < MaxLuns; i++) {
+ chan->lun[i]->PowerState = 0;
+ }
// Reset controller
if(ChipFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX " AHCI path\n"));
-#if DBG
- UniataDumpAhciPortRegs(chan);
+ if(UniataAhciChanImplemented(deviceExtension, j)) {
+#ifdef _DEBUG
+ UniataDumpAhciPortRegs(chan);
#endif
- AtapiDisableInterrupts(deviceExtension, j);
- UniataAhciReset(HwDeviceExtension, j);
+ AtapiDisableInterrupts(deviceExtension, j);
+ UniataAhciReset(HwDeviceExtension, j);
+ } else {
+ KdPrint2((PRINT_PREFIX " skip not implemented\n"));
+ }
} else {
KdPrint2((PRINT_PREFIX " ATA path, chan %#x\n", chan));
KdPrint2((PRINT_PREFIX " disable intr (0)\n"));
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
+ ->HwInitialize
Return Value:
TRUE - if initialization successful.
if(WinVer_WDM_Model) {
AtapiResetController__(HwDeviceExtension, CHAN_NOT_SPECIFIED, RESET_COMPLETE_ALL);
}
+ if(deviceExtension->MasterDev) {
+ KdPrint2((PRINT_PREFIX " mark chan %d of master controller [%x] as inited\n",
+ deviceExtension->Channel, deviceExtension->DevIndex));
+ BMList[deviceExtension->DevIndex].ChanInitOk |= 0x01 << deviceExtension->Channel;
+ }
/* do extra chipset specific setups */
AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
// ULONG tmp32;
ULONG PreferedMode = 0xffffffff;
+ if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+ !UniataAhciChanImplemented(deviceExtension, lChannel)) {
+ return;
+ }
+
AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
FindDevices(deviceExtension, 0, lChannel);
KdPrint2((PRINT_PREFIX " Disable Write Cache\n"));
statusByte = AtaCommand(deviceExtension, i, lChannel,
IDE_COMMAND_SET_FEATURES, 0, 0, 0,
- 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
+ 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
}
+
+ if(LunExt->IdentifyData.FeaturesSupport.PowerMngt ||
+ LunExt->IdentifyData.FeaturesSupport.APM) {
+
+ if(LunExt->opt_AdvPowerMode) {
+ KdPrint2((PRINT_PREFIX " Try Enable Adv. Power Mgmt\n"));
+ // setup APM
+ statusByte = AtaCommand(deviceExtension, i, lChannel,
+ IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+ LunExt->opt_AdvPowerMode, ATA_C_F_ENAB_APM, ATA_WAIT_BASE_READY);
+ // Check for errors.
+ if (statusByte & IDE_STATUS_ERROR) {
+ KdPrint2((PRINT_PREFIX
+ "AtapiHwInitialize: Enable APM on Device %d failed\n",
+ i));
+ }
+ } else {
+ KdPrint2((PRINT_PREFIX " Disable Adv. Power Mgmt\n"));
+ statusByte = AtaCommand(deviceExtension, i, lChannel,
+ IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+ 0, ATA_C_F_DIS_APM, ATA_WAIT_BASE_READY);
+ }
+ }
+ if(LunExt->IdentifyData.FeaturesSupport.AutoAcoustic) {
+ if(LunExt->opt_AcousticMode) {
+ KdPrint2((PRINT_PREFIX " Try Enable Acoustic Mgmt\n"));
+ // setup acoustic mgmt
+ statusByte = AtaCommand(deviceExtension, i, lChannel,
+ IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+ LunExt->opt_AcousticMode, ATA_C_F_ENAB_ACOUSTIC, ATA_WAIT_BASE_READY);
+ // Check for errors.
+ if (statusByte & IDE_STATUS_ERROR) {
+ KdPrint2((PRINT_PREFIX
+ "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
+ i));
+ }
+ } else {
+ KdPrint2((PRINT_PREFIX " Disable Acoustic Mgmt\n"));
+ statusByte = AtaCommand(deviceExtension, i, lChannel,
+ IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+ 0, ATA_C_F_DIS_ACOUSTIC, ATA_WAIT_BASE_READY);
+ }
+ }
+ if(LunExt->IdentifyData.FeaturesSupport.Standby) {
+ KdPrint2((PRINT_PREFIX " Try init standby timer: %d\n"));
+ // setup standby timer
+ statusByte = AtaCommand(deviceExtension, i, lChannel,
+ IDE_COMMAND_IDLE, 0, 0, 0,
+ LunExt->opt_StandbyTimer, 0, ATA_WAIT_BASE_READY);
+ // Check for errors.
+ if (statusByte & IDE_STATUS_ERROR) {
+ KdPrint2((PRINT_PREFIX
+ "AtapiHwInitialize: standby timer on Device %d failed\n",
+ i));
+ }
+ }
}
} else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){
ULONG j;
- BOOLEAN isSanyo = FALSE;
+ //BOOLEAN isSanyo = FALSE;
CCHAR vendorId[26];
KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n"));
// acting like 1) a multi-lun device and 2) building the 'special' TUR's.
LunExt->DeviceFlags |= (DFLAGS_CHANGER_INITED | DFLAGS_SANYO_ATAPI_CHANGER);
LunExt->DiscsPresent = 3;
- isSanyo = TRUE;
+ //isSanyo = TRUE;
}
}
}
if(!hIS) {
return FALSE;
}
- checked = ~hIS; // assume all non-interrupted ports to be already checked
+ // assume all non-interrupted ports to be already checked
+ checked = ~hIS;
+ // assume all not implemented ports to be already checked
+ checked |= ~deviceExtension->AHCI_PI;
} else {
checked = 0; // assume all ports are not checked
}
if(!hIS) {
return FALSE;
}
- checked = ~hIS; // assume all non-interrupted ports to be already checked
+ // assume all non-interrupted ports to be already checked
+ checked = ~hIS;
+ // assume all not implemented ports to be already checked
+ checked |= ~deviceExtension->AHCI_PI;
+
} else {
checked = 0; // assume all ports are not checked
}
KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c));
return;
}
+ if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+ !UniataAhciChanImplemented(deviceExtension, c)) {
+ KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c));
+ return;
+ }
+
chan = &(deviceExtension->chan[c]);
KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr));
if(!InterlockedDecrement(&chan->DisableIntr)) {
if((ChipFlags & UNIATA_AHCI) &&
UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
+
+ if(!UniataAhciChanImplemented(deviceExtension, lChannel)) {
+ return OurInterrupt;
+ }
+
OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
if((OurInterrupt == INTERRUPT_REASON_UNEXPECTED) &&
(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
return INTERRUPT_REASON_IGNORE;
}
break;
- case PRMIO:
- status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x0040);
- if(ChipFlags & PRSATA) {
- pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c);
- AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c, pr_status & 0x000000ff);
+ case PRMIO: {
+ ULONG stat_reg = (ChipFlags & PRG2) ? 0x60 : 0x6c;
+ status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40);
+ AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40, status);
+
+ if(status & (1 << (Channel+1))) {
+ // our
+ } else {
+ KdPrint2((PRINT_PREFIX " Promise mio unexpected\n"));
+ return INTERRUPT_REASON_IGNORE;
}
+
+ if(!(ChipFlags & UNIATA_SATA))
+ break;
+
+ pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg);
+ AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg, (pr_status & (0x11 << Channel)));
if(pr_status & (0x11 << Channel)) {
// TODO: reset channel
KdPrint2((PRINT_PREFIX " Promise mio unexpected + reset req\n"));
- return INTERRUPT_REASON_IGNORE;
+ UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
}
if(!(status & (0x01 << Channel))) {
- KdPrint2((PRINT_PREFIX " Promise mio unexpected\n"));
+ // Connect event
+ KdPrint2((PRINT_PREFIX " Promise mio unexpected attach\n"));
+ UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0);
+ }
+ if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
+ OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
+ } else {
return INTERRUPT_REASON_IGNORE;
}
+
AtapiWritePort4(chan, IDX_BM_DeviceSpecific0, 0x00000001);
- break;
+ break; }
}
break; }
case ATA_NVIDIA_ID: {
KdPrint2((PRINT_PREFIX " OurInterrupt = %d\n", OurInterrupt));
return OurInterrupt;
}
- interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
+ interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
KdPrint3((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason));
return OurInterrupt;
}
BOOLEAN atapiDev = FALSE;
+#ifdef DBG
UCHAR Channel;
+#endif //DBG
UCHAR lChannel;
UCHAR DeviceNumber;
BOOLEAN DmaTransfer = FALSE;
// BOOLEAN RestoreUseDpc = FALSE;
BOOLEAN DataOverrun = FALSE;
BOOLEAN NoStartIo = TRUE;
+ BOOLEAN NoRetry = FALSE;
KdPrint2((PRINT_PREFIX "AtapiInterrupt:\n"));
if(InDpc) {
PHW_LU_EXTENSION LunExt;
lChannel = c;
+
+#ifdef DBG
Channel = (UCHAR)(deviceExtension->Channel + lChannel);
KdPrint2((PRINT_PREFIX " cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c));
+#endif //DBG
if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
(AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ||
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)));
+ KdPrint3((PRINT_PREFIX "Err intr (%#x), SE (%#x)\n",
+ chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB),
+ chan->AhciLastSError));
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;
+ AtaReq->ahci.in_serror = chan->AhciLastSError;
+ if(chan->AhciLastSError & (ATA_SE_HANDSHAKE_ERR | ATA_SE_LINKSEQ_ERR | ATA_SE_TRANSPORT_ERR | ATA_SE_UNKNOWN_FIS)) {
+ KdPrint2((PRINT_PREFIX "Unrecoverable\n"));
+ NoRetry = TRUE;
+ }
} else {
// We have only Overflow. Abort operation and continue
-#if DBG
+#ifdef _DEBUG
UniataDumpAhciPortRegs(chan);
#endif
if(!UniataAhciAbortOperation(chan)) {
KdPrint2((PRINT_PREFIX "need UniataAhciReset\n"));
}
-#if DBG
+#ifdef _DEBUG
UniataDumpAhciPortRegs(chan);
#endif
UniataAhciWaitCommandReady(chan, 10);
if(deviceExtension->HwFlags & UNIATA_AHCI) {
KdPrint3((PRINT_PREFIX " AHCI branch (ATAPI)\n"));
} else {
- interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
+ interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
}
if(deviceExtension->HwFlags & UNIATA_AHCI) {
error = AtaReq->ahci.in_error;
// wait ready
-#if DBG
+#ifdef _DEBUG
UniataDumpAhciPortRegs(chan);
#endif
if(!UniataAhciAbortOperation(chan)) {
}
// clear interrupts again
UniataAhciWaitCommandReady(chan, 10);
-#if DBG
+#ifdef _DEBUG
UniataDumpAhciPortRegs(chan);
#endif
UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
-#if DBG
+ if(NoRetry) {
+ AtaReq->retry += MAX_RETRIES;
+ if(!error && (statusByte & IDE_STATUS_ERROR)) {
+ KdPrint2((PRINT_PREFIX "AtapiInterrupt: force error status\n"));
+ error |= IDE_STATUS_ERROR;
+ }
+ }
+#ifdef _DEBUG
UniataDumpAhciPortRegs(chan);
#endif
} else {
KdPrint2((PRINT_PREFIX " Bad Lba unknown\n"));
}
-
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ KdPrint2((PRINT_PREFIX " no wait ready after error\n"));
+ } else
if(!atapiDev) {
KdPrint2((PRINT_PREFIX " wait 100 ready after IDE error\n"));
AtapiStallExecution(100);
#endif //IO_STATISTICS
if(DmaTransfer /*&&
(error & IDE_ERROR_ICRC)*/) {
+ KdPrint2((PRINT_PREFIX "Errors in DMA mode\n"));
if(AtaReq->retry < MAX_RETRIES) {
//fallback_pio:
- AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
- AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
+ if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
+ AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
+ AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
// LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
+ }
AtaReq->ReqState = REQ_STATE_QUEUED;
goto reenqueue_req;
}
}
}
} else {
- interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
+ interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason));
if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) &&
KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n"));
KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n",
AtaReq->retry,
- chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry],
- chan->lun[DeviceNumber]->BlockIoCount
+ LunExt->RecoverCount[AtaReq->retry],
+ LunExt->BlockIoCount
));
- chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry]++;
- if(chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
+ LunExt->RecoverCount[AtaReq->retry]++;
+ if(LunExt->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
(deviceExtension->HwFlags & UNIATA_NO80CHK)
) {
#else
if(deviceExtension->HwFlags & UNIATA_NO80CHK) {
#endif //IO_STATISTICS
- KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", deviceExtension->lun[DeviceNumber].TransferMode));
- deviceExtension->lun[DeviceNumber].LimitedTransferMode =
- deviceExtension->lun[DeviceNumber].TransferMode;
+ KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", LunExt->TransferMode));
+ LunExt->LimitedTransferMode =
+ LunExt->TransferMode;
}
}
#ifdef IO_STATISTICS
if(AtaReq->bcount) {
// we need stats for Read/Write operations
- chan->lun[DeviceNumber]->BlockIoCount++;
+ LunExt->BlockIoCount++;
}
- chan->lun[DeviceNumber]->IoCount++;
+ LunExt->IoCount++;
#endif //IO_STATISTICS
continue_PIO:
KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI branch\n"));
// ATAPI branch
- interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
+ interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
if(DmaTransfer) {
wordsThisInterrupt = DEV_BSIZE/2*512;
if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
- interruptReason = 0x2;
+ interruptReason = ATAPI_IR_IO_toHost;
} else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
- interruptReason = 0x0;
+ interruptReason = ATAPI_IR_IO_toDev;
} else {
status = SRB_STATUS_ERROR;
goto ReturnEnableIntr;
} else {
- interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? 0x2 : 0x0;
+ interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? ATAPI_IR_IO_toHost : ATAPI_IR_IO_toDev;
}
} else {
// Command complete - verify, write, or the SMART enable/disable.
// Also get_media_status
- interruptReason = 0x3;
+ interruptReason = ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd;
}
}
}
} else {
AtaReq->WordsLeft -= AtaReq->WordsTransfered;
}
- if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
- status = SRB_STATUS_DATA_OVERRUN;
- }
+ //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
+ // status = SRB_STATUS_DATA_OVERRUN;
+ //}
status = SRB_STATUS_SUCCESS;
chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
goto CompleteRequest;
} else
- if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) {
+ if (interruptReason == ATAPI_IR_COD_Cmd && (statusByte & IDE_STATUS_DRQ)) {
// Write the packet.
KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
// Send CDB to device.
- WriteBuffer(chan, (PUSHORT)srb->Cdb, 6, 0);
+ WriteBuffer(chan, (PUSHORT)srb->Cdb,
+ LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
+ 0);
AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
goto ReturnEnableIntr;
- } else if (interruptReason == 0x0 && (statusByte & IDE_STATUS_DRQ)) {
+ } else if (interruptReason == ATAPI_IR_IO_toDev && (statusByte & IDE_STATUS_DRQ)) {
// Write the data.
if (atapiDev) {
goto ReturnEnableIntr;
- } else if (interruptReason == 0x2 && (statusByte & IDE_STATUS_DRQ)) {
+ } else if (interruptReason == ATAPI_IR_IO_toHost && (statusByte & IDE_STATUS_DRQ)) {
if (atapiDev) {
goto ReturnEnableIntr;
- } else if (interruptReason == 0x3 && !(statusByte & IDE_STATUS_DRQ)) {
+ } else if (interruptReason == (ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd) && !(statusByte & IDE_STATUS_DRQ)) {
KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n"));
- // Command complete.
+ // Command complete. We exactly know this because os IReason.
+
if(DmaTransfer) {
KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
- AtaReq->WordsTransfered = AtaReq->WordsLeft;
+ AtaReq->WordsTransfered += AtaReq->WordsLeft;
AtaReq->WordsLeft = 0;
+ } else {
+ KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was PIO\n"));
+
+ wordCount = AtaReq->WordsLeft;
+ // Advance data buffer pointer and bytes left.
+ AtaReq->DataBuffer += wordCount;
+ AtaReq->WordsLeft -= wordCount;
+ AtaReq->WordsTransfered += wordCount;
}
//if (AtaReq->WordsLeft) {
// status = SRB_STATUS_DATA_OVERRUN;
// Check and see if we are processing our secret (mechanism status/request sense) srb
if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
- KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_SUCCESS\n", AtaReq->WordsLeft));
+ KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq->WordsLeft));
status = SRB_STATUS_DATA_OVERRUN;
}
AtaReq->OriginalSrb);
} else {
- // last request was illegal. No point trying again
+ // last request was illegal. No point trying again.
+ // Do-nothing call ?
AtapiHwInitializeChanger (HwDeviceExtension,
srb,
(PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
if (AtaReq->OriginalSrb) {
KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
+ // Do-nothing call ?
AtapiHwInitializeChanger (HwDeviceExtension,
srb,
(PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
} else {
KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n"));
- PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
if (status != SRB_STATUS_SUCCESS) {
error = AtapiReadPort1(chan, IDX_IO1_i_Error);
KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error));
}
- // Build the SMART status block depending upon the completion status.
- cmdOutParameters->cBufferSize = wordCount;
- cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
- cmdOutParameters->DriverStatus.bIDEError = error;
+ if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
- // If the sub-command is return smart status, jam the value from cylinder low and high, into the
- // data buffer.
- if (chan->SmartCommand == RETURN_SMART_STATUS) {
- cmdOutParameters->bBuffer[0] = RETURN_SMART_STATUS;
- cmdOutParameters->bBuffer[1] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason);
- cmdOutParameters->bBuffer[2] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Unused1);
- cmdOutParameters->bBuffer[3] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
- cmdOutParameters->bBuffer[4] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh);
- cmdOutParameters->bBuffer[5] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_DriveSelect);
- cmdOutParameters->bBuffer[6] = SMART_CMD;
- cmdOutParameters->cBufferSize = 8;
- }
+ PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
+ // Build the SMART status block depending upon the completion status.
+ cmdOutParameters->cBufferSize = wordCount;
+ cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
+ cmdOutParameters->DriverStatus.bIDEError = error;
+
+ // If the sub-command is return smart status, jam the value from cylinder low and high, into the
+ // data buffer.
+ if (chan->SmartCommand == RETURN_SMART_STATUS) {
+ PIDEREGS_EX regs = (PIDEREGS_EX)&(cmdOutParameters->bBuffer);
+
+ regs->bOpFlags = 0;
+ UniataSnapAtaRegs(chan, 0, regs);
+
+ regs->bCommandReg = SMART_CMD;
+ regs->bFeaturesReg = RETURN_SMART_STATUS;
+ cmdOutParameters->cBufferSize = 8;
+ }
+ chan->SmartCommand = 0; // cleanup after execution
+ }
// Indicate command complete.
goto IntrCompleteReq;
}
NTAPI
IdeSendSmartCommand(
IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb
+ IN PSCSI_REQUEST_BLOCK Srb,
+ IN ULONG targetId // assume it is always valid
)
{
PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- ULONG c = GET_CHANNEL(Srb);
- PHW_CHANNEL chan = &(deviceExtension->chan[c]);
+ ULONG c ; // = GET_CHANNEL(Srb); may be invalid
+ PHW_CHANNEL chan ; // = &(deviceExtension->chan[c]);
PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
PIDEREGS regs = &cmdInParameters.irDriveRegs;
// ULONG i;
- UCHAR statusByte,targetId;
-
+ UCHAR statusByte;
+ ULONG DeviceNumber;
if (regs->bCommandReg != SMART_CMD) {
KdPrint2((PRINT_PREFIX
return SRB_STATUS_INVALID_REQUEST;
}
- targetId = cmdInParameters.bDriveNumber;
-
- //TODO optimize this check
- if ((!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) ||
- (deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
+ c = targetId / deviceExtension->NumberLuns;
+ DeviceNumber = targetId % deviceExtension->NumberLuns;
+ KdPrint2((PRINT_PREFIX " c %d, dev %d\n", c, DeviceNumber));
- return SRB_STATUS_SELECTION_TIMEOUT;
- }
+ chan = &(deviceExtension->chan[c]);
chan->SmartCommand = regs->bFeaturesReg;
switch(regs->bFeaturesReg) {
case READ_ATTRIBUTES:
case READ_THRESHOLDS:
+ case READ_LOG_SECTOR:
+ case WRITE_LOG_SECTOR:
+
+ if(Srb->DataTransferLength < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1) {
+ KdPrint2((PRINT_PREFIX
+ "IdeSendSmartCommand: wrong buffer size\n"));
+ return SRB_STATUS_DATA_OVERRUN;
+ }
statusByte = WaitOnBusy(chan);
AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2;
- statusByte = AtaCommand(deviceExtension, targetId & 0x1, c,
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
regs->bCommandReg,
(USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
0,
case ENABLE_DISABLE_AUTOSAVE:
case EXECUTE_OFFLINE_DIAGS:
case SAVE_ATTRIBUTE_VALUES:
+ case AUTO_OFFLINE:
statusByte = WaitOnBusy(chan);
AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
AtaReq->WordsLeft = 0;
- statusByte = AtaCommand(deviceExtension, targetId & 0x1, c,
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
regs->bCommandReg,
(USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
0,
if(!(statusByte & IDE_STATUS_ERROR)) {
// Wait for interrupt.
+ UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
return SRB_STATUS_PENDING;
}
return SRB_STATUS_ERROR;
PHW_LU_EXTENSION LunExt;
//ULONG ldev = GET_LDEV(Srb);
ULONG DeviceNumber = GET_CDEV(Srb);
- ULONG i;
ULONG flags;
- UCHAR statusByte,byteCountLow,byteCountHigh;
+ UCHAR statusByte,statusByte0,byteCountLow,byteCountHigh;
BOOLEAN use_dma = FALSE;
BOOLEAN dma_reinited = FALSE;
BOOLEAN retried = FALSE;
if(CmdAction == CMD_ACTION_PREPARE) {
KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb->Cdb)));
+
switch (Srb->Cdb[0]) {
case SCSIOP_RECEIVE:
case SCSIOP_SEND:
KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
return srbStatus;
} else {
+
+ // failed! Get the sense key and maybe try again
+ AtaReq->Srb = BuildRequestSenseSrb ( HwDeviceExtension,
+ AtaReq->OriginalSrb);
+
+ srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
+
+ KdPrint3((PRINT_PREFIX "AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
+
+ if (srbStatus == SRB_STATUS_PENDING) {
+ KdPrint2((PRINT_PREFIX "AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
+ return srbStatus;
+ }
+
+ // failed again ? should not get here
+
AtaReq->Srb = AtaReq->OriginalSrb;
AtaReq->OriginalSrb = NULL;
+
KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiHwInitializeChanger()\n"));
+ // Do-nothing call ?
AtapiHwInitializeChanger (HwDeviceExtension, Srb,
(PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
// fall out
(AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb->Cdb[0], &(Srb->Cdb)));
+
+ if(!LunExt->IdentifyData.AtapiCmdSize &&
+ (Srb->CdbLength > 12)) {
+ KdPrint2((PRINT_PREFIX "Cdb16 not supported\n"));
+ return SRB_STATUS_INVALID_REQUEST;
+ }
+
// Set data buffer pointer and words left.
AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
AtaReq->WordsLeft = Srb->DataTransferLength / 2;
}
// check if DMA read/write
- if(deviceExtension->HwFlags & UNIATA_SATA) {
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (ahci)\n"));
use_dma = TRUE;
goto setup_dma;
} else
+/* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
+ KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
+ use_dma = TRUE;
+ goto setup_dma;
+ } else*/
if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
} else
// Try to drain the data that one preliminary device thinks that it has
// to transfer. Hopefully this random assertion of DRQ will not be present
// in production devices.
+ statusByte = AtapiSuckPort2(chan);
+/*
for (i = 0; i < 0x10000; i++) {
GetStatus(chan, statusByte);
if(statusByte & IDE_STATUS_DRQ) {
break;
}
}
-
- if (i == 0x10000) {
+*/
+ if (statusByte & IDE_STATUS_DRQ) {
make_reset:
KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
if(g_opt_AtapiSendDisableIntr) {
AtapiDisableInterrupts(deviceExtension, lChannel);
}
+ // remember status. Later we may check if error appeared after cmd packet
+ statusByte0 = statusByte;
// Write ATAPI packet command.
AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
WriteBuffer(chan,
(PUSHORT)Srb->Cdb,
- 6,
+ LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
0);
+ GetStatus(chan, statusByte);
+ KdPrint3((PRINT_PREFIX "AtapiSendCommand: cmd status (%#x)\n", statusByte));
+
+ // When we operate in DMA mode, we should not start transfer when there is an error on entry
+ // Interrupt may never come in such case.
+ if(statusByte & IDE_STATUS_ERROR) {
+ UCHAR interruptReason;
+
+ GetBaseStatus(chan, statusByte);
+ KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on cmd: (%#x)\n", statusByte));
+
+ interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
+ KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x\n", interruptReason));
+
+ // TODO: we should check interruptReason and decide what to do now
+
+ // Read the error reg. to clear it and fail this request.
+ AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
+ return MapError(deviceExtension, Srb);
+ }
+/* if(statusByte & IDE_STATUS_DSC) {
+ KdPrint3((PRINT_PREFIX "AtapiSendCommand: DSC on cmd: (%#x)\n", statusByte));
+ // Read the error reg. to clear it and fail this request.
+ statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
+ KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
+ if(statusByte >> 4) {
+ GetBaseStatus(chan, statusByte);
+ AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
+ return MapError(deviceExtension, Srb);
+ }
+ }
+*/
if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
}
SetCheckPoint(4);
UCHAR statusByte,errorByte;
- ULONG status;
+ ULONG status = SRB_STATUS_INVALID_REQUEST;
ULONG i;
ULONGLONG lba;
PMODE_PARAMETER_HEADER modeData;
//ULONG ldev;
ULONG DeviceNumber;
PATA_REQ AtaReq;
+ UCHAR command;
+
SetCheckPoint(5);
//ULONG __ebp__ = 0;
// Fill in vendor identification fields.
for (i = 0; i < 24; i += 2) {
- MOV_DW_SWP(inquiryData->VendorId[i], ((PUCHAR)identifyData->ModelNumber)[i]);
+ MOV_DW_SWP(inquiryData->DeviceIdentificationString[i], ((PUCHAR)identifyData->ModelNumber)[i]);
}
/*
// Initialize unused portion of product id.
break;
+ case SCSIOP_REPORT_LUNS: {
+
+ ULONG alen;
+ PREPORT_LUNS_INFO_HDR LunInfo;
+
+ KdPrint2((PRINT_PREFIX
+ "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
+ Srb->PathId, Srb->Lun, Srb->TargetId));
+
+ MOV_DD_SWP(alen, cdb->REPORT_LUNS.AllocationLength);
+
+ if(alen < 16) {
+ goto invalid_cdb;
+ }
+ alen = 8;
+
+ LunInfo = (PREPORT_LUNS_INFO_HDR)(Srb->DataBuffer);
+ RtlZeroMemory(LunInfo, 16);
+
+ MOV_DD_SWP( LunInfo->ListLength, alen );
+ Srb->DataTransferLength = 16;
+ status = SRB_STATUS_SUCCESS;
+
+ break; }
+
case SCSIOP_MODE_SENSE:
KdPrint2((PRINT_PREFIX
"IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
Srb->PathId, Srb->Lun, Srb->TargetId));
- // This is used to determine if the media is write-protected.
- // Since IDE does not support mode sense then we will modify just the portion we need
- // so the higher level driver can determine if media is protected.
+
+ if(cdb->MODE_SENSE.PageCode == MODE_PAGE_POWER_CONDITION) {
+ PMODE_POWER_CONDITION_PAGE modeData;
+
+ KdPrint2((PRINT_PREFIX "MODE_PAGE_POWER_CONDITION\n"));
+ modeData = (PMODE_POWER_CONDITION_PAGE)(Srb->DataBuffer);
+ if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_POWER_CONDITION_PAGE)) {
+ status = SRB_STATUS_DATA_OVERRUN;
+ } else {
+ RtlZeroMemory(modeData, sizeof(MODE_POWER_CONDITION_PAGE));
+ modeData->PageCode = MODE_PAGE_POWER_CONDITION;
+ modeData->PageLength = sizeof(MODE_PAGE_POWER_CONDITION)-sizeof(MODE_PARAMETER_HEADER);
+ modeData->Byte3.Fields.Idle = LunExt->PowerState <= StartStop_Power_Idle;
+ modeData->Byte3.Fields.Standby = LunExt->PowerState == StartStop_Power_Standby;
+ Srb->DataTransferLength = sizeof(MODE_POWER_CONDITION_PAGE);
+ status = SRB_STATUS_SUCCESS;
+ }
+ } else
if(cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) {
PMODE_CACHING_PAGE modeData;
KdPrint2((PRINT_PREFIX "MODE_PAGE_CACHING\n"));
- modeData = (PMODE_CACHING_PAGE)Srb->DataBuffer;
+ modeData = (PMODE_CACHING_PAGE)(Srb->DataBuffer);
if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) {
- status = STATUS_BUFFER_TOO_SMALL;
+ status = SRB_STATUS_DATA_OVERRUN;
} else {
RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE));
modeData->PageCode = MODE_PAGE_CACHING;
} else
if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
+ // This is used to determine if the media is write-protected.
+ // Since IDE does not support mode sense then we will modify just the portion we need
+ // so the higher level driver can determine if media is protected.
+
//SelectDrive(chan, DeviceNumber);
//AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
//statusByte = WaitOnBusy(chan);
case SCSIOP_START_STOP_UNIT:
KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
- Srb->PathId, Srb->Lun, Srb->TargetId));
+ "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
+ cdb->START_STOP.Immediate, Srb->PathId, Srb->Lun, Srb->TargetId));
//Determine what type of operation we should perform
- cdb = (PCDB)Srb->Cdb;
- if (cdb->START_STOP.LoadEject == 1){
+ command = 0;
- statusByte = WaitOnBaseBusy(chan);
+ if(cdb->START_STOP.FL ||
+ cdb->START_STOP.FormatLayerNumber ||
+ cdb->START_STOP.Reserved2 ||
+ cdb->START_STOP.Reserved2_2 ||
+ cdb->START_STOP.Reserved3 ||
+ FALSE) {
+ goto invalid_cdb;
+ }
+
+ if (cdb->START_STOP.PowerConditions) {
+ KdPrint2((PRINT_PREFIX "START_STOP Power %d\n", cdb->START_STOP.PowerConditions));
+ switch(cdb->START_STOP.PowerConditions) {
+ case StartStop_Power_Idle:
+ command = IDE_COMMAND_IDLE_IMMED;
+ break;
+ case StartStop_Power_Standby:
+ command = IDE_COMMAND_STANDBY_IMMED;
+ break;
+ case StartStop_Power_Sleep:
+ // TODO: we should save power state in order to know
+ // that RESET sould be issued to revert device into
+ // operable state
+
+ command = IDE_COMMAND_SLEEP;
+ break;
+ default:
+ goto invalid_cdb;
+ }
+ LunExt->PowerState = cdb->START_STOP.PowerConditions;
+ } else
+ if (cdb->START_STOP.LoadEject == 1) {
+ KdPrint2((PRINT_PREFIX "START_STOP eject\n"));
// Eject media,
// first select device 0 or 1.
//SelectDrive(chan, DeviceNumber);
//AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_MEDIA_EJECT, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
+ command = IDE_COMMAND_MEDIA_EJECT;
+ } else
+ if (cdb->START_STOP.Start == 0) {
+ KdPrint2((PRINT_PREFIX "START_STOP standby\n"));
+ command = IDE_COMMAND_STANDBY_IMMED;
+ } else {
+ // TODO: we may need to perform hard reset (after sleep) or
+ // issue IDE_COMMAND_IDLE_IMMED in order to activate device
+ KdPrint2((PRINT_PREFIX "START_STOP activate\n"));
+
+ if(LunExt->PowerState == StartStop_Power_Sleep) {
+ UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
+ status = SRB_STATUS_SUCCESS;
+ break;
+ } else
+ if(LunExt->PowerState > StartStop_Power_Idle) {
+ KdPrint2((PRINT_PREFIX " issue IDLE\n"));
+ command = IDE_COMMAND_IDLE_IMMED;
+ } else {
+ KdPrint2((PRINT_PREFIX " do nothing\n"));
+ status = SRB_STATUS_SUCCESS;
+ break;
+ }
+ }
+ if(command) {
+ statusByte = WaitOnBaseBusy(chan);
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, command, 0, 0, 0, 0, 0,
+ cdb->START_STOP.Immediate ? ATA_IMMEDIATE : ATA_WAIT_READY);
+ status = (statusByte & IDE_STATUS_ERROR) ? SRB_STATUS_ERROR : SRB_STATUS_SUCCESS;
+ //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
+
+ } else {
+invalid_cdb:
+ KdPrint2((PRINT_PREFIX "START_STOP invalid\n"));
+ if (Srb->SenseInfoBuffer) {
+
+ PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
+
+ senseBuffer->ErrorCode = 0x70;
+ senseBuffer->Valid = 1;
+ senseBuffer->AdditionalSenseLength = 0xb;
+ senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
+ senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_CDB;
+ senseBuffer->AdditionalSenseCodeQualifier = 0;
+
+ Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
+ Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
+ }
+ status = SRB_STATUS_ERROR;
}
- status = SRB_STATUS_SUCCESS;
break;
case SCSIOP_MEDIUM_REMOVAL:
regs = (PIDEREGS_EX) &(Srb->Cdb[2]);
- lChannel = Srb->TargetId >> 1;
-
- regs->bDriveHeadReg &= 0x0f;
- regs->bDriveHeadReg |= (UCHAR) (((Srb->TargetId & 0x1) << 4) | 0xA0);
+ if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
+ //lChannel = Srb->TargetId >> 1;
+ } else {
+ DeviceNumber = max(DeviceNumber, 1);
+ regs->bDriveHeadReg &= 0x0f;
+ regs->bDriveHeadReg |= (UCHAR) (((DeviceNumber & 0x1) << 4) | 0xA0);
+ }
if((regs->bOpFlags & 1) == 0) { // execute ATA command
KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
+ "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
Srb->PathId, Srb->Lun, Srb->TargetId));
+ if((regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) == UNIATA_SPTI_EX_SPEC_TO) {
+ to_lim = Srb->TimeOutValue;
+ } else {
+ if(Srb->TimeOutValue <= 2) {
+ to_lim = Srb->TimeOutValue*900;
+ } else {
+ to_lim = (Srb->TimeOutValue*999) - 500;
+ }
+ }
AtapiDisableInterrupts(deviceExtension, lChannel);
+ if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
+ // AHCI
+ statusByte = UniataAhciSendPIOCommandDirect(
+ deviceExtension,
+ lChannel,
+ DeviceNumber,
+ Srb,
+ regs,
+ ATA_WAIT_INTR,
+ to_lim
+ );
+ if(statusByte == IDE_STATUS_WRONG) {
+ goto passthrough_err;
+ }
+ if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
+ UniataAhciAbortOperation(chan);
+ goto passthrough_err;
+ }
+ goto passthrough_done;
+ }
+
+ // SATA/PATA
if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) {
- if((chan->lun[Srb->TargetId & 0x1]->LimitedTransferMode >= ATA_DMA)) {
+ if((chan->lun[DeviceNumber]->LimitedTransferMode >= ATA_DMA)) {
use_dma = TRUE;
// this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
- if(!AtapiDmaSetup(HwDeviceExtension, Srb->TargetId & 0x1, lChannel, Srb,
+ if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
(PUCHAR)(Srb->DataBuffer),
((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) {
use_dma = FALSE;
}
}
- AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg);
+ AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg);
AtapiStallExecution(10);
if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command
if(statusByte & IDE_STATUS_ERROR) {
goto passthrough_err;
}
- AtapiDmaStart(HwDeviceExtension, (Srb->TargetId & 0x1), lChannel, Srb);
+ AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
}
ScsiPortStallExecution(1); // wait for busy to be set
- if(regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) {
- to_lim = Srb->TimeOutValue;
- } else {
- if(Srb->TimeOutValue <= 2) {
- to_lim = Srb->TimeOutValue*900;
- } else {
- to_lim = (Srb->TimeOutValue*999) - 500;
- }
- }
for(i=0; i<to_lim;i+=2) { // 2 msec from WaitOnBaseBusy()
statusByte = WaitOnBaseBusy(chan); // wait for busy to be clear, up to 2 msec
GetBaseStatus(chan, statusByte);
if(use_dma) {
AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel);
}
- AtapiDmaDone(deviceExtension, (Srb->TargetId & 0x1), lChannel, NULL);
+ AtapiDmaDone(deviceExtension, DeviceNumber, lChannel, NULL);
GetBaseStatus(chan, statusByte);
if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
}
status = SRB_STATUS_SUCCESS;
}
-
+passthrough_done:;
AtapiEnableInterrupts(deviceExtension, lChannel);
} else { // read task register
+ BOOLEAN use48;
regs = (PIDEREGS_EX) Srb->DataBuffer;
- regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
+ KdPrint2((PRINT_PREFIX
+ "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
+ Srb->PathId, Srb->Lun, Srb->TargetId));
- if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command
- regs->bFeaturesReg = AtapiReadPort1(chan, IDX_IO1_i_Error);
- regs->bSectorCountReg = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
- regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
- regs->bCylLowReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- regs->bCylHighReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
+ if((Srb->DataTransferLength >= sizeof(IDEREGS_EX)) &&
+ (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND)) {
+ use48 = TRUE;
+ } else
+ if(Srb->DataTransferLength >= sizeof(IDEREGS)) {
+ use48 = FALSE;
} else {
- regs->bFeaturesReg = AtapiReadPort1(chan, IDX_IO1_i_Error);
- regs->bFeaturesRegH = AtapiReadPort1(chan, IDX_IO1_i_Error);
- regs->bSectorCountReg = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
- regs->bSectorCountRegH = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
- regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
- regs->bSectorNumberRegH= AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
- regs->bCylLowReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- regs->bCylLowRegH = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- regs->bCylHighReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
- regs->bCylHighRegH = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
+ KdPrint2((PRINT_PREFIX " buffer too small \n"));
+ status = SRB_STATUS_DATA_OVERRUN;
+ break;
}
- regs->bCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status);
+ RtlZeroMemory(regs, use48 ? sizeof(IDEREGS_EX) : sizeof(IDEREGS));
+ regs->bOpFlags = use48 ? ATA_FLAGS_48BIT_COMMAND : 0;
+ UniataSnapAtaRegs(chan, 0, regs);
+
status = SRB_STATUS_SUCCESS;
}
break;
UniataUserDeviceReset(
PHW_DEVICE_EXTENSION deviceExtension,
PHW_LU_EXTENSION LunExt,
- ULONG PathId
+ ULONG lChannel
)
{
ULONG i;
- AtapiDisableInterrupts(deviceExtension, PathId);
- if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
+ AtapiDisableInterrupts(deviceExtension, lChannel);
+ if ((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
+ (LunExt->PowerState != StartStop_Power_Sleep)) {
KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n"));
- AtapiSoftReset(&(deviceExtension->chan[PathId]), LunExt->Lun);
+ AtapiSoftReset(&(deviceExtension->chan[lChannel]), LunExt->Lun);
} else {
KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
- AtapiResetController__(deviceExtension, PathId, RESET_COMPLETE_NONE);
+ AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_NONE);
for(i=0; i<deviceExtension->NumberLuns; i++) {
- deviceExtension->chan[PathId].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
+ deviceExtension->chan[lChannel].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
}
}
LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
- AtapiEnableInterrupts(deviceExtension, PathId);
+ AtapiEnableInterrupts(deviceExtension, lChannel);
return;
} // end UniataUserDeviceReset()
This routine is called from the SCSI port driver synchronized
with the kernel to start an IO request.
+ ->HwStartIo
Arguments:
UniAtaClearAtaReq(Srb->SrbExtension);
}
- do {
+ do { // fetch all queued commands for the channel (if valid)
lChannel = GET_CHANNEL(Srb);
//ldev = GET_LDEV(Srb);
chan = NULL;
LunExt = NULL;
DeviceNumber = GET_CDEV(Srb);
+ commPort = FALSE;
//ASSERT(deviceExtension);
//ASSERT(chan);
"AtapiStartIo: Communication port\n"));
if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
+ if(Srb->DataTransferLength < sizeof(PINQUIRYDATA)) {
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", Srb->DataTransferLength,
+ sizeof(PINQUIRYDATA) ));
+wrong_buffer_size:
+ status = SRB_STATUS_DATA_OVERRUN;
+ goto complete_req;
+ }
+
PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
KdPrint2((PRINT_PREFIX
/* Pass IOCTL request down */
} else
if(lChannel >= deviceExtension->NumberChannels ||
- Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
- Srb->Lun) {
+ Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
+ Srb->Lun) {
- if(lChannel >= deviceExtension->NumberChannels) {
- chan = NULL;
- }
+ if(lChannel >= deviceExtension->NumberChannels) {
+ chan = NULL;
+ }
reject_srb:
//if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
- KdPrint3((PRINT_PREFIX
+ KdPrint3((PRINT_PREFIX
"AtapiStartIo: SRB rejected\n"));
- // Indicate no device found at this address.
- KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
- status = SRB_STATUS_SELECTION_TIMEOUT;
- goto complete_req;
+ // Indicate no device found at this address.
+ KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
+ status = SRB_STATUS_SELECTION_TIMEOUT;
+ goto complete_req;
//}
+ } else
+ if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+ !UniataAhciChanImplemented(deviceExtension, lChannel)) {
+ chan = NULL;
}
if(!commPort) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
} else {
+
// Send command to device.
KdPrint2((PRINT_PREFIX "Send to device %x\n", Srb->Cdb[0]));
if(TopLevel) {
#endif //NAVO_TEST
if(atapiDev &&
- (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
+ (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)/* &&
+ (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0]));
status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
} else {
if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
+ ULONG targetId = (ULONG)(-1);
+
+ if(len < sizeof(SRB_IO_CONTROL)) {
+ goto wrong_buffer_size;
+ }
+
+ // extract bogus bus address
switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
-
PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
- UCHAR deviceNumber;
- KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
+ if(len < sizeof(SRB_IO_CONTROL)+sizeof(GETVERSIONINPARAMS)) {
+ goto wrong_buffer_size;
+ }
- // Version and revision per SMART 1.03
+ targetId = versionParameters->bIDEDeviceMap;
+ KdPrint2((PRINT_PREFIX "targetId (smart ver) %d\n", targetId));
+ break; }
+ case IOCTL_SCSI_MINIPORT_IDENTIFY:
+ case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
+ case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
+ case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
+ case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
+ case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
+ case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
+ case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
+ case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
+ case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE:
+ case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
+ case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG:
+ {
+ PSENDCMDINPARAMS cmdInParameters = (PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
+
+ if(len < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS) - 1) {
+ goto wrong_buffer_size;
+ }
- versionParameters->bVersion = 1;
- versionParameters->bRevision = 1;
- versionParameters->bReserved = 0;
+ targetId = cmdInParameters->bDriveNumber;
+ KdPrint2((PRINT_PREFIX "targetId (smart/ident) %d\n", targetId));
+ break; }
+ default:
+invalid_request:
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
+ ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
+ status = SRB_STATUS_INVALID_REQUEST;
+ goto complete_req;
+ } // end switch()
- // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
- versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
+ // adjust (if necessary) bus address
+ if(targetId != (ULONG)(-1)) {
// This is done because of how the IOCTL_SCSI_MINIPORT
// determines 'targetid's'. Disk.sys places the real target id value
// in the DeviceMap field. Once we do some parameter checking, the value passed
// back to the application will be determined.
- deviceNumber = versionParameters->bIDEDeviceMap;
-
+ if (deviceExtension->NumberChannels == 1) {
+ // do this for legacy controllers and legacy callers
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call\n"));
+ DeviceNumber = (targetId & 0x01);
+ lChannel = 0;
+ } else
if(commPort) {
+ // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
+ // due to DISK.SYS design bug, we have invalid SCSI address in SRB
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call (2)\n"));
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ lChannel = (UCHAR)targetId / 2;
+ DeviceNumber = 0;
+ } else {
+ lChannel = (UCHAR)(targetId / 2);
+ DeviceNumber = targetId & 0x01;
+ }
+ } else {
+ // otherwise assume lChannel and DeviceNumber from Srb are ok
+ }
+ if(lChannel >= deviceExtension->NumberChannels ||
+ DeviceNumber >= deviceExtension->NumberLuns) {
KdPrint2((PRINT_PREFIX
- "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
+ "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
+ targetId));
// Indicate no device found at this address.
- KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
+ goto reject_srb;
}
-
- if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) ||
- atapiDev) {
+ targetId = lChannel*deviceExtension->NumberLuns+DeviceNumber;
+ chan = &(deviceExtension->chan[lChannel]);
+ LunExt = chan->lun[DeviceNumber];
+ if(!LunExt) {
+ goto reject_srb;
+ }
+ atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
+ if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
+ goto reject_srb;
+ }
+ }
+
+ switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
+ case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
+
+ PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
+ UCHAR deviceNumberMap;
+
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
+
+ // Version and revision per SMART 1.03
+
+ versionParameters->bVersion = 1;
+ versionParameters->bRevision = 1;
+ versionParameters->bReserved = 0;
+
+ // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
+ versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
+
+ if (atapiDev) {
+ goto invalid_request;
}
// NOTE: This will only set the bit
// 3 2 1 0
if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
- deviceNumber = 1 << lChannel;
+ deviceNumberMap = 1 << lChannel;
+ DeviceNumber = 0;
} else
if (deviceExtension->NumberChannels == 1) {
if (chan->PrimaryAddress) {
- deviceNumber = 1 << DeviceNumber;
+ deviceNumberMap = 1 << DeviceNumber;
} else {
- deviceNumber = 4 << DeviceNumber;
+ deviceNumberMap = 4 << DeviceNumber;
}
} else {
- deviceNumber = 1 << (DeviceNumber+lChannel*2);
+ deviceNumberMap = 1 << (DeviceNumber+lChannel*2);
}
- versionParameters->bIDEDeviceMap = deviceNumber;
+ versionParameters->bIDEDeviceMap = deviceNumberMap;
status = SRB_STATUS_SUCCESS;
break;
PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
- UCHAR targetId;
KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
// Extract the target.
- targetId = cmdInParameters.bDriveNumber;
KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- // cheat code for AHCI :)
- // upper layer assumes that we have 2 devices per channel
- // TODO: we should invent something to handle PM here
- targetId /= 2;
- }
-
- if((targetId >= deviceExtension->NumberChannels*deviceExtension->NumberLuns) ||
- !(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
- KdPrint2((PRINT_PREFIX "Error: xxx_ID_CMD for non-existant device\n"));
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
- }
switch(cmdInParameters.irDriveRegs.bCommandReg) {
case ID_CMD:
- if((deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
+ if(atapiDev) {
KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n"));
- status = SRB_STATUS_INVALID_REQUEST;
- break;
+ goto invalid_request;
}
/* FALL THROUGH */
case ATAPI_ID_CMD:
- if(!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
+ if(!atapiDev &&
(cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) {
KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n"));
- status = SRB_STATUS_INVALID_REQUEST;
- break;
+ goto invalid_request;
}
len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE);
cmdOutParameters->DriverStatus.bIDEError = 0;
// Extract the identify data from the device extension.
- ScsiPortMoveMemory (cmdOutParameters->bBuffer, &deviceExtension->lun[targetId].IdentifyData,
+ ScsiPortMoveMemory (cmdOutParameters->bBuffer, &(LunExt->IdentifyData),
cmdOutParameters->cBufferSize);
+ if((cmdOutParameters->cBufferSize == IDENTIFY_BUFFER_SIZE) &&
+ (LunExt->IdentifyData.ChecksumValid == ATA_ChecksumValid)) {
+ // adjust checksum if it is possible
+ CHAR csum = 0;
+ ULONG i;
+
+ for(i=0; i < IDENTIFY_BUFFER_SIZE-1; i++) {
+ csum += (CHAR)(cmdOutParameters->bBuffer[i]);
+ }
+ cmdOutParameters->bBuffer[i] = -csum;
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: adjust checksum %d\n"));
+ }
KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
status = SRB_STATUS_SUCCESS;
}
break;
}
-
+/*
case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
-
+*/
+ default:
+ // *all* IOCTLs here are SMART
if(commPort) {
KdPrint2((PRINT_PREFIX
"AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
- // Indicate no device found at this address.
- KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
+ }
+ if (atapiDev) {
+ goto invalid_request;
}
PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
} else {
- status = IdeSendSmartCommand(HwDeviceExtension,Srb);
+ status = IdeSendSmartCommand(HwDeviceExtension, Srb, targetId);
}
break;
- default :
+ // we should not get here, checked above
+/* default :
KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
status = SRB_STATUS_INVALID_REQUEST;
break;
-
+*/
}
} else
if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) {
if(len < pos) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
FIELD_OFFSET(UNIATA_CTL, RawData) ));
- status = SRB_STATUS_DATA_OVERRUN;
- break;
+ goto wrong_buffer_size;
}
if(AtaCtl->addr.Lun ||
if(len < pos+sizeof(AtaCtl->SetMode)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->SetMode) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
if(!AtaCtl->SetMode.ApplyImmediately) {
break;
if(len < pos+sizeof(AtaCtl->FindDelDev)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->FindDelDev) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
if(len < pos+sizeof(AtaCtl->FindDelDev)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->FindDelDev) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
LunExt->DeviceFlags = 0;
if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
if(len < pos+sizeof(AtaCtl->SetMode)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->SetMode) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
if(len < pos+sizeof(AtaCtl->GetMode)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->GetMode) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
AtaCtl->GetMode.OrigMode = LunExt->OrigTransferMode;
AtaCtl->GetMode.MaxMode = LunExt->LimitedTransferMode;
if(len < pos+sizeof(AtaCtl->Version)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->Version) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
AtaCtl->Version.Length = sizeof(GETDRVVERSION);
AtaCtl->Version.VersionMj = UNIATA_VER_MJ;
if(len < pos+sizeof(AtaCtl->AdapterInfo)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->AdapterInfo) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO);
// Set status in SRB.
Srb->SrbStatus = (UCHAR)status;
- KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb));
- AtapiDmaDBSync(chan, Srb);
+ if(chan && Srb) {
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb));
+ AtapiDmaDBSync(chan, Srb);
+ }
KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan, Srb));
UniataRemoveRequest(chan, Srb);
// Indicate command complete.
ULONG statusToReturn, newStatus;
PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
BOOLEAN ReEnter = FALSE;
- WCHAR a;
+// WCHAR a;
#ifndef USE_REACTOS_DDK
NTSTATUS status;
#endif
Connect_DbgPrint();
KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string));
- a = (WCHAR)strlen(ver_string);
+ //a = (WCHAR)strlen(ver_string);
g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0);
if(g_opt_Verbose) {
if(GlobalConfig->AtDiskSecondaryAddressClaimed)
SecondaryClaimed = TRUE;
+ if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed &&
+ !(BMList[i].ChanInitOk & 0x80)) {
+ newStatus = UniataClaimLegacyPCIIDE(i);
+ if(newStatus != STATUS_SUCCESS) {
+ KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
+ break;
+ }
+ }
+
if(g_opt_Verbose) {
_PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
}
statusToReturn = newStatus;
}
if (newStatus == STATUS_SUCCESS) {
- BMList[i].ChanInitOk |= 0x01 << c;
+ if(WinVer_Id() < WinVer_2k) {
+ // This should be done in HwInitialize under w2k+ to ensure that
+ // channel is actually initialized
+ BMList[i].ChanInitOk |= 0x01 << c;
+ } else {
+ if(BMList[i].ChanInitOk & (0x01 << c)) {
+ KdPrint2((PRINT_PREFIX "HwInit passed\n"));
+ }
+ }
/*
if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
c = 1; // this will break our for()
*/
}
}
- if(WinVer_Id() >= WinVer_2k) {
- // the following doesn't work under higher OSes
+/* if(WinVer_Id() >= WinVer_2k) {
+ // the following didn't work under higher OSes,
+ // until we move setting of FLAGS to HwInit
KdPrint2((PRINT_PREFIX "make still one attempt\n"));
continue;
- }
+ }*/
if(BMList[i].ChanInitOk & 0x03) {
- // under NT we receive status immediately, so
- // we can omit alternative init method id STATUS_SUCCESS returned
+ // Under NT we receive status immediately, so
+ // we can omit alternative init method if STATUS_SUCCESS returned.
+ // Under w2k+ we relay on flags, set in HwInitialize.
KdPrint2((PRINT_PREFIX "Ok, no more retries required\n"));
break;
+ } else
+ if(WinVer_Id() >= WinVer_2k) {
+ // try AltInit if HwInit was not called immediately under w2k+
+ KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
+ } else {
+ // if (WinVer_Id() == WinVer_NT) and some error occured
+ // try alternative init method
+ KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
}
- // if (WinVer_Id() == WinVer_NT) and some error occured
- // try alternative init method
} // for(alt...)
-#if 0
- if(WinVer_WDM_Model) {
- hwInitializationData.comm.HwFindAdapter = UniataFindFakeBusMasterController;
- hwInitializationData.comm.NumberOfAccessRanges = 5;
- hwInitializationData.comm.AdapterInterfaceType = PCIBus;
-
- hwInitializationData.comm.VendorId = BMList[i].VendorId;
- hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
- hwInitializationData.comm.DeviceId = BMList[i].DeviceId;
- hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
-
- //BMList[i].channel = 0/*(UCHAR)c*/;
-
- KdPrint2((PRINT_PREFIX "Try init fake: %4.4s %4.4s \n",
- hwInitializationData.comm.VendorId,
- hwInitializationData.comm.DeviceId));
- newStatus = ScsiPortInitialize(DriverObject,
- Argument2,
- &hwInitializationData.comm,
- (PVOID)i);
- KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
- }
-#endif //0
if(g_opt_Verbose) {
if(BMList[i].ChanInitOk & 0x03) {
_PrintNtConsole(" OK\n");
hwInitializationData.comm.NumberOfAccessRanges = 6;
hwInitializationData.comm.AdapterInterfaceType = PCIBus;
- hwInitializationData.comm.VendorId = BMList[i].VendorId;
+ hwInitializationData.comm.VendorId = (PVOID)BMList[i].VendorId;
hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
- hwInitializationData.comm.DeviceId = BMList[i].DeviceId;
+ hwInitializationData.comm.DeviceId = (PVOID)BMList[i].DeviceId;
hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
BMList[i].channel = 0/*(UCHAR)c*/;
}
if(deviceExtension->AdapterInterfaceType == PCIBus) {
// we must never get here for non-PCI
- status = UniataDisconnectIntr2(HwDeviceExtension);
+ /*status =*/ UniataDisconnectIntr2(HwDeviceExtension);
BMList[deviceExtension->DevIndex].Isr2Enable = FALSE;
}
break;
AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
status = UniataConnectIntr2(HwDeviceExtension);
- for (c = 0; c < numberChannels; c++) {
- AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c);
- FindDevices(HwDeviceExtension, 0, c);
- AtapiEnableInterrupts(deviceExtension, c);
- AtapiHwInitialize__(deviceExtension, c);
- }
- if(deviceExtension->Isr2DevObj) {
- // we must never get here for non-PCI
- BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
+ if(NT_SUCCESS(status)) {
+ for (c = 0; c < numberChannels; c++) {
+ AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c);
+ FindDevices(HwDeviceExtension, 0, c);
+ AtapiEnableInterrupts(deviceExtension, c);
+ AtapiHwInitialize__(deviceExtension, c);
+ }
+ if(deviceExtension->Isr2DevObj) {
+ // we must never get here for non-PCI
+ BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
+ }
}
break;
PUCHAR String
);
+#define DEBUG_MSG_BUFFER_SIZE 512
+
extern "C"
VOID
_cdecl
...
)
{
- int len;
- UCHAR dbg_print_tmp_buff[512];
+ //int len;
+ UCHAR dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE];
// UNICODE_STRING msgBuff;
va_list ap;
va_start(ap, DebugMessage);
- len = _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], 511, DebugMessage, ap);
+ /*len =*/ _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], DEBUG_MSG_BUFFER_SIZE-1, DebugMessage, ap);
- dbg_print_tmp_buff[511] = 0;
+ dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE-1] = 0;
- KdPrint(((PCHAR)&(dbg_print_tmp_buff[0])));
+ //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
HalDisplayString(dbg_print_tmp_buff);
+#ifdef _DEBUG
+ if(g_LogToDisplay > 1) {
+ AtapiStallExecution(g_LogToDisplay*1000);
+ }
+#endif // _DEBUG
+
va_end(ap);
} // end PrintNtConsole()