+++ /dev/null
-/*++
-
-Copyright (c) 2002-2016 Alexandr A. Telyatnikov (Alter)
-
-Module Name:
- id_ata.cpp
-
-Abstract:
- This is the miniport driver for ATA/ATAPI IDE/SATA/AHCI controllers
- with Busmaster DMA and Serial ATA support
-
-Author:
- Alexander A. Telyatnikov (Alter)
-
-Environment:
- kernel mode only
-
-Notes:
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Revision History:
-
- The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
- Mike Glass (MGlass)
- Chuck Park (ChuckP)
-
- 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 significantly changed/updated by
- Alter, Copyright (c) 2002-2014:
-
- 1. Internal command queueing/reordering
- 2. Drive identification
- 3. Support for 2 _independent_ channels in a single PCI device
- 4. Smart host<->drive transfer rate slowdown (for bad cable)
- 5. W2k support (binary compatibility)
- 6. HDD hot swap under NT4
- 7. XP support (binary compatibility)
- 8. Serial ATA (SATA/SATA2/SATA3) support
- 9. NT 3.51 support (binary compatibility)
- 10. AHCI support
-
- etc. (See todo.txt)
-
-Licence:
- GPLv2
-
---*/
-
-#include "stdafx.h"
-
-#ifndef UNIATA_CORE
-
-static const CHAR ver_string[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR "\n";
-
-static const CHAR uniata_comm_name[] = UNIATA_COMM_PORT_VENDOR_STR " \n";
-
-UNICODE_STRING SavedRegPath;
-WCHAR SavedRegPathBuffer[256];
-
-#endif //UNIATA_CORE
-
-//UCHAR AtaCommands48[256];
-//UCHAR AtaCommandFlags[256];
-
-ULONG SkipRaids = 1;
-ULONG ForceSimplex = 0;
-
-LONGLONG g_Perf = 0;
-ULONG g_PerfDt = 0;
-
-#ifdef _DEBUG
-ULONG g_LogToDisplay = 0;
-#endif //_DEBUG
-
-ULONG g_WaitBusyInISR = 1;
-
-ULONG g_opt_WaitBusyResetCount = 10000; // 20000
-ULONG g_opt_WaitBusyCount = 200; // 20000
-ULONG g_opt_WaitBusyDelay = 10; // 150
-ULONG g_opt_WaitDrqDelay = 10; // 100
-ULONG g_opt_WaitBusyLongCount = 2000; // 2000
-ULONG g_opt_WaitBusyLongDelay = 250; // 250
-ULONG g_opt_MaxIsrWait = 40;
-
-ULONG g_opt_DriveSelectNanoDelay = 0; // 400; // ns
-
-BOOLEAN g_opt_AtapiSendDisableIntr = 0; // 0
-BOOLEAN g_opt_AtapiDmaRawRead = 1; // 0
-BOOLEAN g_opt_AtapiNoDma = FALSE;
-BOOLEAN g_opt_BochsDmaReadWorkaround = FALSE;
-BOOLEAN hasPCI = FALSE;
-
-ULONG g_opt_VirtualMachine = 0; // Auto
-
-BOOLEAN InDriverEntry = TRUE;
-BOOLEAN g_Dump = FALSE;
-
-BOOLEAN g_opt_Verbose = 0;
-
-BOOLEAN WinVer_WDM_Model = FALSE;
-ULONG CPU_num = 1;
-
-//UCHAR EnableDma = FALSE;
-//UCHAR EnableReorder = FALSE;
-
-UCHAR g_foo = 0;
-
-BOOLEAN
-NTAPI
-AtapiResetController__(
- IN PVOID HwDeviceExtension,
- IN ULONG PathId,
- IN UCHAR CompleteType
- );
-
-VOID
-NTAPI
-AtapiHwInitialize__(
- IN PHW_DEVICE_EXTENSION deviceExtension,
- 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
-
-#ifndef UNIATA_CORE
-
-VOID
-NTAPI
-AtapiCallBack_X(
- IN PVOID HwDeviceExtension
- );
-
-#ifdef UNIATA_USE_XXableInterrupts
- #define RETTYPE_XXableInterrupts BOOLEAN
- #define RETVAL_XXableInterrupts TRUE
-#else
- #define RETTYPE_XXableInterrupts VOID
- #define RETVAL_XXableInterrupts
-#endif
-
-RETTYPE_XXableInterrupts
-NTAPI
-AtapiInterruptDpc(
- IN PVOID HwDeviceExtension
- );
-
-RETTYPE_XXableInterrupts
-NTAPI
-AtapiEnableInterrupts__(
- IN PVOID HwDeviceExtension
- );
-
-VOID
-NTAPI
-AtapiQueueTimerDpc(
- IN PVOID HwDeviceExtension,
- IN ULONG lChannel,
- IN PHW_TIMER HwScsiTimer,
- IN ULONG MiniportTimerValue
- );
-
-SCSI_ADAPTER_CONTROL_STATUS
-NTAPI
-AtapiAdapterControl(
- IN PVOID HwDeviceExtension,
- IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
- IN PVOID Parameters
- );
-
-#endif //UNIATA_CORE
-
-#ifndef UNIATA_CORE
-
-BOOLEAN
-NTAPI
-AtapiRegGetStringParameterValue(
- IN PWSTR RegistryPath,
- IN PWSTR Name,
- IN PWCHAR Str,
- IN ULONG MaxLen
- )
-{
-#define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
- NTSTATUS status;
- RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
- UNICODE_STRING ustr;
-
- ustr.Buffer = Str;
- ustr.Length =
- ustr.MaximumLength = (USHORT)MaxLen;
- RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
-
- parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
- parameters[0].Name = Name;
- parameters[0].EntryContext = &ustr;
- parameters[0].DefaultType = REG_SZ;
- parameters[0].DefaultData = Str;
- parameters[0].DefaultLength = MaxLen;
-
- status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
- RegistryPath, parameters, NULL, NULL);
-
- if(!NT_SUCCESS(status))
- return FALSE;
-
- return TRUE;
-
-#undef ITEMS_TO_QUERY
-} // end AtapiRegGetStringParameterValue()
-
-
-#endif //UNIATA_CORE
-
-VOID
-DDKFASTAPI
-UniataNanoSleep(
- ULONG nano
- )
-{
- LONGLONG t;
- LARGE_INTEGER t0;
-
-#ifdef NAVO_TEST
- return;
-#endif //NAVO_TEST
-
- if(!nano || !g_Perf || !g_PerfDt)
- return;
- t = (g_Perf * nano) / g_PerfDt / 1000;
- if(!t) {
- t = 1;
- }
- do {
- KeQuerySystemTime(&t0);
- t--;
- } while(t);
-} // end UniataNanoSleep()
-
-#define AtapiWritePortN_template(_type, _Type, sz) \
-VOID \
-DDKFASTAPI \
-AtapiWritePort##sz( \
- IN PHW_CHANNEL chan, \
- IN ULONGIO_PTR _port, \
- IN _type data \
- ) \
-{ \
- PIORES res; \
- if(_port >= IDX_MAX_REG) { \
- res = (PIORES)(_port); \
- } else \
- if(chan) { \
- res = &chan->RegTranslation[_port]; \
- } else { \
- KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
- return; \
- } \
- if(res->Proc) { \
- KdPrint(("PROC io write request @ ch %x, res* %x\n", chan, _port)); \
- ASSERT(FALSE); /* We should never get here */ \
- } \
- if(!res->MemIo) { \
- ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
- } else { \
- /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
- ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
- } \
- return; \
-}
-
-AtapiWritePortN_template(ULONG, Ulong, 4);
-AtapiWritePortN_template(USHORT, Ushort, 2);
-AtapiWritePortN_template(UCHAR, Uchar, 1);
-
-#define AtapiWritePortExN_template(_type, _Type, sz) \
-VOID \
-DDKFASTAPI \
-AtapiWritePortEx##sz( \
- IN PHW_CHANNEL chan, \
- IN ULONGIO_PTR _port, \
- IN ULONG offs, \
- IN _type data \
- ) \
-{ \
- PIORES res; \
- if(_port >= IDX_MAX_REG) { \
- res = (PIORES)(_port); \
- } else \
- if(chan) { \
- res = &chan->RegTranslation[_port]; \
- } else { \
- KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
- return; \
- } \
- if(res->Proc) { \
- KdPrint(("PROC io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
- ASSERT(FALSE); /* We should never get here */ \
- } \
- if(!res->MemIo) { \
- ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
- } else { \
- /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
- ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
- } \
- return; \
-}
-
-AtapiWritePortExN_template(ULONG, Ulong, 4);
-//AtapiWritePortExN_template(USHORT, Ushort, 2);
-AtapiWritePortExN_template(UCHAR, Uchar, 1);
-
-#define AtapiReadPortN_template(_type, _Type, sz) \
-_type \
-DDKFASTAPI \
-AtapiReadPort##sz( \
- IN PHW_CHANNEL chan, \
- IN ULONGIO_PTR _port \
- ) \
-{ \
- PIORES res; \
- if(_port >= IDX_MAX_REG) { \
- res = (PIORES)(_port); \
- } else \
- if(chan) { \
- res = &chan->RegTranslation[_port]; \
- } else { \
- KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
- return (_type)(-1); \
- } \
- if(res->Proc) { \
- KdPrint(("PROC io read request @ ch %x, res* %x\n", chan, _port)); \
- ASSERT(FALSE); /* We should never get here */ \
- } \
- if(!res->MemIo) { \
- /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
- return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
- } else { \
- /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
- return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
- } \
-}
-
-AtapiReadPortN_template(ULONG, Ulong, 4);
-AtapiReadPortN_template(USHORT, Ushort, 2);
-AtapiReadPortN_template(UCHAR, Uchar, 1);
-
-#define AtapiReadPortExN_template(_type, _Type, sz) \
-_type \
-DDKFASTAPI \
-AtapiReadPortEx##sz( \
- IN PHW_CHANNEL chan, \
- IN ULONGIO_PTR _port, \
- IN ULONG offs \
- ) \
-{ \
- PIORES res; \
- if(_port >= IDX_MAX_REG) { \
- res = (PIORES)(_port); \
- } else \
- if(chan) { \
- res = &chan->RegTranslation[_port]; \
- } else { \
- KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
- return (_type)(-1); \
- } \
- if(res->Proc) { \
- KdPrint(("PROC io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
- ASSERT(FALSE); /* We should never get here */ \
- } \
- if(!res->MemIo) { \
- return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
- } else { \
- /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
- return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
- } \
-}
-
-AtapiReadPortExN_template(ULONG, Ulong, 4);
-//AtapiReadPortExN_template(USHORT, Ushort, 2);
-AtapiReadPortExN_template(UCHAR, Uchar, 1);
-
-#define AtapiReadPortBufferN_template(_type, _Type, sz) \
-VOID \
-DDKFASTAPI \
-AtapiReadBuffer##sz( \
- IN PHW_CHANNEL chan, \
- IN ULONGIO_PTR _port, \
- IN PVOID Buffer, \
- IN ULONG Count, \
- IN ULONG Timing \
- ) \
-{ \
- PIORES res; \
- \
- if(Timing) { \
- while(Count) { \
- (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
- Count--; \
- Buffer = ((_type*)Buffer)+1; \
- UniataNanoSleep(Timing); \
- } \
- return; \
- } \
- \
- if(_port >= IDX_MAX_REG) { \
- res = (PIORES)(_port); \
- } else \
- if(chan) { \
- res = &chan->RegTranslation[_port]; \
- } else { \
- KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
- return; \
- } \
- if(!res->MemIo) { \
- /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
- ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
- return; \
- } \
- while(Count) { \
- (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
- Count--; \
- Buffer = ((_type*)Buffer)+1; \
- } \
- return; \
-}
-
-#define AtapiWritePortBufferN_template(_type, _Type, sz) \
-VOID \
-DDKFASTAPI \
-AtapiWriteBuffer##sz( \
- IN PHW_CHANNEL chan, \
- IN ULONGIO_PTR _port, \
- IN PVOID Buffer, \
- IN ULONG Count, \
- IN ULONG Timing \
- ) \
-{ \
- PIORES res; \
- \
- if(Timing) { \
- while(Count) { \
- AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
- Buffer = ((_type*)Buffer)+1; \
- Count--; \
- UniataNanoSleep(Timing); \
- } \
- return; \
- } \
- \
- if(_port >= IDX_MAX_REG) { \
- res = (PIORES)(_port); \
- } else \
- if(chan) { \
- res = &chan->RegTranslation[_port]; \
- } else { \
- KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
- return; \
- } \
- if(!res->MemIo) { \
- /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
- ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
- return; \
- } \
- while(Count) { \
- ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
- Count--; \
- Buffer = ((_type*)Buffer)+1; \
- } \
- return; \
-}
-
-AtapiWritePortBufferN_template(ULONG, Ulong, 4);
-AtapiWritePortBufferN_template(USHORT, Ushort, 2);
-
-AtapiReadPortBufferN_template(ULONG, Ulong, 4);
-AtapiReadPortBufferN_template(USHORT, Ushort, 2);
-
-
-UCHAR
-DDKFASTAPI
-AtapiSuckPort2(
- IN PHW_CHANNEL chan
- )
-{
- UCHAR statusByte;
- ULONG i;
-
- // Assume, proper drive is already seleted
- WaitOnBusyLong(chan);
- for (i = 0; i < 0x10000; i++) {
-
- GetStatus(chan, statusByte);
- if (statusByte & IDE_STATUS_DRQ) {
- // Suck out any remaining bytes and throw away.
- AtapiReadPort2(chan, IDX_IO1_i_Data);
- UniataNanoSleep(PIO0_TIMING);
- } else {
- break;
- }
- }
- if(i) {
- KdPrint2((PRINT_PREFIX "AtapiSuckPort2: overrun detected (%#x words)\n", i ));
- }
- return statusByte;
-} // AtapiSuckPort2()
-
-ULONG
-DDKFASTAPI
-AtapiSuckPortBuffer2(
- IN PHW_CHANNEL chan,
- IN PUSHORT Buffer,
- IN ULONG Count
- )
-{
- UCHAR statusByte;
- ULONG i;
- USHORT data;
- BOOLEAN retry = FALSE;
-
- // Assume, proper drive is already seleted
- WaitOnBusyLong(chan);
- for (i = 0; i < Count; i++) {
-
- GetStatus(chan, statusByte);
- if (statusByte & IDE_STATUS_DRQ) {
- // Suck out any remaining bytes and throw away.
- data = AtapiReadPort2(chan, IDX_IO1_i_Data);
- (*Buffer) = data;
- Count--;
- Buffer++;
- UniataNanoSleep(PIO0_TIMING);
- retry = FALSE;
- } else {
- if(i<Count && !retry) {
- KdPrint2((PRINT_PREFIX " wait...\n"));
- WaitForDrq(chan);
- retry = TRUE;
- }
- break;
- }
- }
- if(i) {
- KdPrint2((PRINT_PREFIX "AtapiSuckPortBuffer2: %#x words\n", i ));
- if(i==Count) {
- AtapiSuckPort2(chan);
- }
- }
- return i;
-} // AtapiSuckPortBuffer2()
-
-UCHAR
-DDKFASTAPI
-SelectDrive(
- IN PHW_CHANNEL chan,
- IN ULONG DeviceNumber
- )
-{
- if(!chan) {
- return 0;
- }
-/*
- if(chan->lun[DeviceNumber] &&
- (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_CHANGER)) {
- KdPrint3((" Select %d\n", DeviceNumber));
- }
-*/
- if(chan->last_devsel == DeviceNumber) {
- //KdPrint3((" Selected %d\n", DeviceNumber));
- return 1;
- }
- AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1); \
- chan->last_devsel = DeviceNumber ? 1 : 0;
- if(!g_opt_DriveSelectNanoDelay) {
- //KdPrint3((" Select %d\n", DeviceNumber));
- return 2;
- }
- //KdPrint3((" Select %d (%d ns)\n", DeviceNumber, g_opt_DriveSelectNanoDelay));
- UniataNanoSleep(g_opt_DriveSelectNanoDelay);
- return 2;
-} // end SelectDrive()
-
-UCHAR
-DDKFASTAPI
-WaitOnBusy(
- IN PHW_CHANNEL chan
- )
-{
- ULONG i;
- UCHAR Status;
-
- GetStatus(chan, Status);
- for (i=0; i<g_opt_WaitBusyCount; i++) {
- if (Status & IDE_STATUS_BUSY) {
- AtapiStallExecution(g_opt_WaitBusyDelay);
- GetStatus(chan, Status);
- continue;
- } else {
- break;
- }
- }
- return Status;
-} // end WaitOnBusy()
-
-UCHAR
-DDKFASTAPI
-WaitOnBusyLong(
- IN PHW_CHANNEL chan
- )
-{
- ULONG i;
- UCHAR Status;
-
- Status = WaitOnBusy(chan);
- if(!(Status & IDE_STATUS_BUSY))
- return Status;
- for (i=0; i<g_opt_WaitBusyLongCount; i++) {
- GetStatus(chan, Status);
- if (Status & IDE_STATUS_BUSY) {
- AtapiStallExecution(g_opt_WaitBusyLongDelay);
- continue;
- } else {
- break;
- }
- }
- return Status;
-} // end WaitOnBusyLong()
-
-UCHAR
-DDKFASTAPI
-WaitOnBaseBusy(
- IN PHW_CHANNEL chan
- )
-{
- ULONG i;
- UCHAR Status = IDE_STATUS_WRONG;
- for (i=0; i<g_opt_WaitBusyCount; i++) {
- GetBaseStatus(chan, Status);
- if (Status & IDE_STATUS_BUSY) {
- AtapiStallExecution(g_opt_WaitBusyDelay);
- continue;
- } else {
- break;
- }
- }
- return Status;
-} // end WaitOnBaseBusy()
-
-UCHAR
-DDKFASTAPI
-WaitOnBaseBusyLong(
- IN PHW_CHANNEL chan
- )
-{
- ULONG i;
- UCHAR Status;
-
- Status = WaitOnBaseBusy(chan);
- if(!(Status & IDE_STATUS_BUSY))
- return Status;
- for (i=0; i<2000; i++) {
- GetBaseStatus(chan, Status);
- if (Status & IDE_STATUS_BUSY) {
- AtapiStallExecution(250);
- continue;
- } else {
- break;
- }
- }
- return Status;
-} // end WaitOnBaseBusyLong()
-
-UCHAR
-DDKFASTAPI
-UniataIsIdle(
- IN struct _HW_DEVICE_EXTENSION* deviceExtension,
- IN UCHAR Status
- )
-{
- UCHAR Status2;
-
- if(Status == IDE_STATUS_WRONG) {
- return IDE_STATUS_WRONG;
- }
- if(Status & IDE_STATUS_BUSY) {
- return Status;
- }
-// if(deviceExtension->HwFlags & UNIATA_SATA) {
- if(UniataIsSATARangeAvailable(deviceExtension, 0)) {
- if(Status & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
- return Status;
- }
- } else {
- Status2 = Status & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX);
- if ((Status & IDE_STATUS_BUSY) ||
- (Status2 != IDE_STATUS_IDLE && Status2 != IDE_STATUS_DRDY)) {
- return Status;
- }
- }
- return IDE_STATUS_IDLE;
-} // end UniataIsIdle()
-
-UCHAR
-DDKFASTAPI
-WaitForIdleLong(
- IN PHW_CHANNEL chan
- )
-{
- ULONG i;
- UCHAR Status;
- UCHAR Status2;
- for (i=0; i<20000; i++) {
- GetStatus(chan, Status);
- Status2 = UniataIsIdle(chan->DeviceExtension, Status);
- if(Status2 == IDE_STATUS_WRONG) {
- // no drive ?
- break;
- } else
- if(Status2 & IDE_STATUS_BUSY) {
- AtapiStallExecution(10);
- continue;
- } else {
- break;
- }
- }
- return Status;
-} // end WaitForIdleLong()
-
-UCHAR
-DDKFASTAPI
-WaitForDrq(
- IN PHW_CHANNEL chan
- )
-{
- ULONG i;
- UCHAR Status;
- for (i=0; i<1000; i++) {
- GetStatus(chan, Status);
- if (Status & IDE_STATUS_BUSY) {
- AtapiStallExecution(g_opt_WaitDrqDelay);
- } else if (Status & IDE_STATUS_DRQ) {
- break;
- } else {
- AtapiStallExecution(g_opt_WaitDrqDelay*2);
- }
- }
- return Status;
-} // end WaitForDrq()
-
-UCHAR
-DDKFASTAPI
-WaitShortForDrq(
- IN PHW_CHANNEL chan
- )
-{
- ULONG i;
- UCHAR Status;
- for (i=0; i<2; i++) {
- GetStatus(chan, Status);
- if (Status & IDE_STATUS_BUSY) {
- AtapiStallExecution(g_opt_WaitDrqDelay);
- } else if (Status & IDE_STATUS_DRQ) {
- break;
- } else {
- AtapiStallExecution(g_opt_WaitDrqDelay);
- }
- }
- return Status;
-} // end WaitShortForDrq()
-
-VOID
-DDKFASTAPI
-AtapiSoftReset(
- IN PHW_CHANNEL chan,
- IN ULONG DeviceNumber
- )
-{
- //ULONG c = chan->lChannel;
- ULONG i = 30 * 1000;
- UCHAR dma_status = 0;
- KdPrint2((PRINT_PREFIX "AtapiSoftReset:\n"));
- UCHAR statusByte0, statusByte2;
-
- if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
- UniataAhciSoftReset(chan->DeviceExtension, chan->lChannel, DeviceNumber);
- return;
- }
-
- GetBaseStatus(chan, statusByte2);
- KdPrint2((PRINT_PREFIX " statusByte2 %x:\n", statusByte2));
- SelectDrive(chan, DeviceNumber);
- if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MANUAL_CHS) {
- // For ESDI/MFM
- KdPrint2((PRINT_PREFIX " ESDI/MFM\n"));
- AtapiStallExecution(10000);
- for (i = 0; i < 1000; i++) {
- AtapiStallExecution(999);
- }
-/* } else
- // Seems to be unnecessary, verified by KtP
- if(!hasPCI) {
- // original atapi.sys behavior for old ISA-only hardware
- AtapiStallExecution(10000);
- AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
- for (i = 0; i < 1000; i++) {
- AtapiStallExecution(999);
- } */
- } else {
- AtapiStallExecution(500);
- GetBaseStatus(chan, statusByte2);
- statusByte0 = statusByte2;
- AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
-
- // Do not wait for BUSY assertion if it was initially set, jump to
- // BUSY release wait loop
- if(!(statusByte0 & IDE_STATUS_BUSY)) {
- // Wait for BUSY assertion, in some cases delay may occure
- // 100ms should be enough
- if(g_opt_VirtualMachine == VM_BOCHS) {
- i = 100;
- } else {
- i = 10*1000;
- }
- statusByte2 = AtapiReadPort1(chan, IDX_IO1_i_Status);
- while (!(statusByte2 & IDE_STATUS_BUSY) &&
- i--)
- {
- if(!(statusByte0 & IDE_STATUS_ERROR) && (statusByte2 & IDE_STATUS_ERROR)) {
- KdPrint2((PRINT_PREFIX " Command aborted, statusByte2 %x:\n", statusByte2));
- break;
- }
- 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
- // implementation. (which is around 1 second)
- while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
- i--)
- {
- AtapiStallExecution(30);
- }
- KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n"));
- chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_REINIT_DMA;
- }
-
- chan->last_devsel = -1; // make sure proper drive would be selected
- SelectDrive(chan, DeviceNumber);
- WaitOnBusy(chan);
- GetBaseStatus(chan, statusByte2);
- AtapiStallExecution(500);
-
- GetBaseStatus(chan, statusByte2);
- if(chan && chan->DeviceExtension) {
- dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
- KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
- } else {
- KdPrint2((PRINT_PREFIX " can't get DMA status\n"));
- }
- if(dma_status & BM_STATUS_INTR) {
- // bullshit, we have DMA interrupt, but had never initiate DMA operation
- KdPrint2((PRINT_PREFIX " clear unexpected DMA intr on ATAPI reset\n"));
- AtapiDmaDone(chan->DeviceExtension, DeviceNumber, chan->lChannel, NULL);
- GetBaseStatus(chan, statusByte2);
- }
- if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
- UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, DeviceNumber);
-/* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
- UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
- }*/
- }
- return;
-
-} // end AtapiSoftReset()
-
-VOID
-DDKFASTAPI
-AtapiHardReset(
- IN struct _HW_CHANNEL* chan,
- IN BOOLEAN DisableInterrupts,
- IN ULONG Delay
- )
-{
- KdPrint2((PRINT_PREFIX "AtapiHardReset: %d, dis=%d\n", Delay, DisableInterrupts));
- AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_RESET_CONTROLLER |
- (DisableInterrupts ? IDE_DC_DISABLE_INTERRUPTS : 0));
- chan->last_devsel = -1;
- AtapiStallExecution(Delay);
- AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_REENABLE_CONTROLLER);
-} // end AtapiHardReset()
-
-/*
- Send command to device.
- Translate to 48-Lba form if required
-*/
-UCHAR
-NTAPI
-AtaCommand48(
- IN PHW_DEVICE_EXTENSION deviceExtension,
- IN ULONG DeviceNumber,
- IN ULONG lChannel,
- IN UCHAR command,
- IN ULONGLONG lba,
- IN USHORT count,
- IN USHORT feature,
- IN ULONG wait_flags
- )
-{
- PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
- UCHAR statusByte;
- ULONG i;
- PUCHAR plba;
-
- KdPrint2((PRINT_PREFIX "AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
- deviceExtension->DevIndex, deviceExtension->Channel, DeviceNumber, command, lba, count, feature ));
-
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
-
- KdPrint3((" (ahci)\n"));
-
- statusByte = UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
- (PSCSI_REQUEST_BLOCK)NULL,
- NULL,
- 0,
- command,
- lba, count,
- feature,
- 0 /* ahci flags */ ,
- wait_flags,
- 1000 /* timeout 1 sec */
- );
-
- return statusByte;
- }
-
- SelectDrive(chan, DeviceNumber);
-
- statusByte = WaitOnBusy(chan);
-
- /* ready to issue command ? */
- if (statusByte & IDE_STATUS_BUSY) {
- KdPrint2((PRINT_PREFIX " Returning BUSY status\n"));
- return statusByte;
- }
- // !!! We should not check ERROR condition here
- // ERROR bit may be asserted durring previous operation
- // and not cleared after SELECT
-
- //>>>>>> NV: 2006/08/03
- if(((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp|ATA_CMD_FLAG_FUA)) == ATA_CMD_FLAG_LBAIOsupp) &&
- CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) {
- KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
- return IDE_STATUS_ERROR;
- //return SRB_STATUS_ERROR;
- }
- //<<<<<< NV: 2006/08/03
-
- /* only use 48bit addressing if needed because of the overhead */
- if (UniAta_need_lba48(command, lba, count,
- chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48)) {
-
- KdPrint2((PRINT_PREFIX " dev %#x USE_LBA_48\n", DeviceNumber ));
- /* translate command into 48bit version */
- if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) {
- command = AtaCommands48[command];
- } else {
- KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n"));
- return (UCHAR)-1;
- }
-
- chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
- plba = (PUCHAR)&lba;
-
- AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)(feature>>8));
- AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)feature);
- AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)(count>>8));
- AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)count);
- AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[3]));
- AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[0]));
- AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[4]));
- AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[1]));
- AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[5]));
- AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[2]));
-
- //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
- AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
- } else {
-
- plba = (PUCHAR)&lba; //ktp
- chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
-
- //if(feature ||
- // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
- AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)feature);
- //}
- AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)count);
- AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)plba[0]);
- AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)plba[1]);
- AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)plba[2]);
- if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) {
- //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
- AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
- } else {
- //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
- AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
- }
- }
-
- // write command code to device
- AtapiWritePort1(chan, IDX_IO1_o_Command, command);
-
- switch (wait_flags) {
- case ATA_WAIT_INTR:
-
- // caller requested wait for interrupt
- for(i=0;i<4;i++) {
- WaitOnBusy(chan);
- statusByte = WaitForDrq(chan);
- if (statusByte & IDE_STATUS_DRQ)
- break;
- AtapiStallExecution(500);
- KdPrint2((PRINT_PREFIX " retry waiting DRQ, status %#x\n", statusByte));
- }
-
- return statusByte;
-
- case ATA_WAIT_IDLE:
-
- // caller requested wait for entering Wait state
- for (i=0; i<30 * 1000; i++) {
-
- GetStatus(chan, statusByte);
- statusByte = UniataIsIdle(deviceExtension, statusByte);
- if(statusByte == IDE_STATUS_WRONG) {
- // no drive ?
- break;
- } else
- if(statusByte & IDE_STATUS_ERROR) {
- break;
- } else
- if(statusByte & IDE_STATUS_BUSY) {
- AtapiStallExecution(100);
- continue;
- } else
- if((statusByte & ~IDE_STATUS_INDEX) == IDE_STATUS_IDLE) {
- break;
- } else {
- //if(deviceExtension->HwFlags & UNIATA_SATA) {
- if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- break;
- }
- AtapiStallExecution(100);
- }
- }
- //statusByte |= IDE_STATUS_BUSY;
- break;
-
- case ATA_WAIT_READY:
- statusByte = WaitOnBusyLong(chan);
- break;
- case ATA_WAIT_BASE_READY:
- statusByte = WaitOnBaseBusyLong(chan);
- break;
- case ATA_IMMEDIATE:
- GetStatus(chan, statusByte);
- if (statusByte & IDE_STATUS_ERROR) {
- KdPrint2((PRINT_PREFIX " Warning: Immed Status %#x :(\n", statusByte));
- if(statusByte == (IDE_STATUS_IDLE | IDE_STATUS_ERROR)) {
- break;
- }
- KdPrint2((PRINT_PREFIX " try to continue\n"));
- statusByte &= ~IDE_STATUS_ERROR;
-
- } else {
- //KdPrint2((PRINT_PREFIX " send Status %#x\n", statusByte));
- }
- UniataExpectChannelInterrupt(chan, TRUE);
- // !!!!!
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
-
- statusByte = IDE_STATUS_SUCCESS;
- break;
- }
-
- //KdPrint2((PRINT_PREFIX " Status %#x\n", statusByte));
-
- return statusByte;
-} // end AtaCommand48()
-
-/*
- Send command to device.
- This is simply wrapper for AtaCommand48()
-*/
-UCHAR
-NTAPI
-AtaCommand(
- IN PHW_DEVICE_EXTENSION deviceExtension,
- IN ULONG DeviceNumber,
- IN ULONG lChannel,
- IN UCHAR command,
- IN USHORT cylinder,
- IN UCHAR head,
- IN UCHAR sector,
- IN UCHAR count,
- IN UCHAR feature,
- IN ULONG wait_flags
- )
-{
- if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
- return AtaCommand48(deviceExtension, DeviceNumber, lChannel,
- command,
- (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
- count, feature, wait_flags);
- } else {
- return UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
- (PSCSI_REQUEST_BLOCK)NULL,
- NULL,
- 0,
- command,
- (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
- count,
- feature,
- 0 /* ahci flags */ ,
- wait_flags,
- 1000 /* timeout 1 sec */
- );
-
- }
-} // end AtaCommand()
-
-LONG
-NTAPI
-AtaPio2Mode(LONG pio)
-{
- switch (pio) {
- default: return ATA_PIO;
- case 0: return ATA_PIO0;
- case 1: return ATA_PIO1;
- case 2: return ATA_PIO2;
- case 3: return ATA_PIO3;
- case 4: return ATA_PIO4;
- case 5: return ATA_PIO5;
- }
-} // end AtaPio2Mode()
-
-LONG
-NTAPI
-AtaPioMode(PIDENTIFY_DATA2 ident)
-{
- if (ident->PioTimingsValid) {
- if (ident->AdvancedPIOModes & AdvancedPIOModes_5)
- return 5;
- if (ident->AdvancedPIOModes & AdvancedPIOModes_4)
- return 4;
- if (ident->AdvancedPIOModes & AdvancedPIOModes_3)
- return 3;
- }
- if (ident->PioCycleTimingMode == 2)
- return 2;
- if (ident->PioCycleTimingMode == 1)
- return 1;
- if (ident->PioCycleTimingMode == 0)
- return 0;
- return IOMODE_NOT_SPECIFIED;
-} // end AtaPioMode()
-
-LONG
-NTAPI
-AtaWmode(PIDENTIFY_DATA2 ident)
-{
- if (ident->MultiWordDMASupport & 0x04)
- return 2;
- if (ident->MultiWordDMASupport & 0x02)
- return 1;
- if (ident->MultiWordDMASupport & 0x01)
- return 0;
- return IOMODE_NOT_SPECIFIED;
-} // end AtaWmode()
-
-LONG
-NTAPI
-AtaUmode(PIDENTIFY_DATA2 ident)
-{
- if (!ident->UdmaModesValid)
- return IOMODE_NOT_SPECIFIED;
- if (ident->UltraDMASupport & 0x40)
- return 6;
- if (ident->UltraDMASupport & 0x20)
- return 5;
- if (ident->UltraDMASupport & 0x10)
- return 4;
- if (ident->UltraDMASupport & 0x08)
- return 3;
- if (ident->UltraDMASupport & 0x04)
- return 2;
- if (ident->UltraDMASupport & 0x02)
- return 1;
- if (ident->UltraDMASupport & 0x01)
- return 0;
- return IOMODE_NOT_SPECIFIED;
-} // end AtaUmode()
-
-LONG
-NTAPI
-AtaSAmode(PIDENTIFY_DATA2 ident) {
- if(!ident->SataCapabilities ||
- ident->SataCapabilities == 0xffff) {
- return IOMODE_NOT_SPECIFIED;
- }
- if(ident->SataCapabilities & ATA_SATA_GEN3) {
- return ATA_SA600;
- } else
- if(ident->SataCapabilities & ATA_SATA_GEN2) {
- return ATA_SA300;
- } else
- if(ident->SataCapabilities & ATA_SATA_GEN1) {
- return ATA_SA150;
- }
- return IOMODE_NOT_SPECIFIED;
-} // end AtaSAmode()
-
-#ifndef UNIATA_CORE
-
-VOID
-NTAPI
-AtapiTimerDpc(
- IN PVOID HwDeviceExtension
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PHW_TIMER HwScsiTimer;
- LARGE_INTEGER time;
- ULONG MiniportTimerValue;
- BOOLEAN recall = FALSE;
- ULONG lChannel;
- PHW_CHANNEL chan;
-
- KdPrint2((PRINT_PREFIX "AtapiTimerDpc:\n"));
-
- lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
- if(lChannel == CHAN_NOT_SPECIFIED) {
- KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no items\n"));
- return;
- }
- chan = &(deviceExtension->chan[lChannel]);
-
- while(TRUE) {
-
- HwScsiTimer = chan->HwScsiTimer;
- chan->HwScsiTimer = NULL;
-
- deviceExtension->FirstDpcChan = chan->NextDpcChan;
- if(deviceExtension->FirstDpcChan != CHAN_NOT_SPECIFIED) {
- recall = TRUE;
- }
-
- HwScsiTimer(HwDeviceExtension);
-
- chan->NextDpcChan = CHAN_NOT_SPECIFIED;
-
- lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
- if(lChannel == CHAN_NOT_SPECIFIED) {
- KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no more items\n"));
- deviceExtension->FirstDpcChan =
- deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
- return;
- }
-
- KeQuerySystemTime(&time);
- KdPrint2((PRINT_PREFIX "AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
-
- chan = &deviceExtension->chan[lChannel];
- if(time.QuadPart >= chan->DpcTime - 10) {
- // call now
- KdPrint2((PRINT_PREFIX "AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
- (ULONG)(chan->DpcTime >> 32), (ULONG)(chan->DpcTime)));
- continue;
- }
- break;
- }
-
- if(recall) {
- deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
- MiniportTimerValue = (ULONG)(time.QuadPart - chan->DpcTime)/10;
- if(!MiniportTimerValue)
- MiniportTimerValue = 1;
-
- KdPrint2((PRINT_PREFIX "AtapiTimerDpc: recall AtapiTimerDpc\n"));
- ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
- AtapiTimerDpc,
- MiniportTimerValue
- );
- }
- return;
-
-} // end AtapiTimerDpc()
-
-/*
- Wrapper for ScsiPort, that implements smart Dpc
- queueing. We need it to allow parallel functioning
- of IDE channels with shared interrupt. Standard Dpc mechanism
- cancels previous Dpc request (if any), but we need Dpc queue.
-*/
-VOID
-NTAPI
-AtapiQueueTimerDpc(
- IN PVOID HwDeviceExtension,
- IN ULONG lChannel,
- IN PHW_TIMER HwScsiTimer,
- IN ULONG MiniportTimerValue
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- LARGE_INTEGER time;
- LARGE_INTEGER time2;
- ULONG i;
- PHW_CHANNEL prev_chan;
- PHW_CHANNEL chan;
-// BOOLEAN UseRequestTimerCall = TRUE;
-
- KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
- KeQuerySystemTime(&time);
- time2 = time;
- KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
- time.QuadPart += MiniportTimerValue*10;
- KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time.HighPart, time.LowPart));
-
- KdPrint2((PRINT_PREFIX " ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension->ActiveDpcChan, deviceExtension->FirstDpcChan));
-
- i = deviceExtension->FirstDpcChan;
- chan = prev_chan = NULL;
- while(i != CHAN_NOT_SPECIFIED) {
- prev_chan = chan;
- chan = &(deviceExtension->chan[i]);
- if(chan->DpcTime > time.QuadPart) {
- break;
- }
- i = chan->NextDpcChan;
- }
- chan = &(deviceExtension->chan[lChannel]);
- if(!prev_chan) {
- deviceExtension->FirstDpcChan = lChannel;
- } else {
- prev_chan->NextDpcChan = lChannel;
- }
- chan->NextDpcChan = i;
- chan->HwScsiTimer = HwScsiTimer;
- chan->DpcTime = time.QuadPart;
-
- KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2.HighPart, time2.LowPart));
- if(time.QuadPart <= time2.QuadPart) {
- MiniportTimerValue = 1;
- } else {
- MiniportTimerValue = (ULONG)((time.QuadPart - time2.QuadPart) / 10);
- }
-
- KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
- ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
- AtapiTimerDpc,
- MiniportTimerValue);
-
-} // end AtapiQueueTimerDpc()
-
-#endif //UNIATA_CORE
-
-#ifdef _DEBUG
-VOID
-NTAPI
-UniataDumpATARegs(
- IN PHW_CHANNEL chan
- )
-{
- ULONG j;
- UCHAR statusByteAlt;
-
- GetStatus(chan, statusByteAlt);
- KdPrint2((PRINT_PREFIX " AltStatus (%#x)\n", statusByteAlt));
-
- for(j=1; j<IDX_IO1_SZ; j++) {
- statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
- KdPrint2((PRINT_PREFIX
- " Reg_%#x (%#x) = %#x\n",
- j,
- chan->RegTranslation[IDX_IO1+j].Addr,
- statusByteAlt));
- }
- if(!chan->RegTranslation[IDX_BM_IO].Addr) {
- return;
- }
- for(j=0; j<IDX_BM_IO_SZ-1; j++) {
- statusByteAlt = AtapiReadPort1(chan, IDX_BM_IO+j);
- KdPrint2((PRINT_PREFIX
- " BM_%#x (%#x) = %#x\n",
- j,
- chan->RegTranslation[IDX_BM_IO+j].Addr,
- statusByteAlt));
- }
- return;
-} // end UniataDumpATARegs()
-#endif //_DEBUG
-
-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:
-
- Issue IDENTIFY command to a device.
-
-Arguments:
-
- HwDeviceExtension - HBA miniport driver's adapter data storage
- DeviceNumber - Indicates which device.
- Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
-
-Return Value:
-
- TRUE if all goes well.
-
---*/
-BOOLEAN
-NTAPI
-IssueIdentify(
- IN PVOID HwDeviceExtension,
- IN ULONG DeviceNumber,
- IN ULONG lChannel,
- IN UCHAR Command,
- IN BOOLEAN NoSetup
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
- ULONG waitCount = 50000;
- ULONG j;
- UCHAR statusByte;
- //UCHAR statusByte2;
- UCHAR signatureLow,
- signatureHigh;
- BOOLEAN atapiDev = FALSE;
- BOOLEAN use_ahci = FALSE;
- PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
-
- use_ahci = UniataIsSATARangeAvailable(deviceExtension, lChannel) &&
- (deviceExtension->HwFlags & UNIATA_AHCI);
-
- if(chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) {
- if(chan->PmLunMap & (1 << DeviceNumber)) {
- // OK
- } else {
- KdPrint2((PRINT_PREFIX "IssueIdentify: PM empty port\n"));
- return FALSE;
- }
- } else
- if(DeviceNumber && (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: NO SLAVE\n"));
- return FALSE;
- }
- if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: HIDDEN\n"));
- return FALSE;
- }
-
- if(use_ahci) {
- statusByte = WaitOnBusyLong(chan);
-#ifdef _DEBUG
- if(!chan->AhciInternalAtaReq) {
- KdPrint2((PRINT_PREFIX "!AhciInternalAtaReq\n"));
- }
-#endif
- } else {
- SelectDrive(chan, DeviceNumber);
- AtapiStallExecution(10);
- statusByte = WaitOnBusyLong(chan);
- // Check that the status register makes sense.
- GetBaseStatus(chan, statusByte);
- /*
- // unnecessary
- if(!hasPCI) {
- // original atapi.sys behavior for old ISA-only hardware
- AtapiStallExecution(100);
- }
- */
- }
-
- if (Command == IDE_COMMAND_IDENTIFY) {
- // Mask status byte ERROR bits.
- statusByte = UniataIsIdle(deviceExtension, statusByte & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX));
- KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte));
- // Check if register value is reasonable.
-
- if(statusByte != IDE_STATUS_IDLE) {
-
- // No reset here !!!
- KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
-
- //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
- if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- SelectDrive(chan, DeviceNumber);
- WaitOnBusyLong(chan);
-
- signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
-
- if (signatureLow == ATAPI_MAGIC_LSB &&
- signatureHigh == ATAPI_MAGIC_MSB) {
- // Device is Atapi.
- KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber));
- return FALSE;
- }
-
- // We really should wait up to 31 seconds
- // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
- // (30 seconds for device 1)
- do {
- // Wait for Busy to drop.
- AtapiStallExecution(100);
- GetStatus(chan, statusByte);
- if(statusByte == IDE_STATUS_WRONG) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber));
- return FALSE;
- }
-
- } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
- GetBaseStatus(chan, statusByte);
-
- SelectDrive(chan, DeviceNumber);
- } else {
- GetBaseStatus(chan, statusByte);
- }
- // Another check for signature, to deal with one model Atapi that doesn't assert signature after
- // a soft reset.
- signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
-
- if (signatureLow == ATAPI_MAGIC_LSB &&
- signatureHigh == ATAPI_MAGIC_MSB) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber));
- // Device is Atapi.
- return FALSE;
- }
-
- statusByte = UniataIsIdle(deviceExtension, statusByte) & ~IDE_STATUS_INDEX;
- if (statusByte != IDE_STATUS_IDLE) {
- // Give up on this.
- KdPrint2((PRINT_PREFIX "IssueIdentify: no dev (dev %d)\n", DeviceNumber));
- return FALSE;
- }
- }
- } else {
- KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte));
- if(statusByte == IDE_STATUS_WRONG) {
- return FALSE;
- }
- //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
- if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- statusByte = WaitForIdleLong(chan);
- KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte));
- }
- atapiDev = TRUE;
- }
-
-// if(deviceExtension->HwFlags & UNIATA_SATA) {
- if(use_ahci) {
- statusByte = UniataAhciSendPIOCommand(HwDeviceExtension, lChannel, DeviceNumber,
- (PSCSI_REQUEST_BLOCK)NULL,
- (PUCHAR)(&deviceExtension->FullIdentifyData),
- DEV_BSIZE,
- Command,
- 0, 0,
- 0,
- 0 /* ahci flags */ ,
- ATA_WAIT_INTR,
- 1000 /* timeout 1 sec */
- );
- j = 9; // AHCI is rather different, skip loop at all
- } else
- if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
- j = 9; // don't send IDENTIFY, assume it is not supported
- KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS\n"));
- RtlZeroMemory(&(deviceExtension->FullIdentifyData), sizeof(deviceExtension->FullIdentifyData));
- RtlCopyMemory(&(deviceExtension->FullIdentifyData), &(LunExt->IdentifyData), sizeof(LunExt->IdentifyData));
- } else
- if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- j = 4; // skip old-style checks
- } else {
- j = 0;
- }
- for (; j < 4*2; j++) {
- // 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
-
- if (!statusByte) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: 0-status, not present\n"));
- return FALSE;
- } else
- if (statusByte & IDE_STATUS_DRQ) {
- // Read status to acknowledge any interrupts generated.
- KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte));
- GetBaseStatus(chan, statusByte);
- // One last check for Atapi.
- if (Command == IDE_COMMAND_IDENTIFY) {
- signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
-
- if (signatureLow == ATAPI_MAGIC_LSB &&
- signatureHigh == ATAPI_MAGIC_MSB) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber));
- // Device is Atapi.
- return FALSE;
- }
- }
- break;
- } else {
- KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte));
- if (Command == IDE_COMMAND_IDENTIFY) {
- // Check the signature. If DRQ didn't come up it's likely Atapi.
- signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
-
- if (signatureLow == ATAPI_MAGIC_LSB &&
- signatureHigh == ATAPI_MAGIC_MSB) {
- // Device is Atapi.
- KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber));
- return FALSE;
- }
- } else {
- if(!(statusByte & IDE_STATUS_ERROR) && (statusByte & IDE_STATUS_BUSY)) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
- break;
- }
- }
- // 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);
- AtapiSoftReset(chan,DeviceNumber);
-
- AtapiDisableInterrupts(deviceExtension, lChannel);
- AtapiEnableInterrupts(deviceExtension, lChannel);
-
- GetBaseStatus(chan, statusByte);
- //GetStatus(chan, statusByte);
- KdPrint2((PRINT_PREFIX "IssueIdentify: Status after soft reset (%#x)\n", statusByte));
- }
- }
- // Check for error on really stupid master devices that assert random
- // patterns of bits in the status register at the slave address.
- if ((Command == IDE_COMMAND_IDENTIFY) && (statusByte & IDE_STATUS_ERROR)) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: Exit on error (%#x)\n", statusByte));
- return FALSE;
- }
-
- if(use_ahci) {
- // everything should already be done by controller
- } else
- if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
- j = 9; // don't send IDENTIFY, assume it is not supported
- KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS (2)\n"));
- statusByte = WaitForDrq(chan);
- statusByte = WaitOnBusyLong(chan);
- KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
- GetBaseStatus(chan, statusByte);
- } else {
-
- KdPrint2((PRINT_PREFIX "IssueIdentify: Status before read words %#x\n", statusByte));
- // Suck out 256 words. After waiting for one model that asserts busy
- // after receiving the Packet Identify command.
- statusByte = WaitForDrq(chan);
- statusByte = WaitOnBusyLong(chan);
- KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
-
- if (!(statusByte & IDE_STATUS_DRQ)) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte));
- GetBaseStatus(chan, statusByte);
- return FALSE;
- }
- GetBaseStatus(chan, statusByte);
- KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte));
-
-#ifdef _DEBUG
- if(atapiDev) {
- j = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
- KdPrint3((PRINT_PREFIX "IssueIdentify: iReason %x\n", j));
-
- j =
- AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
-
- j |=
- (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
- KdPrint3((PRINT_PREFIX "IssueIdentify: wCount %x\n", j));
-
- }
-#endif //_DEBUG
-
- if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
-
- KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
- // 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
- // spacifying manual delay in the way you see below.
- ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
-
- // 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));
- statusByte = AtapiSuckPort2(chan);
- } else {
- KdPrint2((PRINT_PREFIX " use 32bit IO\n"));
- ReadBuffer2(chan, (PULONG)&deviceExtension->FullIdentifyData, 256/2, PIO0_TIMING);
- }
-
- KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
- statusByte = WaitForDrq(chan);
- KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
- GetBaseStatus(chan, statusByte);
- }
- KdPrint2((PRINT_PREFIX "IssueIdentify: Status after read words %#x\n", statusByte));
-
- if(NoSetup) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: no setup, exiting\n"));
- return TRUE;
- }
-
- KdPrint2((PRINT_PREFIX "Model: %20.20s\n", deviceExtension->FullIdentifyData.ModelNumber));
- KdPrint2((PRINT_PREFIX "FW: %4.4s\n", deviceExtension->FullIdentifyData.FirmwareRevision));
- KdPrint2((PRINT_PREFIX "S/N: %20.20s\n", deviceExtension->FullIdentifyData.SerialNumber));
- if(g_opt_VirtualMachine == VM_AUTO) {
- if((deviceExtension->FullIdentifyData.FirmwareRevision[0] == 0 ||
- deviceExtension->FullIdentifyData.FirmwareRevision[0] == ' ') &&
- (deviceExtension->FullIdentifyData.FirmwareRevision[1] == 0 ||
- deviceExtension->FullIdentifyData.FirmwareRevision[1] == ' ')) {
- // Check for BOCHS VM signature. If no additional PCI devices (e.g. VGA)
- // are declared BOCHS looks like regular PC
- if (!atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDH00", 6)) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS HDD\n"));
- g_opt_VirtualMachine = VM_BOCHS;
- } else
- if (atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDC00", 6)) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS CD\n"));
- g_opt_VirtualMachine = VM_BOCHS;
- }
- }
- }
-
- KdPrint2((PRINT_PREFIX "Pio: %x\n", deviceExtension->FullIdentifyData.PioCycleTimingMode));
- if(deviceExtension->FullIdentifyData.PioTimingsValid) {
- KdPrint2((PRINT_PREFIX "APio: %x\n", deviceExtension->FullIdentifyData.AdvancedPIOModes));
- }
- 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/%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",
- deviceExtension->FullIdentifyData.SataSupport,
- deviceExtension->FullIdentifyData.SataCapabilities));
-
- LunExt->LimitedTransferMode =
- 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\n",
- deviceExtension->FullIdentifyData.CfAdvPowerMode
- ));
-
- KdPrint2((PRINT_PREFIX "PowerMngt %d/%d, APM %d/%d\n",
- deviceExtension->FullIdentifyData.FeaturesEnabled.PowerMngt,
- deviceExtension->FullIdentifyData.FeaturesSupport.PowerMngt,
- deviceExtension->FullIdentifyData.FeaturesEnabled.APM,
- deviceExtension->FullIdentifyData.FeaturesSupport.APM
- ));
-
- // Check out a few capabilities / limitations of the device.
- if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
- // Determine if this drive supports the MSN functions.
- KdPrint2((PRINT_PREFIX "IssueIdentify: Marking drive %d as removable. SFE = %d\n",
- DeviceNumber,
- deviceExtension->FullIdentifyData.RemovableStatus));
- LunExt->DeviceFlags |= DFLAGS_REMOVABLE_DRIVE;
- }
- if(use_ahci) {
- // AHCI doesn't recommend using PIO and multiblock
- LunExt->MaximumBlockXfer = 0;
- } else
- if (deviceExtension->FullIdentifyData.MaximumBlockTransfer) {
- // Determine max. block transfer for this device.
- LunExt->MaximumBlockXfer =
- (UCHAR)(deviceExtension->FullIdentifyData.MaximumBlockTransfer & 0xFF);
- }
- LunExt->NumOfSectors = 0;
- if (Command == IDE_COMMAND_IDENTIFY) {
- ULONGLONG NumOfSectors=0;
- ULONGLONG NativeNumOfSectors=0;
- ULONGLONG cylinders=0;
- ULONGLONG tmp_cylinders=0;
-
- KdPrint2((PRINT_PREFIX "PhysLogSectorSize %#x, %#x, offset %#x\n",
- deviceExtension->FullIdentifyData.PhysLogSectorSize,
- deviceExtension->FullIdentifyData.LargeSectorSize,
- deviceExtension->FullIdentifyData.LogicalSectorOffset
- ));
-
- KdPrint2((PRINT_PREFIX "NV PM_Sup %d, PM_En %d, En %d, PM ver %#x ver %#x\n",
- deviceExtension->FullIdentifyData.NVCache_PM_Supported,
- deviceExtension->FullIdentifyData.NVCache_PM_Enabled,
- deviceExtension->FullIdentifyData.NVCache_Enabled,
- deviceExtension->FullIdentifyData.NVCache_PM_Version,
- deviceExtension->FullIdentifyData.NVCache_Version
- ));
-
- KdPrint2((PRINT_PREFIX "R-rate %d\n",
- deviceExtension->FullIdentifyData.NominalMediaRotationRate
- ));
- KdPrint2((PRINT_PREFIX "WC %d/%d, LA %d/%d, WB %d/%d, RB %d/%d, Q %d/%d\n",
- deviceExtension->FullIdentifyData.FeaturesEnabled.WriteCache,
- deviceExtension->FullIdentifyData.FeaturesSupport.WriteCache,
- deviceExtension->FullIdentifyData.FeaturesEnabled.LookAhead,
- deviceExtension->FullIdentifyData.FeaturesSupport.LookAhead,
- deviceExtension->FullIdentifyData.FeaturesEnabled.WriteBuffer,
- deviceExtension->FullIdentifyData.FeaturesSupport.WriteBuffer,
- deviceExtension->FullIdentifyData.FeaturesEnabled.ReadBuffer,
- deviceExtension->FullIdentifyData.FeaturesSupport.ReadBuffer,
- deviceExtension->FullIdentifyData.FeaturesEnabled.Queued,
- deviceExtension->FullIdentifyData.FeaturesSupport.Queued
- ));
-
- KdPrint2((PRINT_PREFIX "Protected %d/%d status %#x, rev %#x\n",
- deviceExtension->FullIdentifyData.FeaturesEnabled.Protected,
- deviceExtension->FullIdentifyData.FeaturesSupport.Protected,
- deviceExtension->FullIdentifyData.SecurityStatus,
- deviceExtension->FullIdentifyData.MasterPasswdRevision
- ));
-
- // Read very-old-style drive geometry
- KdPrint2((PRINT_PREFIX "CHS %#x:%#x:%#x\n",
- deviceExtension->FullIdentifyData.NumberOfCylinders,
- deviceExtension->FullIdentifyData.NumberOfHeads,
- deviceExtension->FullIdentifyData.SectorsPerTrack
- ));
- NumOfSectors = deviceExtension->FullIdentifyData.NumberOfCylinders *
- deviceExtension->FullIdentifyData.NumberOfHeads *
- deviceExtension->FullIdentifyData.SectorsPerTrack;
- KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
- // Check for HDDs > 8Gb
- if ((deviceExtension->FullIdentifyData.NumberOfCylinders == 0x3fff) &&
-/* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
- deviceExtension->FullIdentifyData.NumberOfHeads &&
- deviceExtension->FullIdentifyData.SectorsPerTrack &&
- (NumOfSectors < deviceExtension->FullIdentifyData.UserAddressableSectors)) {
- KdPrint2((PRINT_PREFIX "NumberOfCylinders == 0x3fff\n"));
- cylinders =
- (deviceExtension->FullIdentifyData.UserAddressableSectors /
- (deviceExtension->FullIdentifyData.NumberOfHeads *
- deviceExtension->FullIdentifyData.SectorsPerTrack));
-
- KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
-
- NumOfSectors = cylinders *
- deviceExtension->FullIdentifyData.NumberOfHeads *
- deviceExtension->FullIdentifyData.SectorsPerTrack;
-
- KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
- } else {
-
- }
- // Check for LBA mode
- KdPrint2((PRINT_PREFIX "SupportLba flag %#x\n", deviceExtension->FullIdentifyData.SupportLba));
- KdPrint2((PRINT_PREFIX "SupportDMA flag %#x\n", deviceExtension->FullIdentifyData.SupportDma));
- KdPrint2((PRINT_PREFIX "SoftReset %#x\n", deviceExtension->FullIdentifyData.SoftReset));
- KdPrint2((PRINT_PREFIX "SupportIordy %#x, DisableIordy %#x\n",
- deviceExtension->FullIdentifyData.SupportIordy,
- deviceExtension->FullIdentifyData.DisableIordy
- ));
- KdPrint2((PRINT_PREFIX "MajorRevision %#x\n", deviceExtension->FullIdentifyData.MajorRevision));
- KdPrint2((PRINT_PREFIX "UserAddressableSectors %#x\n", deviceExtension->FullIdentifyData.UserAddressableSectors));
- if ( deviceExtension->FullIdentifyData.SupportLba
- ||
- (deviceExtension->FullIdentifyData.MajorRevision &&
-/* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
- deviceExtension->FullIdentifyData.UserAddressableSectors)) {
- KdPrint2((PRINT_PREFIX "LBA mode\n"));
- LunExt->DeviceFlags |= DFLAGS_LBA_ENABLED;
- } else {
- KdPrint2((PRINT_PREFIX "Keep orig geometry\n"));
- LunExt->DeviceFlags |= DFLAGS_ORIG_GEOMETRY;
- goto skip_lba_staff;
- }
- // Check for LBA48 support
- if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
- if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48 &&
- deviceExtension->FullIdentifyData.FeaturesEnabled.Address48 &&
- deviceExtension->FullIdentifyData.NumberOfHeads &&
- deviceExtension->FullIdentifyData.SectorsPerTrack &&
- (deviceExtension->FullIdentifyData.UserAddressableSectors48 > NumOfSectors)
- ) {
- KdPrint2((PRINT_PREFIX "LBA48\n"));
- cylinders =
- (deviceExtension->FullIdentifyData.UserAddressableSectors48 /
- (deviceExtension->FullIdentifyData.NumberOfHeads *
- deviceExtension->FullIdentifyData.SectorsPerTrack));
-
- KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
-
- NativeNumOfSectors = cylinders *
- deviceExtension->FullIdentifyData.NumberOfHeads *
- deviceExtension->FullIdentifyData.SectorsPerTrack;
-
- KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
-
- if(NativeNumOfSectors > NumOfSectors) {
- KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
- NumOfSectors = NativeNumOfSectors;
- }
- }
-
- // Check drive capacity report for LBA48-capable drives.
- if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48) {
- ULONG hNativeNumOfSectors;
- KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
-
- statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
- IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
-
- if(!(statusByte & IDE_STATUS_ERROR)) {
- if(use_ahci) {
- NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
- } else {
- NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
- ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
- ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) ;
-
- AtapiWritePort1(chan, IDX_IO2_o_Control,
- IDE_DC_USE_HOB );
-
- KdPrint2((PRINT_PREFIX "Read high order bytes\n"));
- NativeNumOfSectors |=
- (ULONG)((ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24 );
- hNativeNumOfSectors=
- (ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) |
- ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 8) ;
- ((PULONG)&NativeNumOfSectors)[1] = hNativeNumOfSectors;
- }
- KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
-
- // Some drives report LBA48 capability while has capacity below 128Gb
- // Probably they support large block-counters.
- // But the problem is that some of them reports higher part of Max LBA equal to lower part.
- // Here we check this
- if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
- KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!!\n"));
-
- statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
- IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
-
- if(!(statusByte & IDE_STATUS_ERROR)) {
- if(use_ahci) {
- NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
- } else {
- NativeNumOfSectors = (ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
- ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24) |
- ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8 ) |
- ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 32) |
- ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
- ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 40)
- ;
- }
- }
-
- if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
- KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!! (2)\n"));
- NativeNumOfSectors = 0;
- }
- }
-
- if(NumOfSectors <= ATA_MAX_LBA28 &&
- NativeNumOfSectors > NumOfSectors) {
-
- KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
- KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
-
- statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
- IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
- if(!(statusByte & IDE_STATUS_ERROR)) {
- NumOfSectors = NativeNumOfSectors;
- }
- }
- } // !error
- }
-
- if(NumOfSectors < 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
- // check for native LBA size
- // some drives report ~32Gb in Identify Block
- KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
-
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_READ_NATIVE_SIZE,
- 0, IDE_USE_LBA, 0, 0, 0, ATA_WAIT_READY);
-
- if(!(statusByte & IDE_STATUS_ERROR)) {
- if(use_ahci) {
- NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
- } else {
- NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
- ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
- ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
- (((ULONG)AtapiReadPort1(chan, IDX_IO1_i_DriveSelect) & 0xf) << 24);
- }
- KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
-
- if(NativeNumOfSectors > NumOfSectors) {
-
- KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
- KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
-
- statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
- IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
- if(!(statusByte & IDE_STATUS_ERROR)) {
- NumOfSectors = NativeNumOfSectors;
- }
- }
- }
- }
-
- } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
-
- // fill IdentifyData with bogus geometry
- KdPrint2((PRINT_PREFIX "requested LunExt->GeomType=%x\n", LunExt->opt_GeomType));
- if(deviceExtension->FullIdentifyData.CurrentSectorsPerTrack &&
- deviceExtension->FullIdentifyData.NumberOfCurrentHeads) {
- tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *
- deviceExtension->FullIdentifyData.NumberOfCurrentHeads);
- } else
- if(deviceExtension->FullIdentifyData.SectorsPerTrack &&
- deviceExtension->FullIdentifyData.NumberOfHeads) {
- KdPrint2((PRINT_PREFIX "Current C/H = %#I64x/%#I64x\n",
- deviceExtension->FullIdentifyData.CurrentSectorsPerTrack,
- deviceExtension->FullIdentifyData.NumberOfCurrentHeads));
- tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.SectorsPerTrack *
- deviceExtension->FullIdentifyData.NumberOfHeads);
- } else {
- tmp_cylinders = 0;
- }
- KdPrint2((PRINT_PREFIX "tmp_cylinders = %#I64x\n", tmp_cylinders));
- if((tmp_cylinders < 0xffff) || (LunExt->opt_GeomType == GEOM_ORIG)) {
- // ok, we can keep original values
- if(LunExt->opt_GeomType == GEOM_AUTO) {
- LunExt->opt_GeomType = GEOM_ORIG;
- }
- } else {
- tmp_cylinders = NumOfSectors / (255*63);
- if(tmp_cylinders < 0xffff) {
- // we can use generic values for H/S for generic geometry approach
- if(LunExt->opt_GeomType == GEOM_AUTO) {
- LunExt->opt_GeomType = GEOM_STD;
- }
- } else {
- // we should use UNIATA geometry approach
- if(LunExt->opt_GeomType == GEOM_AUTO) {
- LunExt->opt_GeomType = GEOM_UNIATA;
- }
- }
- }
-
- if(!deviceExtension->FullIdentifyData.SectorsPerTrack ||
- !deviceExtension->FullIdentifyData.NumberOfHeads) {
- KdPrint2((PRINT_PREFIX "Zero S/H -> Force Use GEOM_STD\n"));
- }
-
- if(LunExt->opt_GeomType == GEOM_STD) {
- deviceExtension->FullIdentifyData.CurrentSectorsPerTrack =
- deviceExtension->FullIdentifyData.SectorsPerTrack = 63;
-
- deviceExtension->FullIdentifyData.NumberOfCurrentHeads =
- deviceExtension->FullIdentifyData.NumberOfHeads = 255;
-
- cylinders = NumOfSectors / (255*63);
- KdPrint2((PRINT_PREFIX "Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders, 255, 63));
- } else
- if(LunExt->opt_GeomType == GEOM_UNIATA) {
- while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x80)) {
- cylinders /= 2;
- KdPrint2((PRINT_PREFIX "cylinders /= 2\n"));
- deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
- deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
- }
- while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x80)) {
- cylinders /= 2;
- KdPrint2((PRINT_PREFIX "cylinders /= 2 (2)\n"));
- deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
- deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
- }
- while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x8000)) {
- cylinders /= 2;
- KdPrint2((PRINT_PREFIX "cylinders /= 2 (3)\n"));
- deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
- deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
- }
- while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x8000)) {
- cylinders /= 2;
- KdPrint2((PRINT_PREFIX "cylinders /= 2 (4)\n"));
- deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
- deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
- }
- KdPrint2((PRINT_PREFIX "Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders,
- deviceExtension->FullIdentifyData.NumberOfCurrentHeads,
- deviceExtension->FullIdentifyData.CurrentSectorsPerTrack));
- }
- if(!cylinders) {
- KdPrint2((PRINT_PREFIX "cylinders = tmp_cylinders (%x = %x)\n", cylinders, tmp_cylinders));
- cylinders = tmp_cylinders;
- }
- deviceExtension->FullIdentifyData.NumberOfCurrentCylinders =
- deviceExtension->FullIdentifyData.NumberOfCylinders = (USHORT)cylinders;
-
-skip_lba_staff:
-
- KdPrint2((PRINT_PREFIX "Geometry: C %#x (%#x)\n",
- deviceExtension->FullIdentifyData.NumberOfCylinders,
- deviceExtension->FullIdentifyData.NumberOfCurrentCylinders
- ));
- KdPrint2((PRINT_PREFIX "Geometry: H %#x (%#x)\n",
- deviceExtension->FullIdentifyData.NumberOfHeads,
- deviceExtension->FullIdentifyData.NumberOfCurrentHeads
- ));
- KdPrint2((PRINT_PREFIX "Geometry: S %#x (%#x)\n",
- deviceExtension->FullIdentifyData.SectorsPerTrack,
- deviceExtension->FullIdentifyData.CurrentSectorsPerTrack
- ));
-
- if(NumOfSectors) {
- LunExt->NumOfSectors = NumOfSectors;
- }
- if(deviceExtension->FullIdentifyData.MajorRevision &&
- deviceExtension->FullIdentifyData.DoubleWordIo) {
- LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
- KdPrint2((PRINT_PREFIX "IssueIdentify: DWORDIO supported\n"));
- }
- } else {
- // ATAPI
- if(deviceExtension->FullIdentifyData.MajorRevision &&
- deviceExtension->FullIdentifyData.DoubleWordIo) {
- LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
- KdPrint2((PRINT_PREFIX "IssueIdentify: DFLAGS_DWORDIO_ENABLED.\n"));
- }
- if(deviceExtension->FullIdentifyData.AtapiDMA.DMADirRequired) {
- KdPrint2((PRINT_PREFIX "DMADirRequired.\n"));
- }
- if(deviceExtension->FullIdentifyData.AtapiByteCount0) {
- KdPrint2((PRINT_PREFIX "AtapiByteCount0=%x\n", deviceExtension->FullIdentifyData.AtapiByteCount0));
- }
- }
-
- ScsiPortMoveMemory(&LunExt->IdentifyData,
- &deviceExtension->FullIdentifyData,sizeof(IDENTIFY_DATA2));
-
- InitBadBlocks(LunExt);
-
- if ((LunExt->IdentifyData.DrqType & ATAPI_DRQT_INTR) &&
- (Command != IDE_COMMAND_IDENTIFY)) {
-
- // This device interrupts with the assertion of DRQ after receiving
- // Atapi Packet Command
- LunExt->DeviceFlags |= DFLAGS_INT_DRQ;
- KdPrint2((PRINT_PREFIX "IssueIdentify: Device interrupts on assertion of DRQ.\n"));
-
- } else {
- KdPrint2((PRINT_PREFIX "IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
- }
-
- if(Command != IDE_COMMAND_IDENTIFY) {
- // ATAPI branch
- if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_TAPE) {
- // This is a tape.
- LunExt->DeviceFlags |= DFLAGS_TAPE_DEVICE;
- KdPrint2((PRINT_PREFIX "IssueIdentify: Device is a tape drive.\n"));
- } else
- if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM ||
- LunExt->IdentifyData.DeviceType == ATAPI_TYPE_OPTICAL) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: Device is CD/Optical drive.\n"));
- // set CD default costs
- LunExt->RwSwitchCost = REORDER_COST_SWITCH_RW_CD;
- LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_CD;
- LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_CD;
- statusByte = WaitForDrq(chan);
- } else {
- KdPrint2((PRINT_PREFIX "IssueIdentify: ATAPI drive type %#x.\n",
- LunExt->IdentifyData.DeviceType));
- }
- KdPrint2((PRINT_PREFIX "IssueIdentify: AtapiCmdSize %#x\n", deviceExtension->FullIdentifyData.AtapiCmdSize));
- } else {
- KdPrint2((PRINT_PREFIX "IssueIdentify: hard drive.\n"));
- }
-
- GetBaseStatus(chan, statusByte);
- KdPrint2((PRINT_PREFIX "IssueIdentify: final Status on exit (%#x)\n", statusByte));
- return TRUE;
-
-} // end IssueIdentify()
-
-
-/*++
-
-Routine Description:
- Set drive parameters using the IDENTIFY data.
-
-Arguments:
- HwDeviceExtension - HBA miniport driver's adapter data storage
- DeviceNumber - Indicates which device.
-
-Return Value:
- TRUE if all goes well.
-
---*/
-BOOLEAN
-NTAPI
-SetDriveParameters(
- IN PVOID HwDeviceExtension,
- IN ULONG DeviceNumber,
- IN ULONG lChannel
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PIDENTIFY_DATA2 identifyData;
- PHW_LU_EXTENSION LunExt;
-// ULONG i;
- UCHAR statusByte;
- UCHAR errorByte;
-
- LunExt = deviceExtension->chan[lChannel].lun[DeviceNumber];
- identifyData = &(LunExt->IdentifyData);
-
- if(LunExt->DeviceFlags &
- (DFLAGS_LBA_ENABLED | DFLAGS_ORIG_GEOMETRY))
- return TRUE;
-
- KdPrint2((PRINT_PREFIX "SetDriveParameters: Number of heads %#x\n", identifyData->NumberOfHeads));
- KdPrint2((PRINT_PREFIX "SetDriveParameters: Sectors per track %#x\n", identifyData->SectorsPerTrack));
-
- // Send SET PARAMETER command.
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
- IDE_COMMAND_SET_DRIVE_PARAMETERS, 0,
- (identifyData->NumberOfHeads - 1), 0,
- (UCHAR)identifyData->SectorsPerTrack, 0, ATA_WAIT_IDLE);
-
- statusByte = UniataIsIdle(deviceExtension, statusByte);
- if(statusByte & IDE_STATUS_ERROR) {
- errorByte = AtapiReadPort1(&deviceExtension->chan[lChannel], IDX_IO1_i_Error);
- KdPrint2((PRINT_PREFIX "SetDriveParameters: Error bit set. Status %#x, error %#x\n",
- errorByte, statusByte));
- return FALSE;
- }
-
- if(statusByte == IDE_STATUS_IDLE) {
- return TRUE;
- }
-
- return FALSE;
-
-} // end SetDriveParameters()
-
-VOID
-NTAPI
-UniataForgetDevice(
- 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 Value:
- Nothing.
-
-
---*/
-BOOLEAN
-NTAPI
-AtapiResetController(
- IN PVOID HwDeviceExtension,
- IN ULONG PathId
- )
-{
- KdPrint2((PRINT_PREFIX "AtapiResetController(%x)\n", PathId));
- return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
-} // end AtapiResetController()
-
-BOOLEAN
-NTAPI
-AtapiResetController__(
- IN PVOID HwDeviceExtension,
- IN ULONG PathId,
- IN BOOLEAN CompleteType
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- ULONG numberChannels = deviceExtension->NumberChannels;
- PHW_CHANNEL chan = NULL;
- ULONG i,j;
- ULONG MaxLuns;
- UCHAR statusByte;
- PSCSI_REQUEST_BLOCK CurSrb;
- ULONG ChannelCtrlFlags;
- UCHAR dma_status = 0;
-
- ULONG slotNumber = deviceExtension->slotNumber;
- ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
- ULONG VendorID = deviceExtension->DevID & 0xffff;
-#ifdef _DEBUG
- ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
-#endif
- //ULONG RevID = deviceExtension->RevID;
- ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
- //UCHAR tmp8;
- USHORT tmp16;
-
- KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber));
- KdPrint2((PRINT_PREFIX "simplexOnly %d, VM %x\n", deviceExtension->simplexOnly, g_opt_VirtualMachine));
-
- if(!deviceExtension->simplexOnly && (PathId != CHAN_NOT_SPECIFIED)) {
- // we shall reset both channels on SimplexOnly devices,
- // It's not worth doing so on normal controllers
- j = PathId;
- numberChannels = min(j+1, deviceExtension->NumberChannels);
- } else {
- j=0;
- numberChannels = deviceExtension->NumberChannels;
- }
-
- for (; j < numberChannels; j++) {
-
- KdPrint2((PRINT_PREFIX "AtapiResetController: Reset lchannel %d[%d]\n", j, deviceExtension->Channel));
- chan = &(deviceExtension->chan[j]);
- MaxLuns = chan->NumberLuns;
- // Save control flags
- ChannelCtrlFlags = chan->ChannelCtrlFlags;
- KdPrint2((PRINT_PREFIX " CompleteType %#x, Luns %d, chan %#x, sptr %#x, flags %#x\n", CompleteType, MaxLuns, chan, &chan, ChannelCtrlFlags));
- //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
- if(CompleteType != RESET_COMPLETE_NONE) {
-#ifndef UNIATA_CORE
- while((CurSrb = UniataGetCurRequest(chan))) {
-
- PHW_LU_EXTENSION LunExt;
- PATA_REQ AtaReq = (PATA_REQ)(CurSrb->SrbExtension);
-
- i = GET_CDEV(CurSrb);
- KdPrint2((PRINT_PREFIX " Lun %x\n", i));
- LunExt = chan->lun[i];
-
- KdPrint2((PRINT_PREFIX "AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb, chan));
- if(CurSrb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
- KdPrint2((PRINT_PREFIX " was MechStatus\n"));
-
- if(!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)) {
- LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
- KdPrint2((PRINT_PREFIX " set DFLAGS_CHANGER_INITED\n"));
- }
- }
- // Check and see if we are processing an internal srb
- if (AtaReq->OriginalSrb) {
- KdPrint2((PRINT_PREFIX " restore original SRB %#x\n", AtaReq->OriginalSrb));
- AtaReq->Srb = AtaReq->OriginalSrb;
- CurSrb->SrbExtension = NULL;
- AtaReq->OriginalSrb = NULL;
- // NOTE: internal SRB doesn't get to SRB queue !!!
- CurSrb = AtaReq->Srb;
- }
-
- // Remove current request from queue
- UniataRemoveRequest(chan, CurSrb);
-
- // Check if request is in progress.
- ASSERT(AtaReq->Srb == CurSrb);
- if (CurSrb) {
- // Complete outstanding request with SRB_STATUS_BUS_RESET.
- UCHAR CurPathId = CurSrb->PathId;
- UCHAR TargetId = CurSrb->TargetId;
- UCHAR Lun = CurSrb->Lun;
-
- CurSrb->SrbStatus = ((CompleteType == RESET_COMPLETE_ALL) ? SRB_STATUS_BUS_RESET : SRB_STATUS_ABORTED) | SRB_STATUS_AUTOSENSE_VALID;
- CurSrb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
-
- if (CurSrb->SenseInfoBuffer) {
-
- PSENSE_DATA senseBuffer = (PSENSE_DATA)CurSrb->SenseInfoBuffer;
- KdPrint2((PRINT_PREFIX " senseBuffer %#x, chan %#x, ReqFlags %#x\n", senseBuffer, chan, AtaReq->Flags));
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- if(CompleteType == RESET_COMPLETE_ALL) {
- KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
- senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
- senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_BUS_RESET;
- senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_SCSI_BUS;
- } else {
- KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
- senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
- senseBuffer->AdditionalSenseCode = 0;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
- }
- }
-
- if(!ATAPI_DEVICE(chan, i) && AtaReq->bcount && AtaReq->retry < MAX_RETRIES) {
- KdPrint2((PRINT_PREFIX "Save IDE retry status %d\n", AtaReq->retry));
- LunExt->errLastLba = AtaReq->lba;
- LunExt->errBCount = AtaReq->bcount;
- LunExt->errRetry = AtaReq->retry+1;
- //KdPrint2((PRINT_PREFIX "AtaReq->Flags & REQ_FLAG_RW_MASK = %x (%x)\n", (AtaReq->Flags & REQ_FLAG_RW_MASK), REQ_FLAG_READ));
- //KdPrint2((PRINT_PREFIX "ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION = %x (%x)\n", ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE, CTRFLAGS_DMA_OPERATION));
- //KdPrint2((PRINT_PREFIX "g_opt_VirtualMachine = %x (%x)\n", g_opt_VirtualMachine, VM_BOCHS));
- if(((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_READ) &&
- (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) &&
- (g_opt_VirtualMachine == VM_BOCHS)) {
- KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
- g_opt_BochsDmaReadWorkaround = TRUE;
- g_opt_AtapiNoDma = TRUE;
- } else {
- KdPrint2((PRINT_PREFIX "do nothing\n"));
- }
- } else
- if(ATAPI_DEVICE(chan, i) && AtaReq->bcount && !AtaReq->retry) {
- KdPrint2((PRINT_PREFIX "Save ATAPI retry status %d\n", AtaReq->retry));
- LunExt->errLastLba = AtaReq->lba;
- LunExt->errBCount = AtaReq->bcount;
- LunExt->errRetry = AtaReq->retry+1;
- if(((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_READ) &&
- (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) &&
- (g_opt_VirtualMachine == VM_BOCHS)) {
- KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS ATAPI\n"));
- //g_opt_BochsDmaReadWorkaround = TRUE;
- g_opt_AtapiNoDma = TRUE;
- } else {
- KdPrint2((PRINT_PREFIX "do nothing\n"));
- }
- } else {
- LunExt->errRetry = 0;
- }
-
- // Clear request tracking fields.
- AtaReq->WordsLeft = 0;
- AtaReq->DataBuffer = NULL;
- AtaReq->TransferLength = 0;
- KdPrint2((PRINT_PREFIX "chan %#x\n", chan));
-
- ScsiPortNotification(RequestComplete,
- deviceExtension,
- CurSrb);
-
- // Indicate ready for next request.
- ScsiPortNotification(NextLuRequest,
- deviceExtension,
- CurPathId,
- TargetId,
- Lun);
- }
- if(CompleteType != RESET_COMPLETE_ALL)
- break;
- } // end while()
-#endif //UNIATA_CORE
- } // end if (!CompleteType != RESET_COMPLETE_NONE)
-
- // Clear expecting interrupt flag.
- UniataExpectChannelInterrupt(chan, FALSE);
- chan->RDP = FALSE;
- chan->ChannelCtrlFlags = ChannelCtrlFlags & CTRFLAGS_PERMANENT;
- 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(UniataAhciChanImplemented(deviceExtension, j)) {
-#ifdef _DEBUG
- UniataDumpAhciPortRegs(chan);
-#endif
- AtapiDisableInterrupts(deviceExtension, j);
- UniataAhciReset(HwDeviceExtension, j);
- } else {
- KdPrint2((PRINT_PREFIX " skip not implemented\n"));
- continue;
- }
- } else {
- KdPrint2((PRINT_PREFIX " ATA path, chan %#x\n", chan));
- KdPrint2((PRINT_PREFIX " disable intr (0)\n"));
- AtapiDisableInterrupts(deviceExtension, j);
- KdPrint2((PRINT_PREFIX " done\n"));
- switch(VendorID) {
- case ATA_INTEL_ID: {
- ULONG mask;
- ULONG pshift;
- ULONG timeout;
- if(!(ChipFlags & UNIATA_SATA)) {
- goto default_reset;
- }
- if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
- goto default_reset;
- }
-
-#if 0
- /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
- if(ChipFlags & UNIATA_AHCI) {
- mask = 0x0005 << j;
- } else {
- /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
- GetPciConfig1(0x90, tmp8);
- if(tmp8 & 0x04) {
- mask = 0x0003;
- } else {
- mask = 0x0001 << j;
- }
- }
-#else
- mask = 1 << chan->lun[0]->SATA_lun_map;
- if (MaxLuns > 1) {
- mask |= (1 << chan->lun[1]->SATA_lun_map);
- }
-#endif
- ChangePciConfig2(0x92, a & ~mask);
- AtapiStallExecution(10);
- ChangePciConfig2(0x92, a | mask);
- timeout = 100;
-
- /* Wait up to 1 sec for "connect well". */
- if (ChipFlags & (I6CH | I6CH2)) {
- pshift = 8;
- } else {
- pshift = 4;
- }
- while (timeout--) {
- GetPciConfig2(0x92, tmp16);
- if (((tmp16 >> pshift) & mask) == mask) {
- GetBaseStatus(chan, statusByte);
- if(statusByte != IDE_STATUS_WRONG) {
- break;
- }
- }
- AtapiStallExecution(10000);
- }
- break; }
- case ATA_SIS_ID: {
- KdPrint2((PRINT_PREFIX " SIS\n"));
- if(!(ChipFlags & UNIATA_SATA))
- goto default_reset;
- break; }
-#if 0
- case ATA_NVIDIA_ID: {
- KdPrint2((PRINT_PREFIX " nVidia\n"));
- if(!(ChipFlags & UNIATA_SATA))
- goto default_reset;
- break; }
-#else
- case ATA_NVIDIA_ID: {
- ULONG offs;
- ULONG Channel = deviceExtension->Channel + j;
- KdPrint2((PRINT_PREFIX " nVidia\n"));
- if(!(ChipFlags & UNIATA_SATA)) {
- goto default_reset;
- }
- offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
-
- KdPrint2((PRINT_PREFIX " disable Phy intr, offs %#x, c %u\n", offs, Channel));
- /* disable device and PHY state change interrupts */
- if(ChipFlags & NVQ) {
- KdPrint2((PRINT_PREFIX " NVQ, 32bits reg\n"));
- AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4,
- AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) & ((~(ULONG)0x0000000d) << (!Channel*16)) );
- } else {
- AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1,
- AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) & ((~(UCHAR)0x0d) << (!Channel*4)) );
- }
- tmp16 = UniataSataPhyEnable(HwDeviceExtension, j, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE);
-
- KdPrint2((PRINT_PREFIX " enable Phy intr, offs %#x\n", offs));
- /* enable device and PHY state change interrupts */
- if(ChipFlags & NVQ) {
- AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4,
- AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) | (((ULONG)0x0000000d) << (!Channel*16)) );
- } else {
- AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1,
- AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) | (((UCHAR)0x0d) << (!Channel*4)) );
- }
-
- KdPrint2((PRINT_PREFIX " dev status %#x\n", tmp16));
- if(tmp16 != IDE_STATUS_WRONG) {
- goto default_reset;
- }
- break; }
-#endif //0
- case ATA_SILICON_IMAGE_ID: {
- ULONG offset;
- ULONG Channel = deviceExtension->Channel + j;
- if(!(ChipFlags & UNIATA_SATA))
- goto default_reset;
- offset = ((Channel & 1) << 7) + ((Channel & 2) << 8);
- /* disable PHY state change interrupt */
- AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + offset, 0);
-
- UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
-
- /* reset controller part for this channel */
- AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
- AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) | (0xc0 >> Channel));
- AtapiStallExecution(1000);
- AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
- AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) & ~(0xc0 >> Channel));
-
-
- break; }
- case ATA_PROMISE_ID: {
- break; }
- default:
- if(ChipFlags & UNIATA_SATA) {
- KdPrint2((PRINT_PREFIX " SATA generic reset\n"));
- UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
- }
-default_reset:
-/*
- AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
- IDE_DC_RESET_CONTROLLER );
- chan->last_devsel = -1;
- KdPrint2((PRINT_PREFIX " wait a little\n"));
- AtapiStallExecution(10000);
- // Disable interrupts
- KdPrint2((PRINT_PREFIX " disable intr\n"));
- AtapiDisableInterrupts(deviceExtension, j);
- AtapiStallExecution(100);
- KdPrint2((PRINT_PREFIX " re-enable intr\n"));
- AtapiEnableInterrupts(deviceExtension, j);
- KdPrint2((PRINT_PREFIX " wait a little (2)\n"));
- AtapiStallExecution(100000);
-*/
- AtapiHardReset(chan, TRUE, 100000);
- KdPrint2((PRINT_PREFIX " disable intr\n"));
- AtapiDisableInterrupts(deviceExtension, j);
- AtapiStallExecution(100);
- KdPrint2((PRINT_PREFIX " re-enable intr\n"));
- AtapiEnableInterrupts(deviceExtension, j);
- KdPrint2((PRINT_PREFIX " done\n"));
-
- break;
- } // end switch()
-
- //if(!(ChipFlags & UNIATA_SATA)) {}
- if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
- // Reset DMA engine if active
- KdPrint2((PRINT_PREFIX " check DMA engine\n"));
- dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
- KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
- if((ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
- (dma_status & BM_STATUS_INTR)) {
- AtapiDmaDone(HwDeviceExtension, 0, j, NULL);
- }
- }
- } // ATA vs AHCI
-
- // all these shall be performed inside AtapiHwInitialize__() ?
-#if 1
- 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()
- KdPrint2((PRINT_PREFIX " device have gone\n"));
- continue;
- }
-#ifdef NAVO_TEST
- continue;
-#else //NAVO_TEST
- //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
- if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
- continue;
- }
- if(!CheckDevice(HwDeviceExtension, j, i, TRUE)) {
- continue;
- }
- } else {
- if(ChipFlags & UNIATA_AHCI) {
- // everything is done in UniataAhciReset()
- KdPrint2((PRINT_PREFIX " found some device\n"));
-
- if(!IssueIdentify(HwDeviceExtension,
- i, j,
- ATAPI_DEVICE(chan, i) ?
- IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY,
- FALSE)) {
- KdPrint2((PRINT_PREFIX " identify failed !\n"));
- UniataForgetDevice(chan->lun[i]);
- }
- continue;
- }
- if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
- KdPrint2((PRINT_PREFIX " device have gone\n"));
- UniataForgetDevice(chan->lun[i]);
- }
-#endif //NAVO_TEST
- }
-
- SelectDrive(chan, i);
- AtapiStallExecution(10);
- statusByte = WaitOnBusyLong(chan);
- statusByte = UniataIsIdle(deviceExtension, statusByte);
- if(statusByte == IDE_STATUS_WRONG) {
- KdPrint2((PRINT_PREFIX
- "no drive, status %#x\n",
- statusByte));
- UniataForgetDevice(chan->lun[i]);
- } else
- // Check for ATAPI disk.
- if (ATAPI_DEVICE(chan, i)) {
- // Issue soft reset and issue identify.
- GetStatus(chan, statusByte);
- KdPrint2((PRINT_PREFIX "AtapiResetController: Status before Atapi reset (%#x).\n",
- statusByte));
-
- AtapiDisableInterrupts(deviceExtension, j);
- AtapiSoftReset(chan, i);
- AtapiEnableInterrupts(deviceExtension, j);
-
- GetStatus(chan, statusByte);
-
- if(statusByte != IDE_STATUS_SUCCESS) {
- ULONG k;
- k = UniataAnybodyHome(deviceExtension, j, i);
- if(k == ATA_AT_HOME_HDD) {
- // device reset in progress, perform additional wait
- KdPrint2((PRINT_PREFIX " long reset, wait up to 4.5 s\n"));
- k = 30 * 1000;
- while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
- k--)
- {
- AtapiStallExecution(150);
- }
- KdPrint2((PRINT_PREFIX " exit after %u loops\n", k));
- GetStatus(chan, statusByte);
- }
- }
- if(statusByte == IDE_STATUS_SUCCESS) {
-
- IssueIdentify(HwDeviceExtension,
- i, j,
- IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
- } else {
-
- KdPrint2((PRINT_PREFIX
- "AtapiResetController: Status after soft reset %#x\n",
- statusByte));
- }
- GetBaseStatus(chan, statusByte);
-
- } else {
- // Issue identify and reinit after channel reset.
-
- if (statusByte != IDE_STATUS_IDLE &&
- statusByte != IDE_STATUS_SUCCESS &&
- statusByte != IDE_STATUS_DRDY) {
-// result2 = FALSE;
- KdPrint2((PRINT_PREFIX "AtapiResetController: IdeHardReset failed\n"));
- } else
- if(!IssueIdentify(HwDeviceExtension,
- i, j,
- IDE_COMMAND_IDENTIFY, FALSE)) {
-// result2 = FALSE;
- KdPrint2((PRINT_PREFIX "AtapiResetController: IDE IssueIdentify failed\n"));
- } else
- // Set disk geometry parameters.
- if (!SetDriveParameters(HwDeviceExtension, i, j)) {
- KdPrint2((PRINT_PREFIX "AtapiResetController: SetDriveParameters failed\n"));
- }
- GetBaseStatus(chan, statusByte);
- }
- // force DMA mode reinit
- KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n"));
- chan->lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
- }
-#endif //0
-
- // Enable interrupts, note, we can have here recursive disable
- AtapiStallExecution(10);
- KdPrint2((PRINT_PREFIX "AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
- j,
- chan->DisableIntr));
- AtapiEnableInterrupts(deviceExtension, j);
-
- // Call the HwInitialize routine to setup multi-block.
- AtapiHwInitialize__(deviceExtension, j);
- } // for(channel)
- ScsiPortNotification(NextRequest, deviceExtension, NULL);
-
- return TRUE;
-
-} // end AtapiResetController__()
-
-
-/*++
-
-Routine Description:
- This routine maps ATAPI and IDE errors to specific SRB statuses.
-
-Arguments:
- HwDeviceExtension - HBA miniport driver's adapter data storage
- Srb - IO request packet
-
-Return Value:
- SRB status
-
---*/
-ULONG
-NTAPI
-MapError(
- IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- ULONG lChannel = GET_CHANNEL(Srb);
- PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
-// ULONG i;
- UCHAR errorByte = 0;
- UCHAR srbStatus = SRB_STATUS_SUCCESS;
- UCHAR scsiStatus;
- ULONG DeviceNumber = GET_CDEV(Srb);
- PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
-
- // Read the error register.
-
- 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));
-
- if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
-
- switch (errorByte >> 4) {
- case SCSI_SENSE_NO_SENSE:
-
- KdPrint2((PRINT_PREFIX
- "ATAPI: No sense information\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
- break;
-
- case SCSI_SENSE_RECOVERED_ERROR:
-
- KdPrint2((PRINT_PREFIX
- "ATAPI: Recovered error\n"));
- scsiStatus = 0;
- srbStatus = SRB_STATUS_SUCCESS;
- break;
-
- case SCSI_SENSE_NOT_READY:
-
- KdPrint2((PRINT_PREFIX
- "ATAPI: Device not ready\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
- break;
-
- case SCSI_SENSE_MEDIUM_ERROR:
-
- KdPrint2((PRINT_PREFIX
- "ATAPI: Media error\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
- break;
-
- case SCSI_SENSE_HARDWARE_ERROR:
-
- KdPrint2((PRINT_PREFIX
- "ATAPI: Hardware error\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
- break;
-
- case SCSI_SENSE_ILLEGAL_REQUEST:
-
- KdPrint2((PRINT_PREFIX
- "ATAPI: Illegal request\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
- break;
-
- case SCSI_SENSE_UNIT_ATTENTION:
-
- KdPrint2((PRINT_PREFIX
- "ATAPI: Unit attention\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
- break;
-
- case SCSI_SENSE_DATA_PROTECT:
-
- KdPrint2((PRINT_PREFIX
- "ATAPI: Data protect\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
- break;
-
- case SCSI_SENSE_BLANK_CHECK:
-
- KdPrint2((PRINT_PREFIX
- "ATAPI: Blank check\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
- break;
-
- case SCSI_SENSE_ABORTED_COMMAND:
- KdPrint2((PRINT_PREFIX
- "Atapi: Command Aborted\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
- break;
-
- default:
-
- KdPrint2((PRINT_PREFIX
- "ATAPI: Invalid sense information\n"));
- scsiStatus = 0;
- srbStatus = SRB_STATUS_ERROR;
- break;
- }
-
- } else {
-
- scsiStatus = 0;
-
- // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
- chan->ReturningMediaStatus = errorByte;
-
- if (errorByte & IDE_ERROR_MEDIA_CHANGE_REQ) {
- KdPrint2((PRINT_PREFIX
- "IDE: Media change\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
-
- if (Srb->SenseInfoBuffer) {
-
- PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
- senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
-
- srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- }
-
- } else if (errorByte & IDE_ERROR_COMMAND_ABORTED) {
- KdPrint2((PRINT_PREFIX
- "IDE: Command abort\n"));
- srbStatus = SRB_STATUS_ABORTED;
- scsiStatus = SCSISTAT_CHECK_CONDITION;
-
- if (Srb->SenseInfoBuffer) {
-
- PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
- senseBuffer->AdditionalSenseCode = 0;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
-
- srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- }
-
- LunExt->ErrorCount++;
-
- } else if (errorByte & IDE_ERROR_END_OF_MEDIA) {
-
- KdPrint2((PRINT_PREFIX
- "IDE: End of media\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
-
- if (Srb->SenseInfoBuffer) {
-
- PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
- senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIA_STATE;
- senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_END_OF_MEDIUM;
- senseBuffer->EndOfMedia = 1;
-
- srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- }
-
- if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
- LunExt->ErrorCount++;
- }
-
- } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) {
-
- KdPrint2((PRINT_PREFIX
- "IDE: Illegal length\n"));
- srbStatus = SRB_STATUS_INVALID_REQUEST;
-
- 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_VALUE;
- senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_PARAM_INVALID_VALUE;
- senseBuffer->IncorrectLength = 1;
-
- srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- }
-
- } else if (errorByte & IDE_ERROR_BAD_BLOCK) {
-
- KdPrint2((PRINT_PREFIX
- "IDE: Bad block\n"));
- srbStatus = SRB_STATUS_ERROR;
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- if (Srb->SenseInfoBuffer) {
-
- PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
- senseBuffer->AdditionalSenseCode = 0;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
-
- srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- }
-
- } else if (errorByte & IDE_ERROR_ID_NOT_FOUND) {
-
- KdPrint2((PRINT_PREFIX
- "IDE: Id not found\n"));
- srbStatus = SRB_STATUS_ERROR;
- scsiStatus = SCSISTAT_CHECK_CONDITION;
-
- if (Srb->SenseInfoBuffer) {
-
- PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
- senseBuffer->AdditionalSenseCode = 0;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
-
- srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- }
-
- LunExt->ErrorCount++;
-
- } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) {
-
- KdPrint2((PRINT_PREFIX
- "IDE: Media change\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
-
- if (Srb->SenseInfoBuffer) {
-
- PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
- senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
-
- srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- }
-
- } else if (errorByte & IDE_ERROR_DATA_ERROR) {
-
- KdPrint2((PRINT_PREFIX
- "IDE: Data error\n"));
- scsiStatus = SCSISTAT_CHECK_CONDITION;
- srbStatus = SRB_STATUS_ERROR;
-
- if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
- LunExt->ErrorCount++;
- }
-
- // Build sense buffer
- if (Srb->SenseInfoBuffer) {
-
- PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
- senseBuffer->AdditionalSenseCode = 0;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
-
- srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- }
- }
-
- if (LunExt->ErrorCount >= MAX_ERRORS) {
-// deviceExtension->DWordIO = FALSE;
-
- KdPrint2((PRINT_PREFIX
- "MapError: ErrorCount >= MAX_ERRORS\n"));
-
- LunExt->DeviceFlags &= ~DFLAGS_DWORDIO_ENABLED;
- LunExt->MaximumBlockXfer = 0;
- BrutePoint();
-
- KdPrint2((PRINT_PREFIX
- "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
-
- // Log the error.
- KdPrint2((PRINT_PREFIX
- "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
- HwDeviceExtension,
- Srb,
- Srb->PathId,
- Srb->TargetId,
- Srb->Lun,
- SP_BAD_FW_WARNING,
- 4
- ));
- ScsiPortLogError( HwDeviceExtension,
- Srb,
- Srb->PathId,
- Srb->TargetId,
- Srb->Lun,
- SP_BAD_FW_WARNING,
- 4);
-
- // Reprogram to not use Multi-sector.
- UCHAR statusByte;
-
- if (LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT &&
- !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) {
-
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY);
-
- // Check for errors. Reset the value to 0 (disable MultiBlock) if the
- // command was aborted.
- if (statusByte & IDE_STATUS_ERROR) {
-
- // Read the error register.
- errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
-
- KdPrint2((PRINT_PREFIX "MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
- statusByte,
- errorByte));
-
- // Adjust the devExt. value, if necessary.
- LunExt->MaximumBlockXfer = 0;
- BrutePoint();
-
- }
- }
- }
- }
-
- // Set SCSI status to indicate a check condition.
- Srb->ScsiStatus = scsiStatus;
-
- return srbStatus;
-
-} // end MapError()
-
-
-/*++
-
-Routine Description:
-
-Arguments:
- HwDeviceExtension - HBA miniport driver's adapter data storage
- ->HwInitialize
-
-Return Value:
- TRUE - if initialization successful.
- FALSE - if initialization unsuccessful.
-
---*/
-BOOLEAN
-NTAPI
-AtapiHwInitialize(
- IN PVOID HwDeviceExtension
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- ULONG numberChannels = deviceExtension->NumberChannels;
- ULONG c;
-
- KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base)\n"));
-
- 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);
-/*
- if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
- KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
- BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
- }
-*/
- for (c = 0; c < numberChannels; c++) {
- AtapiHwInitialize__(deviceExtension, c);
- }
- KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base) done\n"));
- return TRUE;
-} // end AtapiHwInitialize()
-
-VOID
-NTAPI
-AtapiHwInitialize__(
- IN PHW_DEVICE_EXTENSION deviceExtension,
- IN ULONG lChannel
- )
-{
- ULONG i;
- UCHAR statusByte, errorByte;
- PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
- PHW_LU_EXTENSION LunExt;
-// ULONG tmp32;
- ULONG PreferedMode = 0xffffffff;
-
- if((deviceExtension->HwFlags & UNIATA_AHCI) &&
- !UniataAhciChanImplemented(deviceExtension, lChannel)) {
- return;
- }
-
- AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
- FindDevices(deviceExtension, 0, lChannel);
-
- for (i = 0; i < chan->NumberLuns; i++) {
-
- KdPrint3((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel, i));
-
- LunExt = chan->lun[i];
- // skip empty slots
- if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
- continue;
- }
-
- AtapiDisableInterrupts(deviceExtension, lChannel);
- AtapiStallExecution(1);
-
- if (!(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) {
-
- KdPrint2((PRINT_PREFIX "AtapiHwInitialize: IDE branch\n"));
- // Enable media status notification
- IdeMediaStatus(TRUE,deviceExtension,lChannel,(UCHAR)i);
-
- // If supported, setup Multi-block transfers.
- statusByte = AtaCommand(deviceExtension, i, lChannel,
- IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
- LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
-
- // Check for errors. Reset the value to 0 (disable MultiBlock) if the
- // command was aborted.
- if (statusByte & IDE_STATUS_ERROR) {
-
- // Read the error register.
- errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
-
- KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
- statusByte,
- errorByte));
-
- statusByte = AtaCommand(deviceExtension, i, lChannel,
- IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
- 0, 0, ATA_WAIT_BASE_READY);
-
- if (statusByte & IDE_STATUS_ERROR) {
- // Read the error register.
- errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
-
- KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
- statusByte,
- errorByte));
- }
- // Adjust the devExt. value, if necessary.
- LunExt->MaximumBlockXfer = 0;
-
- } else {
- KdPrint2((PRINT_PREFIX
- "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
- i,
- LunExt->MaximumBlockXfer));
- }
-
- if(LunExt->IdentifyData.MajorRevision) {
-
- if(LunExt->opt_ReadCacheEnable) {
- KdPrint2((PRINT_PREFIX " Try Enable Read Cache\n"));
- // If supported, setup read/write cacheing
- statusByte = AtaCommand(deviceExtension, i, lChannel,
- IDE_COMMAND_SET_FEATURES, 0, 0, 0,
- 0, ATA_C_F_ENAB_RCACHE, ATA_WAIT_BASE_READY);
-
- // Check for errors.
- if (statusByte & IDE_STATUS_ERROR) {
- KdPrint2((PRINT_PREFIX
- "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
- i));
- LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
- } else {
- LunExt->DeviceFlags |= DFLAGS_RCACHE_ENABLED;
- }
- } else {
- KdPrint2((PRINT_PREFIX " Disable Read Cache\n"));
- statusByte = AtaCommand(deviceExtension, i, lChannel,
- IDE_COMMAND_SET_FEATURES, 0, 0, 0,
- 0, ATA_C_F_DIS_RCACHE, ATA_WAIT_BASE_READY);
- LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
- }
- if(LunExt->IdentifyData.FeaturesSupport.WriteCache) {
- if(LunExt->opt_WriteCacheEnable) {
- KdPrint2((PRINT_PREFIX " Try Enable Write Cache\n"));
- // If supported & allowed, setup write cacheing
- statusByte = AtaCommand(deviceExtension, i, lChannel,
- IDE_COMMAND_SET_FEATURES, 0, 0, 0,
- 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
- // Check for errors.
- if (statusByte & IDE_STATUS_ERROR) {
- KdPrint2((PRINT_PREFIX
- "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
- i));
- LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
- } else {
- LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
- }
- } else {
- KdPrint2((PRINT_PREFIX " Disable Write Cache\n"));
- statusByte = AtaCommand(deviceExtension, i, lChannel,
- IDE_COMMAND_SET_FEATURES, 0, 0, 0,
- 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;
- CCHAR vendorId[26];
-
- KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n"));
-
- // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
- for (j = 0; j < 26; j += 2) {
-
- // Build a buffer based on the identify data.
- MOV_DW_SWP(vendorId[j], ((PUCHAR)LunExt->IdentifyData.ModelNumber)[j]);
- }
-
- if (!AtapiStringCmp (vendorId, "CD-ROM CDR", 11)) {
-
- // Inquiry string for older model had a '-', newer is '_'
- if (vendorId[12] == 'C') {
-
- // Torisan changer. Set the bit. This will be used in several places
- // 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;
- }
- }
- }
-
- PreferedMode = LunExt->opt_MaxTransferMode;
- if((PreferedMode == 0xffffffff) || (PreferedMode > chan->MaxTransferMode)) {
- KdPrint2((PRINT_PREFIX "MaxTransferMode (overriden): %#x\n", chan->MaxTransferMode));
- PreferedMode = chan->MaxTransferMode;
- }
-
- if(LunExt->opt_PreferedTransferMode != 0xffffffff) {
- KdPrint2((PRINT_PREFIX "PreferedTransferMode: %#x\n", PreferedMode));
- PreferedMode = min(LunExt->opt_PreferedTransferMode, PreferedMode);
- }
-
- KdPrint2((PRINT_PREFIX " try mode %#x\n", PreferedMode));
- LunExt->LimitedTransferMode =
- LunExt->TransferMode =
- (CHAR)PreferedMode;
-
- AtapiDmaInit__(deviceExtension, LunExt);
-
- LunExt->LimitedTransferMode =
- LunExt->TransferMode;
- KdPrint2((PRINT_PREFIX "Using %#x mode\n", LunExt->TransferMode));
-
- // We need to get our device ready for action before
- // returning from this function
-
- // According to the atapi spec 2.5 or 2.6, an atapi device
- // clears its status BSY bit when it is ready for atapi commands.
- // However, some devices (Panasonic SQ-TC500N) are still
- // not ready even when the status BSY is clear. They don't react
- // to atapi commands.
- //
- // Since there is really no other indication that tells us
- // the drive is really ready for action. We are going to check BSY
- // is clear and then just wait for an arbitrary amount of time!
- //
- if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
- ULONG waitCount;
-
- // have to get out of the loop sometime!
- // 10000 * 100us = 1000,000us = 1000ms = 1s
- waitCount = 10000;
- GetStatus(chan, statusByte);
- if(statusByte == IDE_STATUS_WRONG) {
- waitCount = 0;
- }
- while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
-
- KdPrint2((PRINT_PREFIX "Wait for ATAPI (status %x)\n", statusByte));
- // Wait for Busy to drop.
- AtapiStallExecution(100);
- GetStatus(chan, statusByte);
- waitCount--;
- }
-
- // 5000 * 100us = 500,000us = 500ms = 0.5s
- if(statusByte != IDE_STATUS_WRONG) {
- waitCount = 5000;
- do {
- AtapiStallExecution(100);
- } while (waitCount--);
- }
- }
- GetBaseStatus(chan, statusByte);
- AtapiEnableInterrupts(deviceExtension, lChannel);
- AtapiStallExecution(10);
- }
-
- return;
-
-} // end AtapiHwInitialize__()
-
-
-#ifndef UNIATA_CORE
-
-VOID
-NTAPI
-AtapiHwInitializeChanger(
- IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb,
- IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus)
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- ULONG lChannel = GET_CHANNEL(Srb);
- PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
- ULONG DeviceNumber = GET_CDEV(Srb);
- PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
-
- if (MechanismStatus) {
- LunExt->DiscsPresent = MechanismStatus->NumberAvailableSlots;
- if (LunExt->DiscsPresent > 1) {
- LunExt->DeviceFlags |= DFLAGS_ATAPI_CHANGER;
- }
- }
- return;
-} // end AtapiHwInitializeChanger()
-
-
-/*++
-
-Routine Description:
- This routine will parse the string for a match on the keyword, then
- calculate the value for the keyword and return it to the caller.
-
-Arguments:
- String - The ASCII string to parse.
- KeyWord - The keyword for the value desired.
-
-Return Values:
- Zero if value not found
- Value converted from ASCII to binary.
-
---*/
-ULONG
-NTAPI
-AtapiParseArgumentString(
- IN PCCH String,
- IN PCCH KeyWord
- )
-{
- PCCH cptr;
- PCCH kptr;
- ULONG value;
- ULONG stringLength = 0;
- ULONG keyWordLength = 0;
- ULONG index;
-
- if (!String) {
- return 0;
- }
- if (!KeyWord) {
- return 0;
- }
-
- // Calculate the string length and lower case all characters.
- cptr = String;
- while (*cptr++) {
- stringLength++;
- }
-
- // Calculate the keyword length.
- kptr = KeyWord;
- while (*kptr++) {
- keyWordLength++;
- }
-
- if (keyWordLength > stringLength) {
-
- // Can't possibly have a match.
- return 0;
- }
-
- // Now setup and start the compare.
- cptr = String;
-
-ContinueSearch:
-
- // The input string may start with white space. Skip it.
- while (*cptr == ' ' || *cptr == '\t') {
- cptr++;
- }
-
- if (*cptr == '\0') {
- // end of string.
- return 0;
- }
-
- kptr = KeyWord;
- while ((*cptr == *kptr) ||
- (*cptr >= 'A' && *cptr <= 'Z' && *cptr + ('a' - 'A') == *kptr) ||
- (*cptr >= 'a' && *cptr <= 'z' && *cptr - ('a' - 'A') == *kptr)) {
- cptr++;
- kptr++;
-
- if (*cptr == '\0') {
- // end of string
- return 0;
- }
- }
-
- if (*kptr == '\0') {
-
- // May have a match backup and check for blank or equals.
- while (*cptr == ' ' || *cptr == '\t') {
- cptr++;
- }
-
- // Found a match. Make sure there is an equals.
- if (*cptr != '=') {
-
- // Not a match so move to the next semicolon.
- while (*cptr) {
- if (*cptr++ == ';') {
- goto ContinueSearch;
- }
- }
- return 0;
- }
- // Skip the equals sign.
- cptr++;
-
- // Skip white space.
- while ((*cptr == ' ') || (*cptr == '\t')) {
- cptr++;
- }
-
- if (*cptr == '\0') {
- // Early end of string, return not found
- return 0;
- }
-
- if (*cptr == ';') {
- // This isn't it either.
- cptr++;
- goto ContinueSearch;
- }
-
- value = 0;
- if ((*cptr == '0') && ((*(cptr + 1) == 'x') || (*(cptr + 1) == 'X'))) {
- // Value is in Hex. Skip the "0x"
- cptr += 2;
- for (index = 0; *(cptr + index); index++) {
-
- if (*(cptr + index) == ' ' ||
- *(cptr + index) == '\t' ||
- *(cptr + index) == ';') {
- break;
- }
-
- if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
- value = (16 * value) + (*(cptr + index) - '0');
- } else {
- if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
- value = (16 * value) + (*(cptr + index) - 'a' + 10);
- } else if ((*(cptr + index) >= 'A') && (*(cptr + index) <= 'F')) {
- value = (16 * value) + (*(cptr + index) - 'A' + 10);
- } else {
- // Syntax error, return not found.
- return 0;
- }
- }
- }
- } else {
-
- // Value is in Decimal.
- for (index = 0; *(cptr + index); index++) {
-
- if (*(cptr + index) == ' ' ||
- *(cptr + index) == '\t' ||
- *(cptr + index) == ';') {
- break;
- }
-
- if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
- value = (10 * value) + (*(cptr + index) - '0');
- } else {
-
- // Syntax error return not found.
- return 0;
- }
- }
- }
-
- return value;
- } else {
-
- // Not a match check for ';' to continue search.
- while (*cptr) {
- if (*cptr++ == ';') {
- goto ContinueSearch;
- }
- }
-
- return 0;
- }
-} // end AtapiParseArgumentString()_
-
-/*
- Timer callback
-*/
-VOID
-NTAPI
-AtapiCallBack__(
- IN PVOID HwDeviceExtension,
- IN UCHAR lChannel
- )
-{
-
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
- ULONG c, _c;
-
- PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
- UCHAR statusByte;
-
- KdPrint2((PRINT_PREFIX "AtapiCallBack:\n"));
- // If the last command was DSC restrictive, see if it's set. If so, the device is
- // ready for a new request. Otherwise, reset the timer and come back to here later.
-
- // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
- // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
- // we shall have no problem with interrupt handler.
- if (!srb || chan->ExpectingInterrupt) {
- KdPrint2((PRINT_PREFIX "AtapiCallBack: Calling ISR directly due to BUSY\n"));
- chan->DpcState = DPC_STATE_TIMER;
- if(!AtapiInterrupt__(HwDeviceExtension, lChannel)) {
- InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
- KdPrint2((PRINT_PREFIX "AtapiCallBack: What's fucking this ???\n"));
- }
- goto ReturnCallback;
- }
-
-#ifdef _DEBUG
- if (!IS_RDP((srb->Cdb[0]))) {
- KdPrint2((PRINT_PREFIX "AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb->Cdb[0]));
- }
-#endif
- if(!(chan->RDP)) {
- goto ReturnEnableIntr;
- }
- GetStatus(chan, statusByte);
- if (statusByte & IDE_STATUS_DSC) {
-
- UCHAR PathId = srb->PathId;
- UCHAR TargetId = srb->TargetId;
- UCHAR Lun = srb->Lun;
-
- KdPrint2((PRINT_PREFIX "AtapiCallBack: Found DSC for RDP - %#x\n", srb->Cdb[0]));
- AtapiDmaDBSync(chan, srb);
- UniataRemoveRequest(chan, srb);
- ScsiPortNotification(RequestComplete, deviceExtension, srb);
- // Clear current SRB.
- if(!deviceExtension->simplexOnly) {
- srb = UniataGetCurRequest(chan);
- } else {
- srb = NULL;
- }
- chan->RDP = FALSE;
-
- // Ask for next request.
- ScsiPortNotification(NextLuRequest,
- deviceExtension,
- PathId,
- TargetId,
- Lun);
- ScsiPortNotification(NextRequest, deviceExtension, NULL);
-
- if(srb) {
- AtapiStartIo__(HwDeviceExtension, srb, FALSE);
- }
-
- } else {
- KdPrint2((PRINT_PREFIX "AtapiCallBack: Requesting another timer for Op %#x\n",
- srb->Cdb[0]));
-
- AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
- AtapiCallBack_X,
- 1000);
-
- goto ReturnCallback;
- }
-
-ReturnEnableIntr:
-
- if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
- KdPrint2((PRINT_PREFIX "AtapiCallBack: CallDisableInterrupts\n"));
- //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
-#ifdef UNIATA_USE_XXableInterrupts
- chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
- // must be called on DISPATCH_LEVEL
- ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
- AtapiEnableInterrupts__);
-#else
- AtapiEnableInterrupts(HwDeviceExtension, lChannel);
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- // Will raise IRQL to DIRQL
- AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
- AtapiEnableInterrupts__,
- 1);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
-#endif // UNIATA_USE_XXableInterrupts
- } else {
- //ASSERT(!deviceExtension->simplexOnly);
- }
-
-ReturnCallback:
-
- // Check other channel
- // In simplex mode no interrupts must appear on other channels
- for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
- c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
-
- if(c == lChannel) {
- continue;
- }
-
- chan = &(deviceExtension->chan[c]);
-
- if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
- CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
- CRNT_ILK_TYPE CHECK_INTR_DETECTED) == CHECK_INTR_DETECTED)
- {
- //ASSERT(!deviceExtension->simplexOnly);
- chan->DpcState = DPC_STATE_ISR;
- if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
- InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
- }
- }
- }
- KdPrint2((PRINT_PREFIX "AtapiCallBack: return\n"));
- return;
-
-} // end AtapiCallBack__()
-
-VOID
-NTAPI
-AtapiCallBack_X(
- IN PVOID HwDeviceExtension
- )
-{
- AtapiCallBack__(HwDeviceExtension, (UCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->ActiveDpcChan);
-} // end AtapiCallBack_X()
-
-#endif //UNIATA_CORE
-
-/*++
-
-Routine Description:
-
- This is the interrupt service routine for ATAPI IDE miniport driver.
-
-Arguments:
-
- HwDeviceExtension - HBA miniport driver's adapter data storage
-
-Return Value:
-
- TRUE if expecting an interrupt.
-
---*/
-BOOLEAN
-NTAPI
-AtapiInterrupt(
- IN PVOID HwDeviceExtension
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- ULONG c, _c;
- BOOLEAN status = FALSE;
- ULONG c_state;
- ULONG i_res = 0;
- ULONG pass;
- //BOOLEAN checked[AHCI_MAX_PORT];
- ULONG hIS;
- ULONG checked;
-
- KdPrint2((PRINT_PREFIX "Intr: DeviceID+VendorID/Rev %#x/%#x (ex %d)\n",
- deviceExtension->DevID, deviceExtension->RevID, deviceExtension->ExpectingInterrupt ));
-
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- // AHCI may generate state change notification, never skip this check
- hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
- if(!hIS) {
- return FALSE;
- }
- // 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(!deviceExtension->ExpectingInterrupt) {
- // if we do not expect interrupt, exit now,
- // but keep in mind that it can be unexpected one
- // Note: this is just a hint, not exact counter
- KdPrint2((PRINT_PREFIX "unexpected, 1st chance\n"));
- //deviceExtension->ExpectingInterrupt++;
- //return FALSE;
- }
- // clear this flag now, it can be set again in sub-calls
- deviceExtension->ExpectingInterrupt=0;
-
-
-// for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
-// checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
-// }
-
-// fc =
- for(pass=0; pass<2; pass++) {
- //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
- if(status && pass) {
- // we catched some expected interrupts now.
- // do not touch unexpected until next ISR call
- break;
- }
- for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
-
- c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
-
- if((checked>>c) & 0x01)
- continue;
-
- // check non-empty and expecting interrupt channels first
- if(!pass && !deviceExtension->chan[c].ExpectingInterrupt)
- continue;
-
- checked |= (ULONG)1 << c;
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
-
- if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
- // we get here on idle channels or when ISR is posted to DPC
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): disabled INTR on ch %d\n", c));
- continue;
- }
- // lock channel. Wait, while 2nd ISR checks interrupt on this channel
- do {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): try lock\n"));
- // c_state = deviceExtension->chan[c].CheckIntr;
- // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
- // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
- // }
- c_state =
- (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
- CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
- CRNT_ILK_TYPE CHECK_INTR_DETECTED);
- if(c_state == CHECK_INTR_IDLE) {
- // c_state = deviceExtension->chan[c].CheckIntr;
- // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
- // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
- // }
- c_state =
- (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
- CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
- CRNT_ILK_TYPE CHECK_INTR_IDLE);
- }
- } while(c_state == CHECK_INTR_CHECK);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): locked\n"));
- // check if already serviced
- if(c_state == CHECK_INTR_ACTIVE) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
- continue;
- }
-
- if((c_state == CHECK_INTR_DETECTED) ||
- (i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
-
- if(i_res == INTERRUPT_REASON_UNEXPECTED) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): Catch unexpected\n"));
- InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
- //return TRUE;
- status = TRUE;
- continue;
- }
- // disable interrupts on other channel of legacy mode
- // ISA-bridged onboard controller
- if(deviceExtension->simplexOnly /*||
- ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
- AtapiDisableInterrupts(deviceExtension, !c);
- }
-
- deviceExtension->chan[c].DpcState = DPC_STATE_ISR;
- if(AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
- deviceExtension->LastInterruptedChannel = (UCHAR)c;
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): return status TRUE\n"));
- status = TRUE;
- } else {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
- InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
- }
-
- // re-enable interrupts on other channel
- if(deviceExtension->simplexOnly /*||
- ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
- AtapiEnableInterrupts(deviceExtension, !c);
- }
-
- } else {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
- InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
- }
-
- }
- }
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): exit with status %#x\n", status));
- if(status) {
- deviceExtension->FirstChannelToCheck++;
- if(deviceExtension->FirstChannelToCheck >= deviceExtension->NumberChannels)
- deviceExtension->FirstChannelToCheck = 0;
- }
- return status;
-} // end AtapiInterrupt()
-
-//ULONG i2c = 0;
-#ifndef UNIATA_CORE
-
-BOOLEAN
-NTAPI
-AtapiInterrupt2(
- IN PKINTERRUPT Interrupt,
- IN PVOID Isr2HwDeviceExtension
- )
-{
- // This ISR is intended to catch interrupts when we are already in other ISR instance
- // for the same device. This may happen when we have multiple channels,
- // especially on SMP machines
-
- PISR2_DEVICE_EXTENSION Isr2DeviceExtension = (PISR2_DEVICE_EXTENSION)Isr2HwDeviceExtension;
- PHW_DEVICE_EXTENSION deviceExtension = Isr2DeviceExtension->HwDeviceExtension;
- ULONG c;
- BOOLEAN status = FALSE;
- ULONG c_count = 0;
- ULONG i_res;
- ULONG hIS;
- ULONG checked;
-
- // we should never get here for ISA/MCA
- if(!BMList[deviceExtension->DevIndex].Isr2Enable) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension->DevIndex, deviceExtension->Channel));
- return FALSE;
- }
-
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- // AHCI may generate state change notification, never skip this check
- hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
- if(!hIS) {
- return FALSE;
- }
- // 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(!deviceExtension->ExpectingInterrupt) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
- deviceExtension->ExpectingInterrupt++;
- return FALSE;
- }
- //deviceExtension->ExpectingInterrupt = 0;
-
- for(c=0; c<deviceExtension->NumberChannels; c++) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
-
- if((checked>>c) & 0x01)
- continue;
-
- checked |= (ULONG)1 << c;
-
- if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: disabled INTR\n"));
- continue;
- }
-
- if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
- CRNT_ILK_TYPE CHECK_INTR_CHECK,
- CRNT_ILK_TYPE CHECK_INTR_IDLE) != CHECK_INTR_IDLE)
- {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
- // hunt on unexpected intr (Some devices generate double interrupts,
- // some controllers (at least CMD649) interrupt twice with small delay.
- // If interrupts are disabled, they queue interrupt and re-issue it later,
- // when we do not expect it.
- continue;
- }
-
- c_count++;
- if((i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: intr\n"));
- if(i_res == INTERRUPT_REASON_UNEXPECTED) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: Catch unexpected\n"));
- InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
- return TRUE;
- }
-
- status = TRUE;
- InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_DETECTED);
- } else {
- InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
- }
- }
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: status %d, c_count %d\n", status, c_count));
- if(status && (c_count != deviceExtension->NumberChannels)) {
- // there is an active ISR/DPC for one channel, but
- // we have an interrupt from another one
- // Lets inform current ISR/DPC about new interrupt
- InterlockedExchange(&(deviceExtension->ReCheckIntr), CHECK_INTR_DETECTED);
- } else {
- status = FALSE;
- }
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: return %d\n", status));
- return status;
-
-} // end AtapiInterrupt2()
-
-RETTYPE_XXableInterrupts
-NTAPI
-AtapiInterruptDpc(
- IN PVOID HwDeviceExtension
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- ULONG c;
-
- for(c=0; c<deviceExtension->NumberChannels; c++) {
- KdPrint2((PRINT_PREFIX "AtapiInterruptDpc: %#x\n",c));
-
- if(!(deviceExtension->chan[c].ChannelCtrlFlags & CTRFLAGS_DPC_REQ)) {
-
- if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
- CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
- CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED)
- {
- continue;
- }
-
- } else {
- deviceExtension->chan[c].ChannelCtrlFlags &= ~CTRFLAGS_DPC_REQ;
- }
-/*
- if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
- AtapiDisableInterrupts(deviceExtension, lChannel);
- }
-*/
- deviceExtension->chan[c].DpcState = DPC_STATE_DPC;
- if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
- InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
- }
- }
- return RETVAL_XXableInterrupts;
-} // end AtapiInterruptDpc()
-
-
-RETTYPE_XXableInterrupts
-NTAPI
-AtapiEnableInterrupts__(
- IN PVOID HwDeviceExtension
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__():\n"));
- ULONG c;
- PHW_CHANNEL chan = NULL;
-
- for(c=0; c<deviceExtension->NumberChannels; c++) {
- KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__(2): %#x\n",c));
- chan = &(deviceExtension->chan[c]);
-
- if(chan->ChannelCtrlFlags & CTRFLAGS_ENABLE_INTR_REQ) {
- // enable intrs on requested channel
- chan->ChannelCtrlFlags &= ~CTRFLAGS_ENABLE_INTR_REQ;
- AtapiEnableInterrupts(HwDeviceExtension, c);
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
-
- // check if current or other channel(s) interrupted
- //AtapiInterrupt(HwDeviceExtension);
-
- if(deviceExtension->simplexOnly) {
- break;
- }
- } else {
- // check if other channel(s) interrupted
- // must do nothing in simplex mode
- if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
- CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
- CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) {
- continue;
- }
- //ASSERT(!deviceExtension->simplexOnly);
- chan->DpcState = DPC_STATE_ISR;
- if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
- InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
- }
- }
- }
- // In simplex mode next command must be sent to device here
- if(deviceExtension->simplexOnly && chan) {
- PSCSI_REQUEST_BLOCK srb;
- chan = UniataGetNextChannel(chan);
- if(chan) {
- srb = UniataGetCurRequest(chan);
- } else {
- srb = NULL;
- }
- if(srb) {
- AtapiStartIo__(HwDeviceExtension, srb, FALSE);
- }
- }
-
- return RETVAL_XXableInterrupts;
-
-} // end AtapiEnableInterrupts__()
-
-#endif //UNIATA_CORE
-
-
-VOID
-NTAPI
-AtapiEnableInterrupts(
- IN PVOID HwDeviceExtension,
- IN ULONG c
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PHW_CHANNEL chan;
- //UCHAR statusByte;
-
- if(c >= deviceExtension->NumberChannels) {
- 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(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_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 |
- ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB |
- ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)
- );
- } else {
- //SelectDrive(chan, 0);
- //GetBaseStatus(chan, statusByte);
- AtapiWritePort1(chan, IDX_IO2_o_Control,
- 0 | IDE_DC_A_4BIT );
- //if(chan->NumberLuns) {
- // SelectDrive(chan, 1);
- // GetBaseStatus(chan, statusByte);
- // AtapiWritePort1(chan, IDX_IO2_o_Control,
- // IDE_DC_A_4BIT );
- // SelectDrive(chan, chan->cur_cdev);
- //}
- }
- chan->ChannelCtrlFlags &= ~CTRFLAGS_INTR_DISABLED;
- } else {
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- // keep interrupts disabled
- UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
- } else {
- AtapiWritePort1(chan, IDX_IO2_o_Control,
- IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
- }
- }
- return;
-} // end AtapiEnableInterrupts()
-
-VOID
-NTAPI
-AtapiDisableInterrupts(
- IN PVOID HwDeviceExtension,
- IN ULONG c
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PHW_CHANNEL chan;
- if(c >= deviceExtension->NumberChannels) {
- KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c));
- return;
- }
- chan = &(deviceExtension->chan[c]);
- KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: %d\n",c, chan->DisableIntr));
- // mark channel as busy
- if(InterlockedIncrement(&chan->DisableIntr)) {
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
- } else {
- //SelectDrive(chan, 0);
- AtapiWritePort1(chan, IDX_IO2_o_Control,
- IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
- //if(chan->NumberLuns) {
- // SelectDrive(chan, 1);
- // AtapiWritePort1(chan, IDX_IO2_o_Control,
- // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
- // SelectDrive(chan, chan->cur_cdev);
- //}
- }
- chan->ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED;
- }
-
- return;
-} // end AtapiDisableInterrupts()
-
-VOID
-UniataExpectChannelInterrupt(
- IN struct _HW_CHANNEL* chan,
- IN BOOLEAN Expecting
- )
-{
- chan->ExpectingInterrupt = Expecting;
- if(Expecting) {
- chan->DeviceExtension->ExpectingInterrupt++;
- } else
- if(chan->DeviceExtension->ExpectingInterrupt) {
- chan->DeviceExtension->ExpectingInterrupt--;
- }
- return;
-} // end UniataExpectChannelInterrupt()
-
-/*
- Check hardware for interrupt state
- */
-BOOLEAN
-NTAPI
-AtapiCheckInterrupt__(
- IN PVOID HwDeviceExtension,
- IN UCHAR c // logical channel
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PHW_CHANNEL chan = &(deviceExtension->chan[c]);
- PHW_LU_EXTENSION LunExt;
-
- ULONG VendorID = deviceExtension->DevID & 0xffff;
- ULONG ChipType = deviceExtension->HwFlags & CHIPTYPE_MASK;
-
- ULONG status;
- ULONG pr_status = 0;
- UCHAR dma_status = 0;
- UCHAR reg8 = 0;
- ULONG reg32 = 0;
- UCHAR statusByte = 0;
- ULONG slotNumber = deviceExtension->slotNumber;
- ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
- ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
- UCHAR Channel;
- UCHAR lChannel;
- BOOLEAN DmaTransfer = FALSE;
- BOOLEAN OurInterrupt = FALSE;
- BOOLEAN StatusValid = FALSE;
-// ULONG k;
- UCHAR interruptReason;
- BOOLEAN EarlyIntr = FALSE;
- BOOLEAN SingleBlockIntr = FALSE;
-
- KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__:\n"));
-
- lChannel = c;
- Channel = (UCHAR)(deviceExtension->Channel + lChannel);
- LunExt = chan->lun[chan->cur_cdev];
-
- //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
- //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
-
- 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)) {
- UniataAhciWaitCommandReady(chan, 2 /* ms */ );
- statusByte = (UCHAR)UniataAhciWaitReady(chan, 0 /* immediate */);
- if(!(statusByte & (IDE_STATUS_BUSY)) ) {
- KdPrint2((PRINT_PREFIX "ATAPI special case READY\n"));
- //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
- OurInterrupt = INTERRUPT_REASON_OUR;
- } else
- if((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRDY)) == (IDE_STATUS_BUSY | IDE_STATUS_DRDY) ) {
- KdPrint2((PRINT_PREFIX "ATAPI special case pre ERR-READY\n"));
- OurInterrupt = INTERRUPT_REASON_OUR;
- } else
- if(statusByte & IDE_STATUS_ERROR) {
- KdPrint2((PRINT_PREFIX "ATAPI special case ERR-READY\n"));
- OurInterrupt = INTERRUPT_REASON_OUR;
- } else {
- KdPrint2((PRINT_PREFIX "ATAPI special case ? %x\n", statusByte));
- OurInterrupt = INTERRUPT_REASON_OUR;
- }
- }
- return OurInterrupt;
- }
-
- if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
- DmaTransfer = TRUE;
- KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension->DevIndex,
- deviceExtension->Channel + c, c));
- } else {
- KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension->DevIndex,
- deviceExtension->Channel + c, c));
- dma_status = GetDmaStatus(deviceExtension, lChannel);
- KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
- }
-
- // do controller-specific interrupt servicing staff
- if(deviceExtension->UnknownDev) {
- KdPrint2((PRINT_PREFIX " UnknownDev\n"));
- goto check_unknown;
- }
-
- // Attention !
- // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
- // Such behavior was observed with Intel ICH-xxx chips
- // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
-
- switch(VendorID) {
-
- case ATA_PROMISE_ID: {
- switch(ChipType) {
- case PROLD:
- case PRNEW:
- status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1c);
- if (!DmaTransfer)
- break;
- if (!(status &
- ((Channel) ? 0x00004000 : 0x00000400))) {
- KdPrint2((PRINT_PREFIX " Promise old/new unexpected\n"));
- return INTERRUPT_REASON_IGNORE;
- }
- break;
- case PRTX:
- AtapiWritePort1(chan, IDX_BM_DeviceSpecific0, 0x0b);
- status = AtapiReadPort1(chan, IDX_BM_DeviceSpecific1);
- if (!DmaTransfer)
- break;
- if(!(status & 0x20)) {
- KdPrint2((PRINT_PREFIX " Promise tx unexpected\n"));
- return INTERRUPT_REASON_IGNORE;
- }
- break;
- 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"));
- UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
- }
- if(!(status & (0x01 << Channel))) {
- // 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; }
- case ATA_NVIDIA_ID: {
- if(!(ChipFlags & UNIATA_SATA))
- break;
-
- KdPrint2((PRINT_PREFIX "NVIDIA\n"));
-
- ULONG offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
- ULONG shift = Channel * ((ChipFlags & NVQ) ? 4 : 16);
-
- /* get and clear interrupt status */
- if(ChipFlags & NVQ) {
- pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
- AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0fUL << shift) | 0x00f000f0);
- } else {
- pr_status = AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
- AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0f << shift));
- }
- KdPrint2((PRINT_PREFIX " pr_status %x, shift %x\n", pr_status, shift));
-
- /* check for and handle connect events */
- if(((pr_status & (0x0cUL << shift)) == (0x04UL << shift)) ) {
- UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0);
- }
- /* check for and handle disconnect events */
- if((pr_status & (0x08UL << shift)) &&
- !((pr_status & (0x04UL << shift) &&
- UniataSataReadPort4(chan, IDX_SATA_SStatus, 0))) ) {
- UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
- }
- /* do we have any device action ? */
- if(!(pr_status & (0x01UL << shift))) {
- KdPrint2((PRINT_PREFIX " nVidia unexpected\n"));
- if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
- OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
- } else {
- return INTERRUPT_REASON_IGNORE;
- }
- }
-
- break; }
- case ATA_ATI_ID:
- KdPrint2((PRINT_PREFIX "ATI\n"));
- if(ChipType == SIIMIO) {
- // fall to SiI
- } else {
- break;
- }
- case ATA_SILICON_IMAGE_ID:
-
- if(ChipType == SIIMIO) {
-
- reg32 = AtapiReadPort4(chan, IDX_BM_DeviceSpecific0);
- KdPrint2((PRINT_PREFIX " Sii DS0 %x\n", reg32));
- if(reg32 == 0xffffffff) {
- KdPrint2((PRINT_PREFIX " Sii mio unexpected\n"));
- return INTERRUPT_REASON_IGNORE;
- }
- if(!(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_DMA_COMPLETE | BM_DS0_SII_IRQ | BM_DS0_SII_DMA_ENABLE | BM_DS0_SII_DMA_ERROR))) {
- KdPrint2((PRINT_PREFIX " Sii mio unexpected (2)\n"));
- return INTERRUPT_REASON_IGNORE;
- }
-
- if(ChipFlags & UNIATA_SATA) {
- if(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_IRQ)) {
-
- /* SIEN doesn't mask SATA IRQs on some 3112s. Those
- * controllers continue to assert IRQ as long as
- * SError bits are pending. Clear SError immediately.
- */
- if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
- OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
- }
- }
- }
-
- if (!DmaTransfer)
- break;
- if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
- KdPrint2((PRINT_PREFIX " Sii mio unexpected (3)\n"));
- return OurInterrupt;
- }
- AtapiWritePort1(chan, IDX_BM_Status, dma_status & ~BM_STATUS_ERR);
- goto skip_dma_stat_check;
-
- } else {
- if(!(deviceExtension->HwFlags & SIIINTR))
- break;
- GetPciConfig1(0x71, reg8);
- KdPrint2((PRINT_PREFIX " 0x71 = %#x\n", reg8));
- if (!(reg8 &
- (Channel ? 0x08 : 0x04))) {
- return INTERRUPT_REASON_IGNORE;
- }
- if (!DmaTransfer) {
- KdPrint2((PRINT_PREFIX " cmd our\n"));
- OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
- }
- SetPciConfig1(0x71, (Channel ? 0x08 : 0x04));
- }
- break;
-
- case ATA_ACARD_ID:
- if (!DmaTransfer)
- break;
- //dma_status = GetDmaStatus(deviceExtension, lChannel);
- if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
- KdPrint2((PRINT_PREFIX " Acard unexpected\n"));
- return INTERRUPT_REASON_IGNORE;
- }
- AtapiWritePort1(chan, IDX_BM_Status, dma_status | BM_STATUS_INTR);
- AtapiStallExecution(1);
- AtapiWritePort1(chan, IDX_BM_Command,
- AtapiReadPort1(chan, IDX_BM_Command) & ~BM_COMMAND_START_STOP);
- goto skip_dma_stat_check;
- case ATA_INTEL_ID:
- if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- if(ChipFlags & UNIATA_AHCI) {
- // Do nothing here
- } else
- if(ChipFlags & UNIATA_SATA) {
- if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
- OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
- }
- if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
- if(UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1)) {
- OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
- }
- }
- }
- }
- break;
- default:
- if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- if(ChipFlags & UNIATA_AHCI) {
- // Do nothing here
- } else
- if(ChipFlags & UNIATA_SATA) {
- if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
- OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
- }
- }
- }
- }
-check_unknown:
- KdPrint2((PRINT_PREFIX " perform generic check\n"));
- if (DmaTransfer) {
- if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
- KdPrint2((PRINT_PREFIX " DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status));
- if(dma_status & BM_STATUS_ERR) {
- KdPrint2((PRINT_PREFIX " DmaTransfer + BM_STATUS_ERR -> our\n"));
- OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
- } else {
- KdPrint2((PRINT_PREFIX " getting status...\n"));
- GetStatus(chan, statusByte);
- StatusValid = 1;
- KdPrint2((PRINT_PREFIX " status %#x\n", statusByte));
- if(statusByte & IDE_STATUS_ERROR) {
- KdPrint2((PRINT_PREFIX " IDE_STATUS_ERROR -> our\n", statusByte));
- OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
- } else
- if ((statusByte & IDE_STATUS_DSC) &&
- (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
- (dma_status == BM_STATUS_ACTIVE)) {
- KdPrint2((PRINT_PREFIX " special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte));
- // some devices interrupts on each block transfer even in DMA mode
- if(LunExt->TransferMode >= ATA_SDMA && LunExt->TransferMode <= ATA_WDMA2) {
- KdPrint2((PRINT_PREFIX " wait for completion\n"));
- ///* clear interrupt and get status */
- //GetBaseStatus(chan, statusByte);
- //return INTERRUPT_REASON_IGNORE;
- SingleBlockIntr = TRUE;
- }
- } else {
- return INTERRUPT_REASON_IGNORE;
- }
- }
- }
- } else {
- if(dma_status & BM_STATUS_INTR) {
- // bullshit, we have DMA interrupt, but had never initiate DMA operation
- KdPrint2((PRINT_PREFIX " clear unexpected DMA intr\n"));
- AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
- // catch it !
- OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
- }
- }
-skip_dma_stat_check:
- if(!(ChipFlags & UNIATA_SATA) && chan->ExpectingInterrupt) {
- AtapiStallExecution(1);
- }
-
- /* if drive is busy it didn't interrupt */
- /* the exception is DCS + BSY state of ATAPI devices */
- if(!StatusValid) {
- KdPrint2((PRINT_PREFIX " getting status...\n"));
- GetStatus(chan, statusByte);
- }
- if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
- KdPrint3((PRINT_PREFIX " ATAPI status %#x\n", statusByte));
- } else {
- KdPrint2((PRINT_PREFIX " IDE status %#x\n", statusByte));
- }
- if (statusByte == IDE_STATUS_WRONG) {
- // interrupt from empty controller ?
- } else
- if (statusByte & IDE_STATUS_BUSY) {
- if(!chan->ExpectingInterrupt) {
- KdPrint3((PRINT_PREFIX " unexpected intr + BUSY\n"));
- return OurInterrupt;
- }
-
- if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
- KdPrint2((PRINT_PREFIX " ATAPI additional check\n"));
- } else {
- KdPrint2((PRINT_PREFIX " expecting intr + BUSY (3), non ATAPI\n"));
- return INTERRUPT_REASON_IGNORE;
- }
- if((statusByte & ~(IDE_STATUS_DRQ | IDE_STATUS_INDEX)) !=
- (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) {
- KdPrint3((PRINT_PREFIX " unexpected status, seems it is not our\n"));
- return INTERRUPT_REASON_IGNORE;
- }
- if(!(LunExt->DeviceFlags & DFLAGS_INT_DRQ) && (statusByte & IDE_STATUS_DRQ)) {
- KdPrint3((PRINT_PREFIX " unexpected DRQ, seems it is not our\n"));
- return INTERRUPT_REASON_IGNORE;
- }
-
- EarlyIntr = TRUE;
-
- if(dma_status & BM_STATUS_INTR) {
- KdPrint3((PRINT_PREFIX " our interrupt with BSY set, try wait in ISR or post to DPC\n"));
- /* clear interrupt and get status */
- GetBaseStatus(chan, statusByte);
- if(!(dma_status & BM_STATUS_ACTIVE)) {
- AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
- }
- KdPrint3((PRINT_PREFIX " base status %#x (+BM_STATUS_INTR)\n", statusByte));
- return INTERRUPT_REASON_OUR;
- }
-
- if(g_WaitBusyInISR) {
- GetStatus(chan, statusByte);
- KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte));
- reg8 = AtapiReadPort1(chan, IDX_IO1_i_Error);
- KdPrint2((PRINT_PREFIX " Error reg (%#x)\n", reg8));
- if (!(statusByte & IDE_STATUS_BUSY)) {
- KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n"));
- }
- if (statusByte & IDE_STATUS_BUSY) {
- KdPrint2((PRINT_PREFIX " still BUSY, seems it is not our\n"));
- return INTERRUPT_REASON_IGNORE;
- }
- }
-
- }
-
- /* clear interrupt and get status */
- GetBaseStatus(chan, statusByte);
- KdPrint2((PRINT_PREFIX " base status %#x\n", statusByte));
- if (statusByte == IDE_STATUS_WRONG) {
- // interrupt from empty controller ?
- } else
- if(!(statusByte & (IDE_STATUS_DRQ | IDE_STATUS_DRDY))) {
- KdPrint2((PRINT_PREFIX " no DRQ/DRDY set\n"));
- return OurInterrupt;
- }
-
-#ifndef UNIATA_PIO_ONLY
- if(DmaTransfer) {
- if(!SingleBlockIntr && (!EarlyIntr || g_WaitBusyInISR)) {
- dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
- } else {
- PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
- PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
-
- //ASSERT(AtaReq);
-
- if(SingleBlockIntr) {
- KdPrint2((PRINT_PREFIX " set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
- } else {
- KdPrint2((PRINT_PREFIX " set REQ_STATE_EARLY_INTR.\n"));
- }
- if(AtaReq) {
- AtaReq->ReqState = SingleBlockIntr ? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2 : REQ_STATE_EARLY_INTR;
- }
- }
- }
-#endif //
-
- if (!(chan->ExpectingInterrupt)) {
-
- KdPrint2((PRINT_PREFIX " Unexpected interrupt.\n"));
-
- if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
- KdPrint2((PRINT_PREFIX " ATAPI additional check\n"));
- } else {
- KdPrint2((PRINT_PREFIX " OurInterrupt = %d\n", OurInterrupt));
- return OurInterrupt;
- }
- interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
- KdPrint3((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason));
- return OurInterrupt;
- }
- //ASSERT(!chan->queue_depth || chan->cur_req);
-
- KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__: exit with TRUE\n"));
- return INTERRUPT_REASON_OUR;
-
-} // end AtapiCheckInterrupt__()
-
-
-BOOLEAN
-NTAPI
-AtapiInterrupt__(
- IN PVOID HwDeviceExtension,
- IN UCHAR c
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PHW_CHANNEL chan = &(deviceExtension->chan[c]);
- // Get current Srb
- PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
- PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
-
- ULONG wordCount = 0, wordsThisInterrupt = DEV_BSIZE/2;
- ULONG status = SRB_STATUS_SUCCESS;
- UCHAR dma_status = 0;
- ULONG i;
- ULONG k;
- UCHAR statusByte = 0,interruptReason;
-
- BOOLEAN atapiDev = FALSE;
-
-#ifdef _DEBUG
- UCHAR Channel;
-#endif //_DEBUG
- UCHAR lChannel;
- UCHAR DeviceNumber;
- BOOLEAN DmaTransfer = FALSE;
- UCHAR error = 0;
- ULONG TimerValue = 1000;
- ULONG TotalTimerValue = 0;
-#ifdef UNIATA_USE_XXableInterrupts
- BOOLEAN InDpc = (KeGetCurrentIrql() == DISPATCH_LEVEL);
-#else
- BOOLEAN InDpc = (chan->DpcState != DPC_STATE_ISR);
-#endif // UNIATA_USE_XXableInterrupts
- BOOLEAN UseDpc = deviceExtension->UseDpc;
-// BOOLEAN RestoreUseDpc = FALSE;
- BOOLEAN DataOverrun = FALSE;
- BOOLEAN NoStartIo = TRUE;
- BOOLEAN NoRetry = FALSE;
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt:\n"));
- if(InDpc) {
- KdPrint2((PRINT_PREFIX " InDpc = TRUE\n"));
- //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
- }
-
- UCHAR PathId;
- UCHAR TargetId;
- UCHAR Lun;
- UCHAR OldReqState = REQ_STATE_NONE;
- //ULONG ldev;
- PHW_LU_EXTENSION LunExt;
-
- lChannel = c;
-
-#ifdef _DEBUG
- Channel = (UCHAR)(deviceExtension->Channel + lChannel);
-
- KdPrint2((PRINT_PREFIX " cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c));
-#endif //_DEBUG
-
- if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
- (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ||
- (deviceExtension->HwFlags & UNIATA_AHCI)) {
- DmaTransfer = TRUE;
- KdPrint2((PRINT_PREFIX " DmaTransfer = TRUE\n"));
- }
-
- if (srb) {
- PathId = srb->PathId;
- TargetId = srb->TargetId;
- Lun = srb->Lun;
- } else {
- PathId = (UCHAR)c;
- TargetId =
- Lun = 0;
- goto enqueue_next_req;
- }
-
- //ldev = GET_LDEV2(PathId, TargetId, Lun);
- DeviceNumber = (UCHAR)(TargetId);
- LunExt = chan->lun[DeviceNumber];
- atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
- KdPrint2((PRINT_PREFIX " dev_type %s\n", atapiDev ? "ATAPI" : "IDE"));
-
- // check if we are in ISR DPC
- if(InDpc) {
- KdPrint2((PRINT_PREFIX " InDpc -> CTRFLAGS_INTR_DISABLED\n"));
- goto ServiceInterrupt;
- }
-
- if (DmaTransfer) {
- dma_status = GetDmaStatus(deviceExtension, lChannel);
- }
-
- if (!(chan->ExpectingInterrupt)) {
-
- KdPrint2((PRINT_PREFIX " Unexpected interrupt for this channel.\n"));
- return FALSE;
- }
-
- // change request state
- if(AtaReq) {
- OldReqState = AtaReq->ReqState;
- AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
- KdPrint2((PRINT_PREFIX " OldReqState = %x\n", OldReqState));
- }
-
- // We don't want using DPC for fast operations, like
- // DMA completion, sending CDB, short ATAPI transfers, etc.
- // !!!! BUT !!!!
- // We MUST use DPC, because of interprocessor synchronization
- // on multiprocessor platforms
-
- if(DmaTransfer)
- goto ServiceInterrupt;
-
- switch(OldReqState) {
- case REQ_STATE_ATAPI_EXPECTING_CMD_INTR:
- KdPrint3((PRINT_PREFIX " EXPECTING_CMD_INTR\n"));
- case REQ_STATE_ATAPI_EXPECTING_DATA_INTR:
- case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2:
- case REQ_STATE_DPC_WAIT_BUSY0:
- case REQ_STATE_DPC_WAIT_BUSY1:
- KdPrint2((PRINT_PREFIX " continue service interrupt\n"));
- goto ServiceInterrupt;
- case REQ_STATE_ATAPI_DO_NOTHING_INTR:
- KdPrint2((PRINT_PREFIX " do nothing on interrupt\n"));
- return TRUE;
- }
-
- if((!DmaTransfer && !atapiDev) || deviceExtension->DriverMustPoll) {
- KdPrint2((PRINT_PREFIX " service PIO HDD\n"));
- UseDpc = FALSE;
- }
-
-#ifndef UNIATA_CORE
-
- if(!UseDpc)
- goto ServiceInterrupt;
-
-#ifdef UNIATA_USE_XXableInterrupts
- if(InDpc) {
- KdPrint2((PRINT_PREFIX " Unexpected InDpc\n"));
- ASSERT(FALSE);
- // shall never get here
- TimerValue = 1;
- goto CallTimerDpc;
- }
-
- KdPrint2((PRINT_PREFIX " this is direct DPC call on DRQL\n"));
- if(AtaReq) {
- AtaReq->ReqState = REQ_STATE_DPC_INTR_REQ;
- KdPrint2((PRINT_PREFIX " ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
- } else {
- KdPrint2((PRINT_PREFIX " DPC without AtaReq!!!\n"));
- }
-#else
- KdPrint2((PRINT_PREFIX "call service interrupt\n"));
- goto ServiceInterrupt;
-#endif // UNIATA_USE_XXableInterrupts
-
-PostToDpc:
-
- // Attention !!!
- // AtapiInterruptDpc() is called on DISPATCH_LEVEL
- // We always get here when are called from timer callback, which is invoked on DRQL.
- // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: start DPC init...\n"));
- // disable interrupts for this channel,
- // but avoid recursion and double-disable
- if(OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
- UniataExpectChannelInterrupt(chan, FALSE);
- AtapiDisableInterrupts(deviceExtension, lChannel);
- }
- // go to ISR DPC
- chan->ChannelCtrlFlags |= CTRFLAGS_DPC_REQ;
-
-#ifdef UNIATA_USE_XXableInterrupts
- // Will lower IRQL to DISPATCH_LEVEL
- ScsiPortNotification(CallEnableInterrupts, HwDeviceExtension,
- /*c ?*/ AtapiInterruptDpc/*_1 : AtapiInterruptDpc_0*/);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: DPC inited\n"));
-#else
- // Will raise IRQL to DIRQL
- AtapiQueueTimerDpc(HwDeviceExtension, c,
- AtapiInterruptDpc,
- TimerValue);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
-#endif // UNIATA_USE_XXableInterrupts
- return TRUE;
-
-#ifndef UNIATA_CORE
-CallTimerDpc:
- AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
-CallTimerDpc2:
- if(!InDpc && OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
- // we must block interrupts from this channel
- // If device generate new interrupt before we get to DPC,
- // ISR will assume, that it is NOT our interrupt
- AtapiDisableInterrupts(deviceExtension, lChannel);
- // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
- }
- // Will raise IRQL to DIRQL
- AtapiQueueTimerDpc(HwDeviceExtension, c,
- AtapiCallBack_X,
- TimerValue);
- return TRUE;
-#endif //UNIATA_CORE
-
-ServiceInterrupt:
-
- if(AtaReq && InDpc) {
- switch(AtaReq->ReqState) {
- case REQ_STATE_DPC_WAIT_DRQ0:
- goto PIO_wait_DRQ0;
- case REQ_STATE_DPC_WAIT_BUSY:
- goto PIO_wait_busy;
- case REQ_STATE_DPC_WAIT_DRQ:
- goto PIO_wait_DRQ;
- case REQ_STATE_DPC_WAIT_DRQ_ERR:
- goto continue_err;
- case REQ_STATE_DPC_WAIT_BUSY0:
- case REQ_STATE_DPC_WAIT_BUSY1:
- // continue normal execution
- break;
- }
- }
-#else
-ServiceInterrupt:
-#endif //UNIATA_CORE
-/*
- // make additional delay for old devices (if we are not in DPC)
- if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
- &&
- !InDpc &&
- !atapiDev &&
- !(deviceExtension->HwFlags & UNIATA_SATA)
- ) {
- KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
- AtapiStallExecution(10);
- }
-*/
-
- /* clear interrupt and get status */
- 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), 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
-#ifdef _DEBUG
- UniataDumpAhciPortRegs(chan);
-#endif
- if(!UniataAhciAbortOperation(chan)) {
- KdPrint2((PRINT_PREFIX "need UniataAhciReset\n"));
- }
-#ifdef _DEBUG
- UniataDumpAhciPortRegs(chan);
-#endif
- UniataAhciWaitCommandReady(chan, 10);
- }
- }
-
- } else {
- GetBaseStatus(chan, statusByte);
- }
- if(atapiDev) {
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte));
- } else {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: Entered with status (%#x)\n", statusByte));
- }
-
- if(!UseDpc) {
- KdPrint2((PRINT_PREFIX " operate like in DPC\n"));
- InDpc = TRUE;
- }
-
- if (!atapiDev) {
- // IDE
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint3((PRINT_PREFIX " AHCI branch (IDE)\n"));
- } else
- if (statusByte & IDE_STATUS_BUSY) {
- if (deviceExtension->DriverMustPoll) {
- // Crashdump is polling and we got caught with busy asserted.
- // Just go away, and we will be polled again shortly.
- KdPrint2((PRINT_PREFIX " Hit BUSY while polling during crashdump.\n"));
- goto ReturnEnableIntr;
- }
-try_dpc_wait:
- // Ensure BUSY is non-asserted.
- // make a very small idle before falling to DPC
- k = (InDpc && UseDpc) ? 1000 : 2;
-
- for (i = 0; i < k; i++) {
-
- GetBaseStatus(chan, statusByte);
- if (!(statusByte & IDE_STATUS_BUSY)) {
- break;
- }
- AtapiStallExecution(10);
- }
-
- if (!InDpc && UseDpc && i == 2) {
-
- KdPrint2((PRINT_PREFIX " BUSY on entry. Status %#x, Base IO %#x\n", statusByte));
-
- TimerValue = 50;
- AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
-
-#ifndef UNIATA_CORE
- goto PostToDpc;
-#else //UNIATA_CORE
- AtapiStallExecution(TimerValue);
- goto ServiceInterrupt;
-#endif //UNIATA_CORE
- } else
- if (InDpc && i == k) {
- // reset the controller.
- KdPrint2((PRINT_PREFIX
- " Resetting due to BUSY on entry - %#x.\n",
- statusByte));
- goto IntrPrepareResetController;
- }
- }
- } else {
- // ATAPI
- if(!LunExt->IdentifyData.MajorRevision &&
- InDpc &&
- /*!atapiDev &&*/
- !(deviceExtension->HwFlags & UNIATA_SATA)
- ) {
- //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
- //AtapiStallExecution(10);
- }
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint3((PRINT_PREFIX " AHCI branch (ATAPI)\n"));
- } else {
- interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
- }
-
- if (statusByte & IDE_STATUS_BUSY) {
- //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
-/*
-#ifndef UNIATA_CORE
- // This is just workaround
- // We should DISABLE interrupts before entering WAIT state
- UniataExpectChannelInterrupt(chan, TRUE);
-#endif //UNIATA_CORE
-*/
- KdPrint3((PRINT_PREFIX " BUSY on ATAPI device, waiting %d us\n", LunExt->AtapiReadyWaitDelay));
-#ifndef UNIATA_CORE
- if(LunExt->AtapiReadyWaitDelay && (LunExt->AtapiReadyWaitDelay > g_opt_MaxIsrWait) && !InDpc && UseDpc) {
- TimerValue = LunExt->AtapiReadyWaitDelay;
- KdPrint2((PRINT_PREFIX " too long wait: ISR -> DPC (0)\n"));
- AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
- goto CallTimerDpc2;
- }
-#endif //UNIATA_CORE
- TimerValue = 10;
- for(k=20; k; k--) {
- GetBaseStatus(chan, statusByte);
- KdPrint3((PRINT_PREFIX " status re-check %#x\n", statusByte));
- KdPrint3((PRINT_PREFIX " Error reg (%#x)\n",
- AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Error)));
- if (!(statusByte & IDE_STATUS_BUSY)) {
- KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n"));
- break;
- }
- TotalTimerValue += TimerValue;
- if(k <= 1) {
- KdPrint3((PRINT_PREFIX " too long wait -> DPC\n"));
- if(!InDpc) {
- KdPrint2((PRINT_PREFIX " too long wait: ISR -> DPC\n"));
- TimerValue = 100;
- AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
- } else {
- KdPrint2((PRINT_PREFIX " too long wait: DPC -> DPC\n"));
- TimerValue = 1000;
- AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY1;
- }
-#ifndef UNIATA_CORE
- if(UseDpc) {
- if(!LunExt->AtapiReadyWaitDelay) {
- LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3;
- }
- goto CallTimerDpc2;
- }
-#endif //UNIATA_CORE
- }
-
- AtapiStallExecution(TimerValue);
- TimerValue += 10;
- }
- if(!LunExt->AtapiReadyWaitDelay) {
- LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3;
- KdPrint2((PRINT_PREFIX " store AtapiReadyWaitDelay: %d\n", LunExt->AtapiReadyWaitDelay));
- }
- if (statusByte & IDE_STATUS_BUSY) {
- KdPrint3((PRINT_PREFIX " expecting intr + BUSY (2), try DPC wait\n"));
- goto try_dpc_wait;
- }
- }
- }
-
- if(AtaReq && DmaTransfer && !(deviceExtension->HwFlags & UNIATA_AHCI)) {
- switch(OldReqState) {
- case REQ_STATE_EARLY_INTR:
- case REQ_STATE_DPC_WAIT_BUSY0:
-
- if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: DMA still active\n"));
- dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
- }
- break;
- }
- }
-
-//retry_check:
- // Check for error conditions.
- if ((statusByte & IDE_STATUS_ERROR) ||
- (dma_status & BM_STATUS_ERR)) {
-
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- error = AtaReq->ahci.in_error;
- // wait ready
-#ifdef _DEBUG
- UniataDumpAhciPortRegs(chan);
-#endif
- if(!UniataAhciAbortOperation(chan)) {
- KdPrint2((PRINT_PREFIX "need UniataAhciReset\n"));
- }
- // clear interrupts again
- UniataAhciWaitCommandReady(chan, 10);
-#ifdef _DEBUG
- UniataDumpAhciPortRegs(chan);
-#endif
- UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
- 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 {
- error = AtapiReadPort1(chan, IDX_IO1_i_Error);
- }
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: Error %#x\n", error));
-/*
- if(error & IDE_STATUS_CORRECTED_ERROR) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
- statusByte &= ~IDE_STATUS_ERROR;
- goto retry_check;
- }
-*/
- if(AtaReq) {
- KdPrint2((PRINT_PREFIX " Bad Lba %#I64x\n", AtaReq->lba));
- } 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);
- } else {
- KdPrint2((PRINT_PREFIX " wait 10 ready after ATAPI error\n"));
- AtapiStallExecution(10);
- }
-continue_err:
-
- KdPrint3((PRINT_PREFIX " Intr on DRQ %x\n",
- LunExt->DeviceFlags & DFLAGS_INT_DRQ));
-
- for (k = atapiDev ? 0 : 200; k; k--) {
- GetBaseStatus(chan, statusByte);
- if (!(statusByte & IDE_STATUS_DRQ)) {
- AtapiStallExecution(50);
- } else {
- break;
- }
- }
-
- if (!atapiDev) {
- /* if this is a UDMA CRC error, reinject request */
-
- AtaReq->retry++;
- if(AtaReq->retry < MAX_RETRIES) {
-#ifdef IO_STATISTICS
- chan->lun[DeviceNumber]->ModeErrorCount[AtaReq->retry]++;
-#endif //IO_STATISTICS
- if(DmaTransfer /*&&
- (error & IDE_ERROR_ICRC)*/) {
- KdPrint2((PRINT_PREFIX "Errors in DMA mode\n"));
- if(AtaReq->retry < MAX_RETRIES) {
-//fallback_pio:
- if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
- //AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
- // Downrate will happen in AtapiDmaReinit(), try UDMA-2 for HDD only
- AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
- }
- AtaReq->ReqState = REQ_STATE_QUEUED;
- goto reenqueue_req;
- }
- } else {
- if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
- AtaReq->retry++;
- }
- KdPrint2((PRINT_PREFIX "Errors in PIO mode\n"));
- }
- }
- } else {
- interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason));
-
- if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- // Do nothing here
- } else
- if(deviceExtension->HwFlags & UNIATA_SATA) {
- UniataSataClearErr(HwDeviceExtension, lChannel, UNIATA_SATA_IGNORE_CONNECT, 0);
- }
- }
-
- if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) &&
- ((error >> 4) == SCSI_SENSE_HARDWARE_ERROR)) {
- if(AtaReq->retry < MAX_RETRIES) {
-//fallback_pio:
- // Downrate will happen in AtapiDmaReinit(), use PIO immediately for ATAPI
- 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 {
- if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
- AtaReq->retry++;
- }
- KdPrint3((PRINT_PREFIX "Errors in PIO mode\n"));
- }
- }
-
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error\n"));
- if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
- // Fail this request.
- status = SRB_STATUS_ERROR;
- goto CompleteRequest;
- } else {
- KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n"));
- }
- } else
- if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE_LBA48) {
- KdPrint2((PRINT_PREFIX "DMA doesn't work right with LBA48\n"));
- deviceExtension->HbaCtrlFlags |= HBAFLAGS_DMA_DISABLED_LBA48;
- } else
- if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE) {
-#ifdef IO_STATISTICS
- KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n"));
- KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n",
- AtaReq->retry,
- LunExt->RecoverCount[AtaReq->retry],
- LunExt->BlockIoCount
- ));
- LunExt->RecoverCount[AtaReq->retry]++;
- if(LunExt->RecoverCount[AtaReq->retry] >= LunExt->BlockIoCount/3 ||
- (deviceExtension->HwFlags & UNIATA_NO80CHK)
- ) {
-#else
- if(deviceExtension->HwFlags & UNIATA_NO80CHK) {
-#endif //IO_STATISTICS
- 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
- LunExt->BlockIoCount++;
- }
- LunExt->IoCount++;
-#endif //IO_STATISTICS
-
-continue_PIO:
-
- // check reason for this interrupt.
- if (atapiDev) {
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI branch\n"));
- // ATAPI branch
-
- 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;
- } else {
- wordsThisInterrupt = DEV_BSIZE/2;
- }
-
- } else {
-
- // ATA branch
-
- if(DmaTransfer) {
- // simulate DRQ for DMA transfers
- statusByte |= IDE_STATUS_DRQ;
- }
- if (statusByte & IDE_STATUS_DRQ) {
-
- if(DmaTransfer) {
- wordsThisInterrupt = DEV_BSIZE/2*512;
- } else
- if (LunExt->MaximumBlockXfer) {
- wordsThisInterrupt = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
- }
-
- if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
-
- interruptReason = ATAPI_IR_IO_toHost;
-
- } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
- interruptReason = ATAPI_IR_IO_toDev;
-
- } else {
- status = SRB_STATUS_ERROR;
- goto CompleteRequest;
- }
-
- } else if (statusByte & IDE_STATUS_BUSY) {
-
- //AtapiEnableInterrupts(deviceExtension, lChannel);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
- return FALSE;
-
- } else {
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: !DRQ, !BUSY, WordsLeft %#x\n", AtaReq->WordsLeft));
- if (AtaReq->WordsLeft) {
-
- // Funky behaviour seen with PCI IDE (not all, just one).
-PIO_wait_DRQ0:
- // The ISR hits with DRQ low, but comes up later.
- for (k = 0; k < 5000; k++) {
- GetBaseStatus(chan, statusByte);
- if (statusByte & IDE_STATUS_DRQ) {
- break;
- }
- if(!InDpc) {
- // goto DPC
- AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ0;
- TimerValue = 100;
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq0)\n"));
-#ifndef UNIATA_CORE
- goto PostToDpc;
-#else //UNIATA_CORE
- AtapiStallExecution(TimerValue);
- goto ServiceInterrupt;
-#endif //UNIATA_CORE
- }
- AtapiStallExecution(100);
- }
- if (k == 5000) {
- // reset the controller.
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
- statusByte));
-IntrPrepareResetController:
- AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_CURRENT);
- goto ReturnEnableIntr;
-
- } else {
- 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 = ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd;
- }
- }
- }
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason, statusByte));
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint2((PRINT_PREFIX " AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq->WordsTransfered, AtaReq->WordsLeft));
-/* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
- //status = SRB_STATUS_DATA_OVERRUN;
- DataOverrun = TRUE;
- } else {
- status = SRB_STATUS_SUCCESS;
- }*/
- if(AtaReq->WordsTransfered >= AtaReq->WordsLeft) {
- AtaReq->WordsLeft = 0;
- } else {
- AtaReq->WordsLeft -= AtaReq->WordsTransfered;
- }
- //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 == ATAPI_IR_COD_Cmd) && (statusByte & IDE_STATUS_DRQ)) {
- if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
- AtapiDmaDBPreSync(HwDeviceExtension, chan, srb);
- }
- // Write the packet.
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
- // Send CDB to device.
- WriteBuffer(chan, (PUSHORT)srb->Cdb,
- LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
- /*0*/ PIO0_TIMING);
- AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
-
- if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: AtapiDmaStart().\n"));
- AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, srb);
- }
-
- goto ReturnEnableIntr;
-
- } else if ((interruptReason == ATAPI_IR_IO_toDev) && (statusByte & IDE_STATUS_DRQ)) {
-
- // Write the data.
- if (atapiDev) {
-
- // Pick up bytes to transfer and convert to words.
- wordCount =
- AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
-
- wordCount |=
- (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
-
- // Covert bytes to words.
- wordCount >>= 1;
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: get W wordCount %#x\n", wordCount));
-
- if (wordCount != AtaReq->WordsLeft) {
- KdPrint2((PRINT_PREFIX
- "AtapiInterrupt: %d words requested; %d words xferred\n",
- AtaReq->WordsLeft,
- wordCount));
- }
-
- // Verify this makes sense.
- if (wordCount > AtaReq->WordsLeft) {
- wordCount = AtaReq->WordsLeft;
- KdPrint2((PRINT_PREFIX
- "AtapiInterrupt: Write underrun\n"));
- DataOverrun = TRUE;
- }
-
- } else {
-
- // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
- if (AtaReq->WordsLeft < wordsThisInterrupt) {
- // Transfer only words requested.
- wordCount = AtaReq->WordsLeft;
- } else {
- // Transfer next block.
- wordCount = wordsThisInterrupt;
- }
- }
-
- if (DmaTransfer &&
- (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
- //ASSERT(AtaReq->WordsLeft == wordCount);
- if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) {
- KdPrint2((PRINT_PREFIX
- "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
- if(AtaReq->WordsLeft > wordCount) {
- AtaReq->WordsLeft -= wordCount;
- AtaReq->WordsTransfered += wordCount;
- AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
- goto ReturnEnableIntr;
- }
- dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
- }
- AtaReq->WordsTransfered = AtaReq->WordsLeft;
- AtaReq->WordsLeft = 0;
- status = SRB_STATUS_SUCCESS;
- chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
- goto CompleteRequest;
- }
-
- // Ensure that this is a write command.
- if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
-
- KdPrint2((PRINT_PREFIX
- "AtapiInterrupt: Write interrupt\n"));
-
- statusByte = WaitOnBusy(chan);
-
- if (/*atapiDev || */ !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/
- || (wordCount & 1)) {
-
- WriteBuffer(chan,
- AtaReq->DataBuffer,
- wordCount,
- UniataGetPioTiming(LunExt));
- } else {
-
- WriteBuffer2(chan,
- (PULONG)(AtaReq->DataBuffer),
- wordCount / 2,
- UniataGetPioTiming(LunExt));
- }
- } else {
-
- KdPrint3((PRINT_PREFIX
- "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
- interruptReason,
- srb));
-
- // Fail this request.
- status = SRB_STATUS_ERROR;
- if(!wordCount && atapiDev && (srb->Cdb[0] != SCSIOP_REQUEST_SENSE)) {
- // some devices feel bad after incorrect commands and may need reset
- KdPrint2((PRINT_PREFIX
- "AtapiInterrupt: Try ATAPI reset\n"));
-
- AtapiDisableInterrupts(deviceExtension, lChannel);
- AtapiSoftReset(chan, DeviceNumber);
- AtapiEnableInterrupts(deviceExtension, lChannel);
- status = SRB_STATUS_BUS_RESET;
- AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
-
-// goto IntrPrepareResetController;
- }
- goto CompleteRequest;
- }
- // Advance data buffer pointer and bytes left.
- AtaReq->DataBuffer += wordCount;
- AtaReq->WordsLeft -= wordCount;
- AtaReq->WordsTransfered += wordCount;
-
- if (atapiDev) {
- AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
- }
-
- goto ReturnEnableIntr;
-
- } else if (interruptReason == ATAPI_IR_IO_toHost && (statusByte & IDE_STATUS_DRQ)) {
-
-continue_read_drq:
-
- if (atapiDev) {
-
- // Pick up bytes to transfer and convert to words.
- wordCount =
- (ULONG)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow) |
- ((ULONG)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8);
-
- // Convert bytes to words.
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: get R byteCount %#x\n", wordCount));
- wordCount >>= 1;
- /*
- When ATAPI 64k PIO read is requested we may have 0xfffe byte
- count reported for 0x10000 bytes in single interrupt.
- It is not allowed to read entire 64k block with DwordIo intead of
- wait for last word.
- */
- if (wordCount != AtaReq->WordsLeft) {
- KdPrint2((PRINT_PREFIX
- "AtapiInterrupt: %d words requested; %d words xferred\n",
- AtaReq->WordsLeft,
- wordCount));
- }
-
- // Verify this makes sense.
- if (wordCount > AtaReq->WordsLeft) {
- wordCount = AtaReq->WordsLeft;
- DataOverrun = TRUE;
- }
-
- } else {
-
- // Check if words left is at least 256.
- if (AtaReq->WordsLeft < wordsThisInterrupt) {
- // Transfer only words requested.
- wordCount = AtaReq->WordsLeft;
- } else {
- // Transfer next block.
- wordCount = wordsThisInterrupt;
- }
- }
-
- if(DmaTransfer &&
- (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
- if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) {
- KdPrint2((PRINT_PREFIX
- "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
- if(AtaReq->WordsLeft > wordCount) {
- AtaReq->WordsLeft -= wordCount;
- AtaReq->WordsTransfered += wordCount;
- AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
- goto ReturnEnableIntr;
- }
- dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
- }
- //ASSERT(AtaReq->WordsLeft == wordCount);
- AtaReq->WordsTransfered = AtaReq->WordsLeft;
- AtaReq->WordsLeft = 0;
- status = SRB_STATUS_SUCCESS;
- chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
- goto CompleteRequest;
- }
- // Ensure that this is a read command.
- if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
-
-/* KdPrint2((
- "AtapiInterrupt: Read interrupt\n"));*/
-
- statusByte = WaitOnBusy(chan);
-
- if(wordCount&1 && atapiDev && (g_opt_VirtualMachine == VM_BOCHS)) {
- KdPrint2((PRINT_PREFIX
- "IdeIntr: unaligned ATAPI %#x Words\n", wordCount));
- } else
- if(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) {
- KdPrint2((PRINT_PREFIX
- "IdeIntr: pre-Read %#x Dwords\n", wordCount/2));
-
- ReadBuffer2(chan,
- (PULONG)(AtaReq->DataBuffer),
- wordCount / 2,
- UniataGetPioTiming(LunExt));
- // Advance data buffer pointer and bytes left.
- AtaReq->DataBuffer += wordCount & ~1;
- AtaReq->WordsLeft -= wordCount & ~1;
- AtaReq->WordsTransfered += wordCount & ~1;
- wordCount &= 1;
- }
- if (wordCount) {
- KdPrint2((PRINT_PREFIX
- "IdeIntr: Read %#x words\n", wordCount));
-
- ReadBuffer(chan,
- AtaReq->DataBuffer,
- wordCount,
- UniataGetPioTiming(LunExt));
- }
-
- KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)-1) ));
- //KdDump(AtaReq->DataBuffer, wordCount*2);
- if(srb && atapiDev && srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
- KdDump(AtaReq->DataBuffer, wordCount*2);
- }
-
- GetBaseStatus(chan, statusByte);
- KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte));
-
- 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 {
-
- KdPrint3((PRINT_PREFIX
- "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
- interruptReason,
- srb));
-
- // Fail this request.
- status = SRB_STATUS_ERROR;
- goto CompleteRequest;
- }
-//continue_atapi_pio_read:
- // Advance data buffer pointer and bytes left.
- AtaReq->DataBuffer += wordCount;
- AtaReq->WordsLeft -= wordCount;
- AtaReq->WordsTransfered += wordCount;
-
- // Check for read command complete.
- if (AtaReq->WordsLeft == 0) {
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
- if (atapiDev) {
-
- if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM) {
-
- // Work around to make many atapi devices return correct sector size
- // of 2048. Also certain devices will have sector count == 0x00, check
- // for that also.
- if (srb->Cdb[0] == SCSIOP_READ_CAPACITY) {
-
- AtaReq->DataBuffer -= AtaReq->WordsTransfered;
- if (AtaReq->DataBuffer[0] == 0x00) {
- *((ULONG *) &(AtaReq->DataBuffer[0])) = 0xFFFFFF7F;
- }
-
- *((ULONG *) &(AtaReq->DataBuffer[2])) = 0x00080000;
- AtaReq->DataBuffer += AtaReq->WordsTransfered;
- }
-#ifndef UNIATA_INIT_CHANGERS
- else
- if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
-
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
- // Bingo!!
- AtapiHwInitializeChanger (HwDeviceExtension,
- srb,
- (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer);
- LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
- KdPrint2((PRINT_PREFIX " set DFLAGS_CHANGER_INITED\n"));
- }
-#endif // UNIATA_INIT_CHANGERS
- }
- GetStatus(chan, statusByte);
- if(!(statusByte & IDE_STATUS_BUSY)) {
- // Assume command is completed if BUSY is cleared
- // and all data read
- // Optionally, we may receive COMPLETE interrupt later and
- // treat it as unexpected
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete ? status %x\n", statusByte));
-
- status = SRB_STATUS_SUCCESS;
- goto CompleteRequest;
- }
-
- } else {
-
- /*
- // Completion for IDE drives.
- if (AtaReq->WordsLeft) {
- status = SRB_STATUS_DATA_OVERRUN;
- } else {
- status = SRB_STATUS_SUCCESS;
- }
-
- goto CompleteRequest;
- */
- status = SRB_STATUS_SUCCESS;
- goto CompleteRequest;
-
- }
- } else {
- if (atapiDev) {
- AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
- GetStatus(chan, statusByte);
- if(!(statusByte & IDE_STATUS_BUSY)) {
- // Assume command is completed if BUSY is cleared
- // even if NOT all data read
- // Optionally, we may receive COMPLETE interrupt later and
- // treat it as unexpected
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete + underrun ? status %x\n", statusByte));
-
- status = SRB_STATUS_SUCCESS;
- goto CompleteRequest;
- }
- } else {
- if(!atapiDev && !DataOverrun && (srb->SrbFlags & SRB_FLAGS_DATA_IN) &&
- ((statusByte & ~IDE_STATUS_INDEX) == (IDE_STATUS_IDLE | IDE_STATUS_DRQ))) {
- KdPrint2((PRINT_PREFIX " HDD read data ready \n"));
- goto continue_read_drq;
- }
- }
- }
-
- goto ReturnEnableIntr;
-
- } else if (interruptReason == (ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd) && !(statusByte & IDE_STATUS_DRQ)) {
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n"));
- // Command complete. We exactly know this because of IReason.
-
- if(DmaTransfer) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
- 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;
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: wordCount %#x, WordsTransfered %#x\n", wordCount, AtaReq->WordsTransfered));
-
- }
- //if (AtaReq->WordsLeft) {
- // status = SRB_STATUS_DATA_OVERRUN;
- //} else {
- status = SRB_STATUS_SUCCESS;
- //}
-
-#ifdef UNIATA_DUMP_ATAPI
- if(srb &&
- srb->SrbFlags & SRB_FLAGS_DATA_IN) {
- UCHAR ScsiCommand;
- PCDB Cdb;
- PCHAR CdbData;
- PCHAR ModeSelectData;
- ULONG CdbDataLen;
- PSCSI_REQUEST_BLOCK Srb = srb;
-
- Cdb = (PCDB)(Srb->Cdb);
- ScsiCommand = Cdb->CDB6.OperationCode;
- CdbData = (PCHAR)(Srb->DataBuffer);
- CdbDataLen = Srb->DataTransferLength;
-
- if(CdbDataLen > 0x1000) {
- CdbDataLen = 0x1000;
- }
-
- KdPrint(("--\n"));
- KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
- KdPrint2(("P:T:D=%d:%d:%d\n",
- Srb->PathId,
- Srb->TargetId,
- Srb->Lun));
- KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand));
- KdDump(Cdb, 16);
-
- if(ScsiCommand == SCSIOP_MODE_SENSE) {
- KdPrint(("ModeSense 6\n"));
- PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
- ModeSelectData = CdbData+4;
- KdDump(CdbData, CdbDataLen);
- } else
- if(ScsiCommand == SCSIOP_MODE_SENSE10) {
- KdPrint(("ModeSense 10\n"));
- PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
- ModeSelectData = CdbData+8;
- KdDump(CdbData, CdbDataLen);
- } else {
- if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
- KdPrint(("Read buffer from device:\n"));
- KdDump(CdbData, CdbDataLen);
- }
- }
- KdPrint(("--\n"));
- }
-#endif //UNIATA_DUMP_ATAPI
-
-CompleteRequest:
-
- 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->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
- KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq->WordsLeft));
- status = SRB_STATUS_DATA_OVERRUN;
- }
-
- if (AtaReq->OriginalSrb) {
-
- ULONG srbStatus;
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: OriginalSrb != NULL\n"));
- if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
-#ifdef UNIATA_INIT_CHANGERS
- // We can get here only when UNIATA_INIT_CHANGERS is defined
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
- if (status == SRB_STATUS_SUCCESS) {
- // Bingo!!
- AtapiHwInitializeChanger (HwDeviceExtension,
- srb,
- (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer);
-
- // Get ready to issue the original srb
- srb = AtaReq->Srb = AtaReq->OriginalSrb;
- AtaReq->OriginalSrb = NULL;
-
- } else {
- // failed! Get the sense key and maybe try again
- srb = AtaReq->Srb = BuildRequestSenseSrb (
- HwDeviceExtension,
- AtaReq->OriginalSrb);
- }
-/*
- // do not enable interrupts in DPC, do not waste time, do it now!
- if(UseDpc && chan->DisableIntr) {
- AtapiEnableInterrupts(HwDeviceExtension, c);
- UseDpc = FALSE;
- RestoreUseDpc = TRUE;
- }
-*/
- srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
-
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
-
- if (srbStatus == SRB_STATUS_PENDING) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
- goto ReturnEnableIntr;
- }
-/*
- if(RestoreUseDpc) {
- // restore state on error
- UseDpc = TRUE;
- AtapiDisableInterrupts(HwDeviceExtension, c);
- }
-*/
-#else
- KdPrint((PRINT_PREFIX "AtapiInterrupt: ERROR: internal SCSIOP_MECHANISM_STATUS !!!!\n"));
- ASSERT(FALSE);
-#endif // UNIATA_INIT_CHANGERS
- } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
-
- PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer;
-#ifdef __REACTOS__
- (void)senseData;
-#endif
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI command status %#x\n", status));
- if (status == SRB_STATUS_DATA_OVERRUN) {
- // Check to see if we at least get mininum number of bytes
- if ((srb->DataTransferLength - AtaReq->WordsLeft) >
- (FIELD_OFFSET (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) {
- status = SRB_STATUS_SUCCESS;
- }
- }
-
- if (status == SRB_STATUS_SUCCESS) {
-#ifndef UNIATA_CORE
-#ifdef UNIATA_INIT_CHANGERS
- if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) &&
- FALSE &&
- chan->MechStatusRetryCount) {
-
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: MechStatusRetryCount %#x\n", chan->MechStatusRetryCount));
- // The sense key doesn't say the last request is illegal, so try again
- chan->MechStatusRetryCount--;
- srb = AtaReq->Srb = BuildMechanismStatusSrb (
- HwDeviceExtension,
- AtaReq->OriginalSrb);
- } else
-#endif // UNIATA_INIT_CHANGERS
- {
- // Get ready to issue the original srb
- srb = AtaReq->Srb = AtaReq->OriginalSrb;
- AtaReq->OriginalSrb = NULL;
- }
-#endif //UNIATA_CORE
-/*
- // do not enable interrupts in DPC, do not waste time, do it now!
- if(UseDpc && chan->DisableIntr) {
- AtapiEnableInterrupts(HwDeviceExtension, c);
- UseDpc = FALSE;
- RestoreUseDpc = TRUE;
- }
-*/
- srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
-
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan->ExpectingInterrupt));
-
- if (srbStatus == SRB_STATUS_PENDING) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
- goto ReturnEnableIntr;
- }
-/*
- if(RestoreUseDpc) {
- // restore state on error
- UseDpc = TRUE;
- AtapiDisableInterrupts(HwDeviceExtension, c);
- }
-*/
- }
- }
-
- // If we get here, it means AtapiSendCommand() has failed
- // Can't recover. Pretend the original srb has failed and complete it.
-
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. complete OriginalSrb\n"));
-
- if (AtaReq->OriginalSrb) {
- srb = AtaReq->Srb = AtaReq->OriginalSrb;
- AtaReq->OriginalSrb = NULL;
- }
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan->ExpectingInterrupt));
-
- // fake an error and read no data
- status = SRB_STATUS_ERROR;
- srb->ScsiStatus = 0;
- AtaReq->DataBuffer = (PUSHORT)(srb->DataBuffer);
- AtaReq->WordsLeft = srb->DataTransferLength;
- chan->RDP = FALSE;
-
- } else if (status == SRB_STATUS_ERROR) {
-
- // Map error to specific SRB status and handle request sense.
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. Begin mapping...\n"));
- status = MapError(deviceExtension,
- srb);
-
- chan->RDP = FALSE;
-
- } else if(!DmaTransfer) {
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion\n"));
- // Command complete.
-PIO_wait_busy:
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion, wait BUSY\n"));
- // Wait for busy to drop.
- for (i = 0; i < 5*30; i++) {
- GetBaseStatus(chan, statusByte);
- if (!(statusByte & IDE_STATUS_BUSY)) {
- break;
- }
- if(!InDpc) {
- // goto DPC
- AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY;
- TimerValue = 200;
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (busy)\n"));
-#ifndef UNIATA_CORE
- goto PostToDpc;
-#else //UNIATA_CORE
- AtapiStallExecution(TimerValue);
- goto ServiceInterrupt;
-#endif //UNIATA_CORE
- }
- AtapiStallExecution(100);
- }
-
- if (i == 5*30) {
-
- // reset the controller.
- KdPrint2((PRINT_PREFIX
- "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
- statusByte));
- goto IntrPrepareResetController;
- }
- // Check to see if DRQ is still up.
- if(statusByte & IDE_STATUS_DRQ) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: DRQ...\n"));
- if(srb) {
- if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
- KdPrint2((PRINT_PREFIX "srb %x data in\n", srb));
- } else {
- KdPrint2((PRINT_PREFIX "srb %x data out\n", srb));
- }
- } else {
- KdPrint2((PRINT_PREFIX "srb NULL\n"));
- }
- if(AtaReq) {
- KdPrint2((PRINT_PREFIX "AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq, AtaReq->WordsLeft));
- } else {
- KdPrint2((PRINT_PREFIX "AtaReq NULL\n"));
- }
- if(AtaReq && AtaReq->WordsLeft /*&&
- !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
- KdPrint2((PRINT_PREFIX "DRQ+AtaReq->WordsLeft -> next portion\n"));
- goto continue_PIO;
- }
- }
- //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
- //if ((statusByte & IDE_STATUS_DRQ)) {}
- if((statusByte & IDE_STATUS_DRQ) &&
- (LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED)) ) {
-
-PIO_wait_DRQ:
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO_wait_DRQ\n"));
- for (i = 0; i < 200; i++) {
- GetBaseStatus(chan, statusByte);
- if (!(statusByte & IDE_STATUS_DRQ)) {
- break;
- }
- if(!InDpc) {
- // goto DPC
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq)\n"));
- AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ;
- TimerValue = 100;
-#ifndef UNIATA_CORE
- goto PostToDpc;
-#else //UNIATA_CORE
- AtapiStallExecution(TimerValue);
- goto ServiceInterrupt;
-#endif //UNIATA_CORE
- }
- AtapiStallExecution(100);
- }
-
- if (i == 200) {
- // reset the controller.
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
- statusByte));
- goto IntrPrepareResetController;
- }
- }
- if(atapiDev) {
- KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
- AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)(-1)), srb->DataTransferLength ));
- //KdDump(srb->DataBuffer, srb->DataTransferLength);
- }
- if(!AtapiDmaPioSync(HwDeviceExtension, srb, (PUCHAR)(srb->DataBuffer), srb->DataTransferLength)) {
- KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
- }
- }
-
- // Clear interrupt expecting flag.
- UniataExpectChannelInterrupt(chan, FALSE);
- // clear this flag now, it can be set again in sub-calls
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
-
- // Sanity check that there is a current request.
- if(srb != NULL) {
- // Set status in SRB.
- srb->SrbStatus = (UCHAR)status;
-
- // Check for underflow.
- if(AtaReq->WordsLeft) {
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq->WordsLeft));
- // Subtract out residual words and update if filemark hit,
- // setmark hit , end of data, end of media...
- if (!(LunExt->DeviceFlags & DFLAGS_TAPE_DEVICE)) {
- if (status == SRB_STATUS_DATA_OVERRUN) {
- srb->DataTransferLength -= AtaReq->WordsLeft*2;
- } else {
- srb->DataTransferLength = 0;
- }
- } else {
- srb->DataTransferLength -= AtaReq->WordsLeft*2;
- }
- }
- if(status == SRB_STATUS_SUCCESS) {
- //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
- // // This should be set in UniataAhciEndTransaction() for AHCI
- // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
- //}
- if(!atapiDev &&
- AtaReq->WordsTransfered*2 < AtaReq->TransferLength) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
- AtaReq->WordsTransfered*2, AtaReq->TransferLength));
- AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
- AtaReq->ReqState = REQ_STATE_PREPARE_TO_NEXT;
- goto reenqueue_req;
- } else {
- KdPrint2((PRINT_PREFIX " Transfered %x, full size %x\n",
- AtaReq->WordsTransfered*2, AtaReq->TransferLength));
- }
- }
-
- if (srb->Function != SRB_FUNCTION_IO_CONTROL) {
-
-CompleteRDP:
- // Indicate command complete.
- if (!(chan->RDP)) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete\n"));
-IntrCompleteReq:
-
- if (status == SRB_STATUS_SUCCESS &&
- srb->SenseInfoBuffer &&
- srb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
-
- PSENSE_DATA senseBuffer = (PSENSE_DATA)srb->SenseInfoBuffer;
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: set AutoSense\n"));
- senseBuffer->ErrorCode = 0;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = 0;
- senseBuffer->AdditionalSenseCode = 0;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
-
- srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- }
- AtapiDmaDBSync(chan, srb);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove srb %#x, status %x\n", srb, status));
- UniataRemoveRequest(chan, srb);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete, srb %#x\n", srb));
- ScsiPortNotification(RequestComplete,
- deviceExtension,
- srb);
- }
- } else {
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n"));
-
- if (status != SRB_STATUS_SUCCESS) {
- error = AtapiReadPort1(chan, IDX_IO1_i_Error);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error));
- }
-
- if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
-
- 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;
- }
-
- } else {
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: No SRB!\n"));
- }
-
- if (chan->RDP) {
- // Check DSC
- for (i = 0; i < 5; i++) {
- GetBaseStatus(chan, statusByte);
- if(!(statusByte & IDE_STATUS_BUSY)) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: RDP + cleared BUSY\n"));
- chan->RDP = FALSE;
- goto CompleteRDP;
- } else
- if (statusByte & IDE_STATUS_DSC) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: Clear RDP\n"));
- chan->RDP = FALSE;
- goto CompleteRDP;
- }
- AtapiStallExecution(50);
- }
- }
- // RDP can be cleared since previous check
- if (chan->RDP) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestTimerCall 2000\n"));
-
- TimerValue = 2000;
-#ifndef UNIATA_CORE
- goto CallTimerDpc;
-#else //UNIATA_CORE
- AtapiStallExecution(TimerValue);
- goto ServiceInterrupt;
-#endif //UNIATA_CORE
- }
-
-// ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-enqueue_next_req:
- // Get next request
- srb = UniataGetCurRequest(chan);
-
-reenqueue_req:
-
-#ifndef UNIATA_CORE
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: NextRequest, srb=%#x\n",srb));
- if(!srb) {
- ScsiPortNotification(NextRequest,
- deviceExtension,
- NULL);
- } else {
- ScsiPortNotification(NextLuRequest,
- deviceExtension,
- PathId,
- TargetId,
- Lun);
- // in simplex mode next command must NOT be sent here
- if(!deviceExtension->simplexOnly) {
- AtapiStartIo__(HwDeviceExtension, srb, FALSE);
- }
- }
- // Try to get SRB fron any non-empty queue (later)
- if(deviceExtension->simplexOnly) {
- NoStartIo = FALSE;
- }
-#endif //UNIATA_CORE
-
- goto ReturnEnableIntr;
-
- } else {
-
- // Unexpected int. Catch it
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
- interruptReason,
- statusByte));
-
- if(g_opt_VirtualMachine == VM_QEMU) {
- if(interruptReason == ATAPI_IR_IO_toDev && !(statusByte & IDE_STATUS_DRQ) && !DmaTransfer) {
- statusByte = WaitForDrq(chan);
- if(statusByte & IDE_STATUS_DRQ) {
- goto continue_PIO;
- }
- }
- }
-
- 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:
-
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: ReturnEnableIntr\n",srb));
- //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
- deviceExtension->ExpectingInterrupt = TRUE;
- if(UseDpc) {
- if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
-#ifdef UNIATA_USE_XXableInterrupts
- //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
- chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
- // must be called on DISPATCH_LEVEL
- ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
- AtapiEnableInterrupts__);
-#else
- AtapiEnableInterrupts(HwDeviceExtension, c);
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- // Will raise IRQL to DIRQL
-#ifndef UNIATA_CORE
- AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
- AtapiEnableInterrupts__,
- 1);
-#endif // UNIATA_CORE
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
-#endif // UNIATA_USE_XXableInterrupts
- }
- }
-
- InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
- // in simplex mode next command must be sent here if
- // DPC is not used
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc, NoStartIo));
-
-#ifndef UNIATA_CORE
- if(!UseDpc && /*deviceExtension->simplexOnly &&*/ !NoStartIo) {
- chan = UniataGetNextChannel(chan);
- if(chan) {
- srb = UniataGetCurRequest(chan);
- } else {
- srb = NULL;
- }
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: run srb %x\n", srb));
- if(srb) {
- AtapiStartIo__(HwDeviceExtension, srb, FALSE);
- }
- }
-#endif //UNIATA_CORE
- return TRUE;
-
-} // end AtapiInterrupt__()
-
-#ifndef UNIATA_CORE
-
-/*++
-
-Routine Description:
-
- This routine handles SMART enable, disable, read attributes and threshold commands.
-
-Arguments:
-
- HwDeviceExtension - HBA miniport driver's adapter data storage
- Srb - IO request packet
-
-Return Value:
-
- SRB status
-
---*/
-ULONG
-NTAPI
-IdeSendSmartCommand(
- IN PVOID HwDeviceExtension,
- 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); 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;
- ULONG DeviceNumber;
-
- if (regs->bCommandReg != SMART_CMD) {
- KdPrint2((PRINT_PREFIX
- "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
- return SRB_STATUS_INVALID_REQUEST;
- }
-
- c = targetId / deviceExtension->NumberLuns;
- DeviceNumber = targetId % deviceExtension->NumberLuns;
- KdPrint2((PRINT_PREFIX " c %d, dev %d\n", c, DeviceNumber));
-
- chan = &(deviceExtension->chan[c]);
-
- chan->SmartCommand = regs->bFeaturesReg;
-
- // Determine which of the commands to carry out.
- 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);
-
- if (statusByte & IDE_STATUS_BUSY) {
- KdPrint2((PRINT_PREFIX
- "IdeSendSmartCommand: Returning BUSY status\n"));
- return SRB_STATUS_BUSY;
- }
-
- // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
- RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1);
-
- // Set data buffer pointer and words left.
- AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
- AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2;
-
- statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
- regs->bCommandReg,
- (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
- 0,
- regs->bSectorNumberReg,
- regs->bSectorCountReg,
- regs->bFeaturesReg,
- ATA_IMMEDIATE);
-
- if(!(statusByte & IDE_STATUS_ERROR)) {
- // Wait for interrupt.
- return SRB_STATUS_PENDING;
- }
- return SRB_STATUS_ERROR;
-
- case ENABLE_SMART:
- case DISABLE_SMART:
- case RETURN_SMART_STATUS:
- case ENABLE_DISABLE_AUTOSAVE:
- case EXECUTE_OFFLINE_DIAGS:
- case SAVE_ATTRIBUTE_VALUES:
- case AUTO_OFFLINE:
-
- statusByte = WaitOnBusy(chan);
-
- if (statusByte & IDE_STATUS_BUSY) {
- KdPrint2((PRINT_PREFIX
- "IdeSendSmartCommand: Returning BUSY status\n"));
- return SRB_STATUS_BUSY;
- }
-
- // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
- RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) - 1);
-
- // Set data buffer pointer and indicate no data transfer.
- AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
- AtaReq->WordsLeft = 0;
-
- statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
- regs->bCommandReg,
- (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
- 0,
- regs->bSectorNumberReg,
- regs->bSectorCountReg,
- regs->bFeaturesReg,
- ATA_IMMEDIATE);
-
- if(!(statusByte & IDE_STATUS_ERROR)) {
- // Wait for interrupt.
- UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
- return SRB_STATUS_PENDING;
- }
- return SRB_STATUS_ERROR;
- } // end switch(regs->bFeaturesReg)
-
- return SRB_STATUS_INVALID_REQUEST;
-
-} // end IdeSendSmartCommand()
-
-#endif //UNIATA_CORE
-
-ULONGLONG
-NTAPI
-UniAtaCalculateLBARegs(
- PHW_LU_EXTENSION LunExt,
- ULONGLONG startingSector,
- PULONG max_bcount
- )
-{
- UCHAR drvSelect,sectorNumber;
- USHORT cylinder;
- ULONG tmp;
-
- if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
- (*max_bcount) = 0;
- if(LunExt->LimitedTransferMode >= ATA_DMA) {
- if(LunExt->DeviceExtension) {
- (*max_bcount) = LunExt->DeviceExtension->MaximumDmaTransferLength / DEV_BSIZE;
- }
- }
- return startingSector;
- }
- tmp = LunExt->IdentifyData.SectorsPerTrack *
- LunExt->IdentifyData.NumberOfHeads;
- if(!tmp) {
- KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: 0-sized\n"));
- cylinder = 0;
- drvSelect = 0;
- sectorNumber = 1;
- (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack;
- } else {
- cylinder = (USHORT)(startingSector / tmp);
- drvSelect = (UCHAR)((startingSector % tmp) / LunExt->IdentifyData.SectorsPerTrack);
- sectorNumber = (UCHAR)(startingSector % LunExt->IdentifyData.SectorsPerTrack) + 1;
- (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack - sectorNumber + 1;
- KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
- cylinder, drvSelect, sectorNumber, (*max_bcount)));
- }
-
- return (ULONG)(sectorNumber&0xff) | (((ULONG)cylinder&0xffff)<<8) | (((ULONG)drvSelect&0xf)<<24);
-} // end UniAtaCalculateLBARegs()
-
-ULONGLONG
-NTAPI
-UniAtaCalculateLBARegsBack(
- PHW_LU_EXTENSION LunExt,
- ULONGLONG lba
- )
-{
- ULONG drvSelect,sectorNumber;
- ULONG cylinder;
- ULONG tmp;
-
- if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
- return lba;
- }
- tmp = LunExt->IdentifyData.SectorsPerTrack *
- LunExt->IdentifyData.NumberOfHeads;
-
- cylinder = (USHORT)((lba >> 8) & 0xffff);
- drvSelect = (UCHAR)((lba >> 24) & 0xf);
- sectorNumber = (UCHAR)(lba & 0xff);
-
- lba = sectorNumber-1 +
- (drvSelect*LunExt->IdentifyData.SectorsPerTrack) +
- (cylinder*tmp);
-
- return lba;
-} // end UniAtaCalculateLBARegsBack()
-
-
-/*++
-
-Routine Description:
-
- This routine handles IDE read and writes.
-
-Arguments:
-
- HwDeviceExtension - HBA miniport driver's adapter data storage
- Srb - IO request packet
-
-Return Value:
-
- SRB status
-
---*/
-ULONG
-NTAPI
-IdeReadWrite(
- IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb,
- IN ULONG CmdAction
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- UCHAR lChannel = GET_CHANNEL(Srb);
- PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
- PHW_LU_EXTENSION LunExt;
- PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
- //ULONG ldev = GET_LDEV(Srb);
- UCHAR DeviceNumber = GET_CDEV(Srb);;
- ULONGLONG startingSector=0;
- ULONG max_bcount = 0;
- ULONG wordCount = 0;
- UCHAR statusByte,statusByte2;
- UCHAR cmd;
- ULONGLONG lba;
- BOOLEAN use_dma = FALSE;
- ULONG fis_size;
-
- AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
- LunExt = chan->lun[DeviceNumber];
-
- if((CmdAction & CMD_ACTION_PREPARE) &&
- (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
-
- if(LunExt->opt_ReadOnly &&
- (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) {
- if(LunExt->opt_ReadOnly == 1) {
- KdPrint2((PRINT_PREFIX "Abort WRITE (Soft R/O)\n"));
- return SRB_STATUS_ERROR;
- } else {
- KdPrint2((PRINT_PREFIX "Ignore WRITE (Soft R/O)\n"));
- return SRB_STATUS_SUCCESS;
- }
- }
-
- // Set data buffer pointer and words left.
- AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
-
- if(AtaReq->WordsTransfered) {
- AtaReq->DataBuffer = ((PUSHORT)(Srb->DataBuffer)) + AtaReq->WordsTransfered;
- 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 %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
- startingSector,
- AtaReq->TransferLength/2,
- AtaReq->WordsTransfered,
- AtaReq->bcount));
- } else {
- AtaReq->DataBuffer = (PUSHORT)(Srb->DataBuffer);
- AtaReq->TransferLength = Srb->DataTransferLength;
- // Set up 1st block.
- 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));
- }
- lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
-
- if(max_bcount) {
- AtaReq->bcount = min(AtaReq->bcount, max_bcount);
- }
- AtaReq->WordsLeft = min(AtaReq->TransferLength - AtaReq->WordsTransfered*2,
- AtaReq->bcount * DEV_BSIZE) / 2;
-
- KdPrint2((PRINT_PREFIX "IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
- startingSector,
- AtaReq->WordsLeft,
- AtaReq->bcount));
-
- AtaReq->lba = lba;
- if(LunExt->errRetry &&
- lba == LunExt->errLastLba &&
- /* AtaReq->bcount && */ // errRetry can be set only for non-zero bcount
- AtaReq->bcount == LunExt->errBCount) {
- KdPrint3((PRINT_PREFIX "IdeReadWrite: Retry after BUS_RESET %d @%#I64x (%#x)\n",
- LunExt->errRetry, LunExt->errLastLba, LunExt->errBCount));
- if(AtaReq->retry < MAX_RETRIES) {
- AtaReq->retry = LunExt->errRetry;
- AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
- }
- LunExt->errRetry = 0;
- }
-
- // assume best case here
- // we cannot reinit Dma until previous request is completed
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- UniataAhciSetupCmdPtr(AtaReq);
- if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
- (PUCHAR)(AtaReq->DataBuffer),
- AtaReq->bcount * DEV_BSIZE)) {
- KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !DMA\n"));
- return SRB_STATUS_ERROR;
- }
- } else
- if ((LunExt->LimitedTransferMode >= ATA_DMA)) {
- use_dma = TRUE;
- // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
- if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
- (PUCHAR)(AtaReq->DataBuffer),
- AtaReq->bcount * DEV_BSIZE)) {
- use_dma = FALSE;
- }
- }
-
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint2((PRINT_PREFIX "IdeReadWrite: setup AHCI FIS\n"));
- RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
-
- fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
- &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
- (AtaReq->Flags & REQ_FLAG_READ) ? IDE_COMMAND_READ_DMA : IDE_COMMAND_WRITE_DMA,
- lba,
- (USHORT)(AtaReq->bcount),
- 0
- /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
- );
-
- if(!fis_size) {
- KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !FIS\n"));
- return SRB_STATUS_ERROR;
- }
-
- AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0, (AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE, fis_size, DeviceNumber);
- KdPrint2((PRINT_PREFIX "IdeReadWrite ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
- }
-
- AtaReq->ReqState = REQ_STATE_READY_TO_TRANSFER;
-
- } else { // exec_only
- KdPrint2((PRINT_PREFIX "IdeReadWrite (ExecOnly): \n"));
- lba = AtaReq->lba;
-
- if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
- use_dma = TRUE;
- }
- }
- if(!(CmdAction & CMD_ACTION_EXEC)) {
-
- return SRB_STATUS_PENDING;
- }
-
- // if this is queued request, reinit DMA and check
- // if DMA mode is still available
- AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
- if (/*EnableDma &&*/
- (LunExt->TransferMode >= ATA_DMA)) {
- use_dma = TRUE;
- } else {
- AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
- use_dma = FALSE;
- }
-
- // Check if write request.
- if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
-
- // Prepare read command.
- if(use_dma) {
- cmd = IDE_COMMAND_READ_DMA;
- } else
- if(LunExt->MaximumBlockXfer) {
- cmd = IDE_COMMAND_READ_MULTIPLE;
- } else {
- cmd = IDE_COMMAND_READ;
- }
- } else {
-
- // Prepare write command.
- if (use_dma) {
- wordCount = AtaReq->bcount*DEV_BSIZE/2;
- cmd = IDE_COMMAND_WRITE_DMA;
- } else
- if (LunExt->MaximumBlockXfer) {
- wordCount = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
-
- if (AtaReq->WordsLeft < wordCount) {
- // Transfer only words requested.
- wordCount = AtaReq->WordsLeft;
- }
- cmd = IDE_COMMAND_WRITE_MULTIPLE;
-
- } else {
- wordCount = DEV_BSIZE/2;
- cmd = IDE_COMMAND_WRITE;
- }
- }
-
- // Send IO command.
- KdPrint2((PRINT_PREFIX "IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba, ((Srb->DataTransferLength + 0x1FF) / 0x200),
- ((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE)));
- if(use_dma) {
- chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
- } else {
- chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
- }
-
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- // AHCI doesn't distinguish DMA and PIO
- //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
- UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
- UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- return SRB_STATUS_PENDING;
- }
-
- if ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) ||
- use_dma) {
- if(use_dma) {
- AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb);
- if(g_opt_BochsDmaReadWorkaround &&
- (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
- KdPrint2((PRINT_PREFIX "CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
- AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
- }
- }
- statusByte2 = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
- cmd, lba,
- (USHORT)(AtaReq->bcount),
-// (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
- 0, ATA_IMMEDIATE);
-/* if(statusByte2 != IDE_STATUS_WRONG) {
- GetStatus(chan, statusByte2);
- }*/
- if(statusByte2 & IDE_STATUS_ERROR) {
- // Unfortunately, we cannot handle errors in such a way in real life (except known bad blocks).
- // Because some devices doesn't reset ERR from previous command immediately after getting new one.
- // On the other hand we cannot wait here because of possible timeout condition
- statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
- KdPrint2((PRINT_PREFIX "IdeReadWrite: status %#x, error %#x\n", statusByte2, statusByte));
- return SRB_STATUS_ERROR;
- }
- if(use_dma) {
- if(!g_opt_BochsDmaReadWorkaround ||
- !(Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
- //GetStatus(chan, statusByte2);
- AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
- }
- }
- return SRB_STATUS_PENDING;
- }
-
- statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
- cmd, lba,
- (USHORT)(AtaReq->bcount),
-// (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
- 0, ATA_WAIT_INTR);
-
- if (!(statusByte & IDE_STATUS_DRQ) ||
- statusByte == IDE_STATUS_WRONG) {
-
- if(statusByte == IDE_STATUS_WRONG) {
- KdPrint2((PRINT_PREFIX
- "IdeReadWrite: error sending command (%#x)\n",
- statusByte));
- } else {
- KdPrint2((PRINT_PREFIX
- "IdeReadWrite: DRQ never asserted (%#x)\n",
- statusByte));
- }
-
- AtaReq->WordsLeft = 0;
-
- // Clear interrupt expecting flag.
- UniataExpectChannelInterrupt(chan, FALSE);
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
-
- // Clear current SRB.
- UniataRemoveRequest(chan, Srb);
-
- return (statusByte == IDE_STATUS_WRONG) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT;
- }
-
- UniataExpectChannelInterrupt(chan, TRUE);
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
-
- // Write next DEV_BSIZE/2*N words.
- if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) || (wordCount & 1)) {
- KdPrint2((PRINT_PREFIX
- "IdeReadWrite: Write %#x words\n", wordCount));
-
- WriteBuffer(chan,
- AtaReq->DataBuffer,
- wordCount,
- UniataGetPioTiming(LunExt));
-
- } else {
-
- KdPrint2((PRINT_PREFIX
- "IdeReadWrite: Write %#x Dwords\n", wordCount/2));
-
- WriteBuffer2(chan,
- (PULONG)(AtaReq->DataBuffer),
- wordCount / 2,
- UniataGetPioTiming(LunExt));
- }
-
- // Adjust buffer address and words left count.
- AtaReq->WordsLeft -= wordCount;
- AtaReq->DataBuffer += wordCount;
- AtaReq->WordsTransfered += wordCount;
-
- // Wait for interrupt.
- return SRB_STATUS_PENDING;
-
-} // end IdeReadWrite()
-
-#ifndef UNIATA_CORE
-
-/*++
-
-Routine Description:
- This routine handles IDE Verify.
-
-Arguments:
- HwDeviceExtension - HBA miniport driver's adapter data storage
- Srb - IO request packet
- `
-Return Value:
- SRB status
-
---*/
-ULONG
-NTAPI
-IdeVerify(
- IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- UCHAR lChannel = GET_CHANNEL(Srb);
- PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
- PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
- PHW_LU_EXTENSION LunExt;
- //ULONG ldev = GET_LDEV(Srb);
- ULONG DeviceNumber = GET_CDEV(Srb);
- UCHAR statusByte;
- ULONGLONG startingSector=0;
- ULONG max_bcount;
- ULONGLONG sectors;
- ULONGLONG endSector;
- ULONG sectorCount=0;
- ULONGLONG lba;
-
- LunExt = chan->lun[DeviceNumber];
- // Drive has these number sectors.
- if(!(sectors = (ULONG)(LunExt->NumOfSectors))) {
- sectors = LunExt->IdentifyData.SectorsPerTrack *
- LunExt->IdentifyData.NumberOfHeads *
- LunExt->IdentifyData.NumberOfCylinders;
- }
-
- KdPrint2((PRINT_PREFIX
- "IdeVerify: Total sectors %#x\n",
- sectors));
-
- // Get starting sector number from CDB.
- 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 %#I64x. Number of blocks %#x\n",
- startingSector,
- sectorCount));
-
- endSector = startingSector + sectorCount;
-
- KdPrint2((PRINT_PREFIX
- "IdeVerify: Ending sector %#I64x\n",
- endSector));
-
- if (endSector > sectors) {
-
- // Too big, round down.
- KdPrint2((PRINT_PREFIX
- "IdeVerify: Truncating request to %#x blocks\n",
- sectors - startingSector - 1));
-
- sectorCount = (ULONG)(sectors - startingSector - 1);
-
- } else {
-
- // Set up sector count register. Round up to next block.
- if (sectorCount > 0xFF) {
- sectorCount = (USHORT)0xFF;
- }
- }
-
- // Set data buffer pointer and words left.
- AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
- AtaReq->WordsLeft = Srb->DataTransferLength / 2;
-
- // Indicate expecting an interrupt.
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
-
- lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
-
- statusByte = AtaCommand48(deviceExtension, LunExt->Lun, GET_CHANNEL(Srb),
- IDE_COMMAND_VERIFY, lba,
- (USHORT)sectorCount,
- 0, ATA_IMMEDIATE);
-
- if(!(statusByte & IDE_STATUS_ERROR)) {
- // Wait for interrupt.
- return SRB_STATUS_PENDING;
- }
- return SRB_STATUS_ERROR;
-
-} // end IdeVerify()
-
-#endif //UNIATA_CORE
-
-/*++
-
-Routine Description:
- Send ATAPI packet command to device.
-
-Arguments:
- HwDeviceExtension - HBA miniport driver's adapter data storage
- Srb - IO request packet
-
-Return Value:
-
---*/
-ULONG
-NTAPI
-AtapiSendCommand(
- IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb,
- IN ULONG CmdAction
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- UCHAR lChannel = GET_CHANNEL(Srb);
- PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
- PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
- PHW_LU_EXTENSION LunExt;
- //ULONG ldev = GET_LDEV(Srb);
- ULONG DeviceNumber = GET_CDEV(Srb);
- ULONG flags;
- UCHAR statusByte,statusByte0,byteCountLow,byteCountHigh;
- UCHAR interruptReason;
- BOOLEAN use_dma = FALSE;
- BOOLEAN dma_reinited = FALSE;
- BOOLEAN retried = FALSE;
- ULONG fis_size, i;
- UCHAR FeatureReg=0;
-
- LunExt = chan->lun[DeviceNumber];
-
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: req state %#x, Action %x\n", AtaReq->ReqState, CmdAction));
- if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
- AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
-
-
-#ifdef UNIATA_DUMP_ATAPI
- if(CmdAction & CMD_ACTION_PREPARE) {
- UCHAR ScsiCommand;
- PCDB Cdb;
- PCHAR CdbData;
- PCHAR ModeSelectData;
- ULONG CdbDataLen;
-
- Cdb = (PCDB)(Srb->Cdb);
- ScsiCommand = Cdb->CDB6.OperationCode;
- CdbData = (PCHAR)(Srb->DataBuffer);
- CdbDataLen = Srb->DataTransferLength;
-
- if(CdbDataLen > 0x1000) {
- CdbDataLen = 0x1000;
- }
-
- KdPrint(("--\n"));
- KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
- KdPrint2(("P:T:D=%d:%d:%d\n",
- Srb->PathId,
- Srb->TargetId,
- Srb->Lun));
- KdPrint(("SCSI Command %2.2x\n", ScsiCommand));
- KdDump(Cdb, 16);
-
- if(ScsiCommand == SCSIOP_WRITE_CD) {
- KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
- Cdb->WRITE_CD.LBA[0],
- Cdb->WRITE_CD.LBA[1],
- Cdb->WRITE_CD.LBA[2],
- Cdb->WRITE_CD.LBA[3]
- ));
- } else
- if(ScsiCommand == SCSIOP_WRITE12) {
- KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
- Cdb->CDB12READWRITE.LBA[0],
- Cdb->CDB12READWRITE.LBA[1],
- Cdb->CDB12READWRITE.LBA[2],
- 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;
- ModeSelectData = CdbData+4;
- KdDump(CdbData, CdbDataLen);
- } else
- if(ScsiCommand == SCSIOP_MODE_SELECT10) {
- KdPrint(("ModeSelect 10\n"));
- PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
- ModeSelectData = CdbData+8;
- KdDump(CdbData, CdbDataLen);
- } else {
- if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
- KdPrint(("Send buffer to device:\n"));
- KdDump(CdbData, CdbDataLen);
- }
- }
- KdPrint(("--\n"));
- }
-#endif //UNIATA_DUMP_ATAPI
-
-
- 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:
- case SCSIOP_READ:
- case SCSIOP_WRITE:
- case SCSIOP_READ12:
- case SCSIOP_WRITE12:
- case SCSIOP_READ16:
- case SCSIOP_WRITE16:
- // all right
- break;
- case SCSIOP_READ_CD:
- case SCSIOP_READ_CD_MSF:
- if(deviceExtension->opt_AtapiDmaRawRead) {
- // all right
- break;
- }
- /* FALL THROUGH */
- default:
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY\n"));
- return SRB_STATUS_BUSY;
- }
- //
-#ifdef UNIATA_INIT_CHANGERS
- if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
- !AtaReq->OriginalSrb) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
- return SRB_STATUS_BUSY;
- }
-#endif // UNIATA_INIT_CHANGERS
- }
-
-#ifndef UNIATA_CORE
- // standard atapi.sys claims:
-
- // We need to know how many platters our atapi cd-rom device might have.
- // Before anyone tries to send a srb to our target for the first time,
- // we must "secretly" send down a separate mechanism status srb in order to
- // initialize our device extension changer data. That's how we know how
- // many platters our target has.
-
- // BUT!
- // some devices freeze (sometimes) forever on this command
- // Let CD-ROM driver send this command itself, if it find it necessary
- // We shall just parse output (if any)
-
-#ifdef UNIATA_INIT_CHANGERS
- if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
- !AtaReq->OriginalSrb) {
-
- ULONG srbStatus;
-
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n"));
- // Set this flag now. If the device hangs on the mech. status
- // command, we will not have the chance to set it.
- LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
-
- chan->MechStatusRetryCount = 3;
- AtaReq->OriginalSrb = Srb;
- AtaReq->Srb = BuildMechanismStatusSrb (
- HwDeviceExtension,
- Srb);
-
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n"));
- srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
- if (srbStatus == SRB_STATUS_PENDING) {
- 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;
- // fall out
- }
- }
-#endif // UNIATA_INIT_CHANGERS
-#endif //UNIATA_CORE
-
- if((CmdAction & CMD_ACTION_PREPARE) &&
- (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;
- AtaReq->TransferLength = Srb->DataTransferLength;
- AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
- // reset this to force PRD init. May be already setup by recursive SRB
- AtaReq->dma_entries = 0;
-
- // 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:
-
- MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
- goto GetLba;
-
- case SCSIOP_READ:
- case SCSIOP_WRITE:
-
- 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 ||
- 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(g_opt_AtapiNoDma) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: CTRFLAGS_DMA_BEFORE_R => no dma\n"));
- use_dma = FALSE;
- } else
- 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
- if(AtaReq->TransferLength && !(AtaReq->TransferLength & 0x0f)) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: try DMA setup\n"));
- // try use DMA if TransferLength is 16-byte aligned
- switch(Srb->Cdb[0]) {
- case SCSIOP_WRITE:
- case SCSIOP_WRITE12:
- case SCSIOP_WRITE16:
- case SCSIOP_SEND:
- if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO)
- break;
- /* FALLTHROUGH */
- case SCSIOP_RECEIVE:
- case SCSIOP_READ:
- case SCSIOP_READ12:
- case SCSIOP_READ16:
-
- if(deviceExtension->opt_AtapiDmaReadWrite) {
-call_dma_setup:
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
- use_dma = TRUE;
- } else
- if(AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
- (PUCHAR)(AtaReq->DataBuffer),
- Srb->DataTransferLength
- /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
- )) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
- use_dma = TRUE;
- }
- }
- break;
- case SCSIOP_READ_CD:
- case SCSIOP_READ_CD_MSF:
- if(deviceExtension->opt_AtapiDmaRawRead)
- goto call_dma_setup;
- break;
- default:
-
- if(deviceExtension->opt_AtapiDmaControlCmd) {
- if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
- // read operation
- use_dma = TRUE;
- } else {
- // write operation
- if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) {
- KdPrint2((PRINT_PREFIX "dma RO\n"));
- use_dma = FALSE;
- } else {
- use_dma = TRUE;
- }
- }
- }
- break;
- }
- // try setup DMA
-setup_dma:
- if(use_dma) {
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
- //use_dma = TRUE;
- } else
- if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
- (PUCHAR)(AtaReq->DataBuffer),
- Srb->DataTransferLength)) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma\n"));
- use_dma = FALSE;
- } else {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
- }
- }
- } else {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero/unaligned transfer %x, no DMA setup\n", AtaReq->TransferLength));
- }
-
-
- 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)) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: no AHCI dma!\n"));
- return SRB_STATUS_ERROR;
- }
- if(!use_dma) {
- AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
- } else {
- FeatureReg |= ATA_F_DMA;
- if(LunExt->IdentifyData.AtapiDMA.DMADirRequired) {
- if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
- KdPrint2((PRINT_PREFIX "Set DMADir.\n"));
- FeatureReg |= ATA_F_DMAREAD;
- }
- }
- }
-
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
- // 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),
- FeatureReg/* feature */
- );
-
- if(!fis_size) {
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
- return SRB_STATUS_ERROR;
- }
-
- AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0,
- ((Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) ? ATA_AHCI_CMD_WRITE : 0) |
- (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH),
- fis_size, DeviceNumber);
-
- KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
- }
-
- } else {
- if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
- // if this is queued request, reinit DMA and check
- // if DMA mode is still available
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() (1)\n"));
- AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
- if (/*EnableDma &&*/
- (LunExt->TransferMode >= ATA_DMA)) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (2)\n"));
- use_dma = TRUE;
- } else {
- AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma (2)\n"));
- use_dma = FALSE;
- }
- dma_reinited = TRUE;
- }
- }
-
- if(!(CmdAction & CMD_ACTION_EXEC)) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
- return SRB_STATUS_PENDING;
- }
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma, Srb->Cdb[0]));
- if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
- KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
- }
-
- 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;
- AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
- } if(AtaReq->TransferLength) {
- if(!dma_reinited) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()\n"));
- AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
- if (/*EnableDma &&*/
- (LunExt->TransferMode >= ATA_DMA)) {
- use_dma = TRUE;
- } else {
- AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
- use_dma = FALSE;
- }
- }
- } else {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer\n"));
- use_dma = FALSE;
- AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
- if(!deviceExtension->opt_AtapiDmaZeroTransfer && !(deviceExtension->HwFlags & UNIATA_SATA)) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
- AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
- }
- }
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
- if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
- KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
- }
-
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_EXEC\n"));
-
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
- &(Srb->Cdb), Srb->Cdb[0], Srb->TargetId, Srb->Lun));
-
- // Make sure command is to ATAPI device.
- flags = LunExt->DeviceFlags;
- if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
- if((Srb->Lun) > (LunExt->DiscsPresent - 1)) {
-
- // Indicate no device found at this address.
- AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
- return SRB_STATUS_SELECTION_TIMEOUT;
- }
- } else if(Srb->Lun > 0) {
- AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
- return SRB_STATUS_SELECTION_TIMEOUT;
- }
-
- if(!(flags & DFLAGS_ATAPI_DEVICE)) {
- AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
- return SRB_STATUS_SELECTION_TIMEOUT;
- }
-retry:
- // Select device 0 or 1. Or more for PM
- SelectDrive(chan, DeviceNumber);
-
- // Verify that controller is ready for next command.
- GetStatus(chan, statusByte);
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte));
-
- if(statusByte == IDE_STATUS_WRONG) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: bad status 0xff on entry\n"));
- goto make_reset;
- }
- if(statusByte & IDE_STATUS_BUSY) {
- if(statusByte & IDE_STATUS_DSC) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte));
- } else {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte));
- // We have to make reset here, since we are expecting device to be available
- //return SRB_STATUS_BUSY; // this cause queue freeze
- goto make_reset;
- }
- }
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- ULONG CI;
- // Check if command list is free
- CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
- if(CI) {
- // controller is busy, however we expect it to be free
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI));
- goto make_reset;
- }
- }
- if(statusByte & IDE_STATUS_ERROR) {
- if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
-
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on entry: (%#x)\n", statusByte));
- // Read the error reg. to clear it and fail this request.
- AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
- return MapError(deviceExtension, Srb);
- } else {
- KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n", statusByte));
- }
- }
- // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
- // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
- if((!(statusByte & IDE_STATUS_DSC)) &&
- (flags & (DFLAGS_TAPE_DEVICE | DFLAGS_ATAPI_DEVICE)) && chan->RDP) {
-
- AtapiStallExecution(200);
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte));
- AtaReq->ReqState = REQ_STATE_QUEUED;
- return SRB_STATUS_PENDING;
- }
-
- if(IS_RDP(Srb->Cdb[0])) {
- chan->RDP = TRUE;
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb->Cdb[0]));
- } else {
- chan->RDP = FALSE;
- }
- if(statusByte & IDE_STATUS_DRQ) {
-
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
- statusByte));
- // 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) {
- AtapiReadPort2(chan, IDX_IO1_i_Data);
- } else {
- break;
- }
- }
-*/
- if (statusByte & IDE_STATUS_DRQ) {
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted. Status (%#x)\n", statusByte));
-make_reset:
- AtapiDisableInterrupts(deviceExtension, lChannel);
-
- AtapiSoftReset(chan, DeviceNumber);
-
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: Issued soft reset to Atapi device. \n"));
- // Re-initialize Atapi device.
- CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), DeviceNumber, TRUE);
-/*
- IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
- IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
-*/
- // Inform the port driver that the bus has been reset.
- ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
- // Clean up device extension fields that AtapiStartIo won't.
- UniataExpectChannelInterrupt(chan, FALSE);
- chan->RDP = FALSE;
- InterlockedExchange(&(deviceExtension->chan[GET_CHANNEL(Srb)].CheckIntr),
- CHECK_INTR_IDLE);
-
- AtapiEnableInterrupts(deviceExtension, lChannel);
-/*
- AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
- return SRB_STATUS_BUS_RESET;
-*/
- if(!retried) {
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: retry after reset.\n"));
- retried = TRUE;
- goto retry;
- }
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: selection timeout.\n"));
- AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
- return SRB_STATUS_SELECTION_TIMEOUT;
- }
- }
-
- if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
- // As the cdrom driver sets the LUN field in the cdb, it must be removed.
- Srb->Cdb[1] &= ~0xE0;
- if((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) {
- // Torisan changer. TUR's are overloaded to be platter switches.
- Srb->Cdb[7] = Srb->Lun;
- }
- }
-
- // SETUP DMA !!!!!
-
- if(use_dma) {
- chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
- } else {
- chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
- }
-
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n"));
- //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
- UniataExpectChannelInterrupt(chan, TRUE);
- UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
- return SRB_STATUS_PENDING;
- }
-
- statusByte = WaitOnBusy(chan);
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n",
- statusByte));
-
- if(use_dma) {
- FeatureReg |= ATA_F_DMA;
- if(LunExt->IdentifyData.AtapiDMA.DMADirRequired) {
- if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
- FeatureReg |= ATA_F_DMAREAD;
- }
- }
- }
-
- // Write transfer byte count to registers.
- if (Srb->DataTransferLength >= 0x10000) {
- byteCountLow = byteCountHigh = 0xFF;
- } else {
- byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
- byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
- }
-
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: F:%#x, CntHL:%#x:%#x.\n", FeatureReg, byteCountHigh, byteCountLow));
-
- if (flags & DFLAGS_INT_DRQ) {
- // This device interrupts when ready to receive the packet.
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
- statusByte));
-
- UniataExpectChannelInterrupt(chan, TRUE);
- AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR;
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- // inform driver that packet command must be sent in ISR
- flags |= DFLAGS_INT_DRQ;
- } else {
- // This device quickly sets DRQ when ready to receive the packet.
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
- statusByte));
-
- UniataExpectChannelInterrupt(chan, TRUE);
- AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR;
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
-
- if(g_opt_AtapiSendDisableIntr) {
- AtapiDisableInterrupts(deviceExtension, lChannel);
- }
- // remember status. Later we may check if error appeared after cmd packet
- statusByte0 = statusByte;
- }
-
- // must be already selected, experimental for ROS BUG-9119
- //AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
- AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Feature /*IDX_IO1_o_Feature*/, FeatureReg);
- //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused0, 0); // experimental for ROS BUG-9119
- //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused1, 0); // experimental for ROS BUG-9119
- AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow);
- AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh);
- // Write ATAPI packet command.
- AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Command /*IDX_IO1_o_Command*/, IDE_COMMAND_ATAPI_PACKET);
-
- if (flags & DFLAGS_INT_DRQ) {
- // Wait for interrupt and send PACKET there
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
- return SRB_STATUS_PENDING;
- }
-
- WaitOnBusy(chan);
-/*
- // Wait for DRQ.
- statusByte = WaitForDrq(chan);
-
- // Need to read status register and clear interrupt (if any)
- GetBaseStatus(chan, statusByte);
-
- if (!(statusByte & IDE_STATUS_DRQ)) {
- if(g_opt_AtapiSendDisableIntr) {
- AtapiEnableInterrupts(deviceExtension, lChannel);
- }
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte));
- AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
- return SRB_STATUS_ERROR;
- }
-*/
- GetStatus(chan, statusByte);
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
-
- //statusByte = WaitOnBaseBusy(chan);
-
- // Indicate expecting an interrupt and wait for it.
- UniataExpectChannelInterrupt(chan, TRUE);
-
- for(i=0; i<5000; i++) {
- if(g_opt_AtapiSendDisableIntr) {
- GetStatus(chan, statusByte);
- } else {
- GetBaseStatus(chan, statusByte);
- }
- interruptReason = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason);
- //KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i));
- if(((interruptReason & ATAPI_IR_COD) == ATAPI_IR_COD_Cmd) &&
- (((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) == IDE_STATUS_DRQ))) {
- break;
- }
- AtapiStallExecution(g_opt_WaitDrqDelay*2);
-#ifdef _DEBUG
-// KdPrint3((PRINT_PREFIX "AtapiSendCommand: wait CoD, status (%#x)\n", interruptReason));
-#endif // _DEBUG
- }
- if(((interruptReason & ATAPI_IR_COD) != ATAPI_IR_COD_Cmd) ||
- (((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) != IDE_STATUS_DRQ)) ) {
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: no CoD raised, abort cmd\n"));
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i));
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
- if(g_opt_AtapiSendDisableIntr) {
- AtapiEnableInterrupts(deviceExtension, lChannel);
- }
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ+CoD never asserted\n"));
- 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);
- }
- goto make_reset;
-// AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
-// return SRB_STATUS_ERROR;
- } else {
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: ready for packet, status %#x, i=%d\n", interruptReason, i));
- }
- // clear interrupt
- GetBaseStatus(chan, statusByte);
-
- if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
- AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb);
- }
- if(g_opt_AtapiSendDisableIntr) {
- AtapiEnableInterrupts(deviceExtension, lChannel);
- }
-
- // Send CDB to device.
- WriteBuffer(chan,
- (PUSHORT)Srb->Cdb,
- LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
- /*0*/ PIO0_TIMING);
-
- 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) {
-
- 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_DRQ) {
- // Some devices require this. If error condition is not checked in such a way,
- // device may not operate correctly and would be treated as failed
- // (and finally invisible for OS)
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ 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);
- }
-
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
-
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt));
-
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
- return SRB_STATUS_PENDING;
-
-} // end AtapiSendCommand()
-
-
-#ifndef UNIATA_CORE
-
-/*++
-
-Routine Description:
- Program ATA registers for IDE disk transfer.
-
-Arguments:
- HwDeviceExtension - ATAPI driver storage.
- Srb - System request block.
-
-Return Value:
- SRB status (pending if all goes well).
-
---*/
-
-#ifdef _DEBUG
-ULONG check_point = 0;
-#define SetCheckPoint(cp) { check_point = (cp) ; }
-#else
-#define SetCheckPoint(cp)
-#endif
-
-ULONG
-NTAPI
-IdeSendCommand(
- IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb,
- IN ULONG CmdAction
- )
-{
- SetCheckPoint(1);
- KdPrint2((PRINT_PREFIX "** Ide: Command: entryway\n"));
- SetCheckPoint(2);
-
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- SetCheckPoint(3);
- UCHAR lChannel;
- PHW_CHANNEL chan;
- PCDB cdb;
- PHW_LU_EXTENSION LunExt;
-
- SetCheckPoint(4);
-
- UCHAR statusByte,errorByte;
- 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;
-
- SetCheckPoint(0x20);
- KdPrint2((PRINT_PREFIX "** Ide: Command:\n\n"));
-/* __asm {
- mov eax,ebp
- mov __ebp__, eax
- }*/
- /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
- __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
- KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
- (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
- KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
- Srb));
- KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
- Srb->SrbExtension));
- KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
- Srb->TargetId));*/
-
- SetCheckPoint(0x30);
- AtaReq = (PATA_REQ)(Srb->SrbExtension);
-
- KdPrint2((PRINT_PREFIX "** Ide: Command &AtaReq %#x\n",
- &AtaReq));
- KdPrint2((PRINT_PREFIX "** Ide: Command AtaReq %#x\n",
- AtaReq));
- KdPrint2((PRINT_PREFIX "** --- **\n"));
-
- lChannel = GET_CHANNEL(Srb);
- chan = &(deviceExtension->chan[lChannel]);
- //ldev = GET_LDEV(Srb);
- DeviceNumber = GET_CDEV(Srb);
- LunExt = chan->lun[DeviceNumber];
-
- SetCheckPoint(0x40);
- 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;
- }
- }
-
- SetCheckPoint(0x100 | Srb->Cdb[0]);
- switch (Srb->Cdb[0]) {
- case SCSIOP_INQUIRY:
-
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
- Srb->PathId, Srb->Lun, Srb->TargetId));
- // Filter out wrong TIDs.
- if ((Srb->Lun != 0) ||
- (Srb->PathId >= deviceExtension->NumberChannels) ||
- (Srb->TargetId >= deviceExtension->NumberLuns)) {
-
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
- // Indicate no device found at this address.
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
-
- } else {
-
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
- PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
- PIDENTIFY_DATA2 identifyData = &(LunExt->IdentifyData);
-
- if (!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
-
- if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
- // Indicate no device found at this address.
-#ifndef NAVO_TEST
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
- }
- } else {
- if(!UniataAnybodyHome(HwDeviceExtension, lChannel, DeviceNumber)) {
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
- // Indicate no device found at this address.
- UniataForgetDevice(chan->lun[DeviceNumber]);
-#endif //NAVO_TEST
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
- }
- }
-
- // Zero INQUIRY data structure.
- RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
-
- // Standard IDE interface only supports disks.
- inquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
-
- // Set the removable bit, if applicable.
- if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
- KdPrint2((PRINT_PREFIX
- "RemovableMedia\n"));
- inquiryData->RemovableMedia = 1;
- }
- // Set the Relative Addressing (LBA) bit, if applicable.
- if (LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
- inquiryData->RelativeAddressing = 1;
- KdPrint2((PRINT_PREFIX
- "RelativeAddressing\n"));
- }
- // Set the CommandQueue bit
- inquiryData->CommandQueue = 1;
-
- // Fill in vendor identification fields.
- for (i = 0; i < 24; i += 2) {
- MOV_DW_SWP(inquiryData->DeviceIdentificationString[i], ((PUCHAR)identifyData->ModelNumber)[i]);
- }
-/*
- // Initialize unused portion of product id.
- for (i = 0; i < 4; i++) {
- inquiryData->ProductId[12+i] = ' ';
- }
-*/
- // Move firmware revision from IDENTIFY data to
- // product revision in INQUIRY data.
- for (i = 0; i < 4; i += 2) {
- MOV_DW_SWP(inquiryData->ProductRevisionLevel[i], ((PUCHAR)identifyData->FirmwareRevision)[i]);
- }
-
- status = SRB_STATUS_SUCCESS;
- }
-
- 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));
-
- 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;
-#ifdef __REACTOS__
- modeData->PageLength = sizeof(MODE_POWER_CONDITION_PAGE)-sizeof(MODE_PARAMETER_HEADER);
-#else
- modeData->PageLength = sizeof(MODE_PAGE_POWER_CONDITION)-sizeof(MODE_PARAMETER_HEADER);
-#endif
- 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);
- if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) {
- status = SRB_STATUS_DATA_OVERRUN;
- } else {
- RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE));
- modeData->PageCode = MODE_PAGE_CACHING;
- modeData->PageLength = sizeof(MODE_CACHING_PAGE)-sizeof(MODE_PARAMETER_HEADER);
- modeData->ReadDisableCache = (LunExt->DeviceFlags & DFLAGS_RCACHE_ENABLED) ? 0 : 1;
- modeData->WriteCacheEnable = (LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) ? 1 : 0;
- Srb->DataTransferLength = sizeof(MODE_CACHING_PAGE);
- status = SRB_STATUS_SUCCESS;
- }
- } 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);
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
-
- if (!(statusByte & IDE_STATUS_ERROR)) {
-
- // no error occured return success, media is not protected
- UniataExpectChannelInterrupt(chan, FALSE);
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- status = SRB_STATUS_SUCCESS;
-
- } else {
-
- // error occured, handle it locally, clear interrupt
- errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
-
- GetBaseStatus(chan, statusByte);
- UniataExpectChannelInterrupt(chan, FALSE);
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- status = SRB_STATUS_SUCCESS;
-
- if (errorByte & IDE_ERROR_DATA_ERROR) {
-
- //media is write-protected, set bit in mode sense buffer
- modeData = (PMODE_PARAMETER_HEADER)Srb->DataBuffer;
-
- Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER);
- modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
- }
- }
- status = SRB_STATUS_SUCCESS;
- } else {
- status = SRB_STATUS_INVALID_REQUEST;
- }
- break;
-
- case SCSIOP_TEST_UNIT_READY:
-
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
- Srb->PathId, Srb->Lun, Srb->TargetId));
- if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
-
- // Select device 0 or 1.
- //SelectDrive(chan, DeviceNumber);
- //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
- // Wait for busy. If media has not changed, return success
- //statusByte = WaitOnBusy(chan);
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
-
- if (!(statusByte & IDE_STATUS_ERROR)){
- UniataExpectChannelInterrupt(chan, FALSE);
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- status = SRB_STATUS_SUCCESS;
- } else {
- errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
- if (errorByte == IDE_ERROR_DATA_ERROR){
-
- // Special case: If current media is write-protected,
- // the 0xDA command will always fail since the write-protect bit
- // is sticky,so we can ignore this error
- GetBaseStatus(chan, statusByte);
- UniataExpectChannelInterrupt(chan, FALSE);
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- status = SRB_STATUS_SUCCESS;
-
- } else {
-
- // Request sense buffer to be build
- UniataExpectChannelInterrupt(chan, TRUE);
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- status = SRB_STATUS_PENDING;
- }
- }
- } else {
- status = SRB_STATUS_SUCCESS;
- }
-
- break;
-
- case SCSIOP_READ_CAPACITY:
-
- 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_CAPACITY_DATA));
- MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i );
-
- // Calculate last sector.
- if(!(i = (ULONG)LunExt->NumOfSectors)) {
- i = 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_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress, i );
-
- KdPrint2((PRINT_PREFIX
- "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
- Srb->TargetId,
- LunExt->IdentifyData.SectorsPerTrack,
- LunExt->IdentifyData.NumberOfHeads,
- LunExt->IdentifyData.NumberOfCylinders));
-
-
- 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;
- }
- lba--;
- MOV_QD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->LogicalBlockAddress, lba );
-
- 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",
- Srb->PathId, Srb->Lun, Srb->TargetId));
- status = IdeVerify(HwDeviceExtension,Srb);
-
- break;
-
- 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 ||
- Srb->Cdb[0] == SCSIOP_WRITE12 ||
- Srb->Cdb[0] == SCSIOP_WRITE16) ? REQ_FLAG_WRITE : REQ_FLAG_READ;
- status = IdeReadWrite(HwDeviceExtension,
- Srb, CmdAction);
- break;
-
- case SCSIOP_START_STOP_UNIT:
-
- KdPrint2((PRINT_PREFIX
- "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
-
- command = 0;
-
- 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);
- 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;
- }
- break;
-
- case SCSIOP_MEDIUM_REMOVAL:
-
- cdb = (PCDB)Srb->Cdb;
-
- if(LunExt->IdentifyData.Removable) {
- statusByte = WaitOnBaseBusy(chan);
-
- //SelectDrive(chan, DeviceNumber);
- if (cdb->MEDIA_REMOVAL.Prevent != FALSE) {
- //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_LOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
- } else {
- //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_UNLOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
- }
- status = SRB_STATUS_SUCCESS;
- } else {
- status = SRB_STATUS_INVALID_REQUEST;
- }
- break;
-
-#if 0
- // Note: I don't implement this, because NTFS driver too often issues this command
- // It causes awful performance degrade. However, if somebody wants, I will implement
- // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
- case SCSIOP_FLUSH_BUFFER:
- case SCSIOP_SYNCHRONIZE_CACHE:
-
- SelectDrive(chan, DeviceNumber);
- AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_FLUSH_CACHE);
- status = SRB_STATUS_SUCCESS;
-// status = SRB_STATUS_PENDING;
- statusByte = WaitOnBusy(chan);
- break;
-#endif
-
- case SCSIOP_REQUEST_SENSE:
- // this function makes sense buffers to report the results
- // of the original GET_MEDIA_STATUS command
-
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
- Srb->PathId, Srb->Lun, Srb->TargetId));
- if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
- status = IdeBuildSenseBuffer(HwDeviceExtension,Srb);
- break;
- }
- status = SRB_STATUS_INVALID_REQUEST;
- break;
-
- // ATA_PASSTHORUGH
- case SCSIOP_ATA_PASSTHROUGH:
- {
- PIDEREGS_EX regs;
- BOOLEAN use_dma = FALSE;
- ULONG to_lim;
-
- regs = (PIDEREGS_EX) &(Srb->Cdb[2]);
-
- 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_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[DeviceNumber]->LimitedTransferMode >= ATA_DMA)) {
- use_dma = TRUE;
- // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
- 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);
- AtapiStallExecution(10);
- if(use_dma) {
- AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb);
- }
-
- if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command
- AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg);
- AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg);
- AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg);
- AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg);
- AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
- } else {
- AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesRegH);
- AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg);
- AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountRegH);
- AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg);
- AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberRegH);
- AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg);
- AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowRegH);
- AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg);
- AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighRegH);
- AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
- }
- AtapiWritePort1(chan, IDX_IO1_o_Command, regs->bCommandReg);
-
- if(use_dma) {
- GetBaseStatus(chan, statusByte);
- if(statusByte & IDE_STATUS_ERROR) {
- goto passthrough_err;
- }
- AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
- }
-
- ScsiPortStallExecution(1); // wait for busy to be set
-
- 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(statusByte & IDE_STATUS_ERROR) {
- break;
- }
- if(!(statusByte & IDE_STATUS_BUSY)) {
- break;
- }
- }
- if(i >= to_lim) {
- //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
- //}
- AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_NONE);
- goto passthrough_err;
- }
-
- if(use_dma) {
- AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel);
- }
- AtapiDmaDone(deviceExtension, DeviceNumber, lChannel, NULL);
- GetBaseStatus(chan, statusByte);
-
- if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
- AtapiSuckPort2(chan);
-passthrough_err:
- if (Srb->SenseInfoBuffer) {
-
- PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
- senseBuffer->AdditionalSenseCode = 0;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
-
- Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
- Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
- }
- status = SRB_STATUS_ERROR;
- } else {
-
- if(!use_dma) {
- if (statusByte & IDE_STATUS_DRQ) {
- if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
- ReadBuffer(chan,
- (PUSHORT) Srb->DataBuffer,
- Srb->DataTransferLength / 2,
- 0);
- } else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
- WriteBuffer(chan,
- (PUSHORT) Srb->DataBuffer,
- Srb->DataTransferLength / 2,
- 0);
- }
- }
- }
- status = SRB_STATUS_SUCCESS;
- }
-passthrough_done:;
- AtapiEnableInterrupts(deviceExtension, lChannel);
-
- } else { // read task register
-
- BOOLEAN use48;
- regs = (PIDEREGS_EX) Srb->DataBuffer;
-
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
- Srb->PathId, Srb->Lun, Srb->TargetId));
-
- if((Srb->DataTransferLength >= sizeof(IDEREGS_EX)) &&
- (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND)) {
- use48 = TRUE;
- } else
- if(Srb->DataTransferLength >= sizeof(IDEREGS)) {
- use48 = FALSE;
- } else {
- KdPrint2((PRINT_PREFIX " buffer too small \n"));
- status = SRB_STATUS_DATA_OVERRUN;
- break;
- }
- 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;
- }
-
- default:
-default_abort:
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: Unsupported command %#x\n",
- Srb->Cdb[0]));
-
- status = SRB_STATUS_INVALID_REQUEST;
-
- } // end switch
-
- if(status == SRB_STATUS_PENDING) {
- KdPrint2((PRINT_PREFIX "IdeSendCommand: SRB_STATUS_PENDING\n"));
- if(CmdAction & CMD_ACTION_EXEC) {
- KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
- AtaReq->ReqState = REQ_STATE_EXPECTING_INTR;
- }
- } else {
- KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
- AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
- }
-
- return status;
-
-} // end IdeSendCommand()
-
-
-/*++
-
-Routine Description:
- Enables disables media status notification
-
-Arguments:
- HwDeviceExtension - ATAPI driver storage.
-
---*/
-VOID
-NTAPI
-IdeMediaStatus(
- BOOLEAN EnableMSN,
- IN PVOID HwDeviceExtension,
- IN ULONG lChannel,
- IN ULONG DeviceNumber
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PHW_CHANNEL chan;
- UCHAR statusByte,errorByte;
-
- chan = &(deviceExtension->chan[lChannel]);
- SelectDrive(chan, DeviceNumber);
-
- if (EnableMSN != FALSE){
-
- // If supported enable Media Status Notification support
- if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE)) {
-
- // enable
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
- IDE_COMMAND_SET_FEATURES, 0, 0, 0,
- 0, ATA_C_F_ENAB_MEDIASTAT, ATA_WAIT_BASE_READY);
-
- if (statusByte & IDE_STATUS_ERROR) {
- // Read the error register.
- errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
-
- KdPrint2((PRINT_PREFIX
- "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
- statusByte,
- errorByte));
- } else {
- chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_MEDIA_STATUS_ENABLED;
- KdPrint2((PRINT_PREFIX "IdeMediaStatus: Media Status Notification Supported\n"));
- chan->ReturningMediaStatus = 0;
-
- }
-
- }
- } else { // end if EnableMSN != FALSE
-
- // disable if previously enabled
- if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)) {
-
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
- IDE_COMMAND_SET_FEATURES, 0, 0, 0,
- 0, ATA_C_F_DIS_MEDIASTAT, ATA_WAIT_BASE_READY);
- chan->lun[DeviceNumber]->DeviceFlags &= ~DFLAGS_MEDIA_STATUS_ENABLED;
- }
-
-
- }
-
-
-} // end IdeMediaStatus()
-
-
-/*++
-
-Routine Description:
-
- Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
- command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
-Arguments:
-
- HwDeviceExtension - ATAPI driver storage.
- Srb - System request block.
-
-Return Value:
-
- SRB status (ALWAYS SUCCESS).
-
---*/
-ULONG
-NTAPI
-IdeBuildSenseBuffer(
- IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
-// ULONG status;
- PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->DataBuffer;
- UCHAR ReturningMediaStatus = deviceExtension->chan[GET_CHANNEL(Srb)].ReturningMediaStatus;
-
- if (senseBuffer){
-
- if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE) {
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
- senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
- } else if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE_REQ) {
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
- senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
- } else if(ReturningMediaStatus & IDE_ERROR_END_OF_MEDIA) {
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_NOT_READY;
- senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
- } else if(ReturningMediaStatus & IDE_ERROR_DATA_ERROR) {
-
- senseBuffer->ErrorCode = 0x70;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_DATA_PROTECT;
- senseBuffer->AdditionalSenseCode = 0;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
- }
- return SRB_STATUS_SUCCESS;
- }
- return SRB_STATUS_ERROR;
-
-}// End of IdeBuildSenseBuffer
-
-VOID
-NTAPI
-UniataUserDeviceReset(
- PHW_DEVICE_EXTENSION deviceExtension,
- PHW_LU_EXTENSION LunExt,
- ULONG lChannel
- )
-{
- ULONG i;
- AtapiDisableInterrupts(deviceExtension, lChannel);
- if ((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
- (LunExt->PowerState != StartStop_Power_Sleep)) {
- KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n"));
- AtapiSoftReset(&(deviceExtension->chan[lChannel]), LunExt->Lun);
- } else {
- KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
- AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_NONE);
- for(i=0; i<deviceExtension->NumberLuns; i++) {
- deviceExtension->chan[lChannel].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
- }
- }
- LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
- AtapiEnableInterrupts(deviceExtension, lChannel);
- return;
-} // end UniataUserDeviceReset()
-
-BOOLEAN
-NTAPI
-UniataNeedQueueing(
- PHW_DEVICE_EXTENSION deviceExtension,
- PHW_CHANNEL chan,
- BOOLEAN TopLevel
- )
-{
- BOOLEAN PostReq = FALSE;
- if(TopLevel) {
- KdPrint3((PRINT_PREFIX "UniataNeedQueueing: TopLevel, qd=%x\n", chan->queue_depth));
- if(chan->queue_depth > 0) {
-#if 0
- if(atapiDev &&
- ((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY)/* ||
- (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
- KdPrint2((PRINT_PREFIX "spec: SCSIOP_TEST_UNIT_READY\n"));
- //PostReq = FALSE;
- status = SRB_STATUS_BUSY;
- goto skip_exec;
- } else {
- PostReq = TRUE;
- }
-#else
- PostReq = TRUE;
-#endif
- } else
- if(deviceExtension->simplexOnly && deviceExtension->queue_depth > 0) {
- PostReq = TRUE;
- }
- } else {
- KdPrint3((PRINT_PREFIX "UniataNeedQueueing: qd=%x\n", chan->queue_depth));
- }
- return PostReq;
-} // end UniataNeedQueueing()
-
-/*++
-
-Routine Description:
-
- This routine is called from the SCSI port driver synchronized
- with the kernel to start an IO request.
- ->HwStartIo
-
-Arguments:
-
- HwDeviceExtension - HBA miniport driver's adapter data storage
- Srb - IO request packet
-
-Return Value:
-
- TRUE
-
---*/
-BOOLEAN
-NTAPI
-AtapiStartIo(
- IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb
- )
-{
- return AtapiStartIo__(HwDeviceExtension, Srb, TRUE);
-} // end AtapiStartIo()
-
-BOOLEAN
-NTAPI
-AtapiStartIo__(
- IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb,
- IN BOOLEAN TopLevel
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- UCHAR lChannel;
- PHW_CHANNEL chan;
- PHW_LU_EXTENSION LunExt;
- ULONG status;
- //ULONG ldev;
- ULONG DeviceNumber;
- UCHAR PathId;
- UCHAR TargetId;
- UCHAR Lun;
- PATA_REQ AtaReq;
- PSCSI_REQUEST_BLOCK tmpSrb;
- BOOLEAN PostReq = FALSE;
- BOOLEAN atapiDev;
- BOOLEAN commPort = FALSE;
-
- // deviceExtension->Isr2DevObj must always be NULL for non-PCI
- if(deviceExtension->Isr2DevObj && !BMList[deviceExtension->DevIndex].Isr2Enable) {
- KdPrint2((PRINT_PREFIX "Isr2Enable -> 1\n"));
- BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
- }
-// deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
-
-/* KeBugCheckEx(0xc000000e,
- (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
- Srb->Function,
- TopLevel, 0x80000001);
-*/
- if(TopLevel && Srb && Srb->SrbExtension) {
- KdPrint2((PRINT_PREFIX "TopLevel\n"));
- //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
- UniAtaClearAtaReq(Srb->SrbExtension);
- }
-
- 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);
-
- KdPrint2((PRINT_PREFIX
- "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
- Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId));
- KdPrint2((PRINT_PREFIX " DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
-
- if(lChannel == deviceExtension->NumberChannels &&
- !Srb->Lun && !Srb->TargetId &&
- ((Srb->Function == SRB_FUNCTION_IO_CONTROL) ||
- (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Cdb[0] == SCSIOP_INQUIRY))
- ) {
- // This is our virtual device
- KdPrint2((PRINT_PREFIX
- "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
- " INQUIRY\n"));
- // Zero INQUIRY data structure.
- RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
-
- inquiryData->DeviceType = COMMUNICATION_DEVICE;
-
- // Fill in vendor identification fields.
- RtlCopyMemory(&inquiryData->VendorId, &uniata_comm_name, 28);
-
- status = SRB_STATUS_SUCCESS;
- goto complete_req;
- }
- commPort = TRUE;
- /* Pass IOCTL request down */
- } else
- if(lChannel >= deviceExtension->NumberChannels ||
- Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
- Srb->Lun) {
-
- if(lChannel >= deviceExtension->NumberChannels) {
- chan = NULL;
- }
-
-reject_srb:
- //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
- 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;
- //}
- } else
- if((deviceExtension->HwFlags & UNIATA_AHCI) &&
- !UniataAhciChanImplemented(deviceExtension, lChannel)) {
- chan = NULL;
- }
-
- if(!commPort) {
- chan = &(deviceExtension->chan[lChannel]);
- LunExt = chan->lun[DeviceNumber];
- if(!LunExt) {
- goto reject_srb;
- }
- atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
- } else {
- atapiDev = FALSE;
- }
-
-#ifdef _DEBUG
- if(!commPort && !LunExt) {
-#if 0
- PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
- deviceExtension,
- chan, DeviceNumber,
- deviceExtension->NumberChannels);
- PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
- lChannel, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]);
- PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
- Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId);
-#endif //0
-/*
- int i;
- for(i=0; i<1000; i++) {
- AtapiStallExecution(3*1000);
- }
-*/
- goto reject_srb;
- }
-#endif //_DEBUG
-
- // Determine which function.
- switch (Srb->Function) {
-
- case SRB_FUNCTION_EXECUTE_SCSI:
-
- if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
- if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
- // let passthrough go
- } else
- if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
- // let INQUIRY go
- } else {
-
- //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
- KdPrint2((PRINT_PREFIX
- "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
- // Indicate no device found at this address.
- KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
- //}
- }
- } else {
- KdPrint2((PRINT_PREFIX
- " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb, &(Srb->Cdb), Srb->SrbExtension, Srb->Cdb[0]));
- }
-/*
- __try {
- if(Srb->DataTransferLength) {
- UCHAR a;
- a = ((PUCHAR)(Srb->DataBuffer))[0];
- g_foo += a;
- }
- } __except(EXCEPTION_EXECUTE_HANDLER) {
- KdPrint3((PRINT_PREFIX
- "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
- // Indicate no device found at this address.
- KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
- status = SRB_STATUS_ERROR;
- KdPrint2((PRINT_PREFIX " *** Exception...\n"));
- ASSERT(FALSE);
- break;
- }
-*/
- PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
-
- if(PostReq) {
-
- KdPrint3((PRINT_PREFIX "Non-empty queue\n"));
- if (atapiDev &&
- (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
- KdPrint3((PRINT_PREFIX "Try ATAPI prepare\n"));
-
- status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
- } else {
- KdPrint2((PRINT_PREFIX "Try IDE prepare\n"));
- status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
- }
- /*KeBugCheckEx(0xc000000e,
- (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
- Srb->Function,
- status, 0x80000001);*/
- if(status == SRB_STATUS_BUSY)
- status = SRB_STATUS_PENDING;
- // Insert requests AFTER they have been initialized on
- // CMD_ACTION_PREPARE stage
- // we should not check TopLevel here (it is always TRUE)
- //ASSERT(chan->lun[GET_CDEV(Srb)]);
- UniataQueueRequest(chan, Srb);
-
- 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) {
- KdPrint2((PRINT_PREFIX "TopLevel (2), srb %#x\n", Srb));
- AtaReq = (PATA_REQ)(Srb->SrbExtension);
- KdPrint2((PRINT_PREFIX "TopLevel (3), AtaReq %#x\n", AtaReq));
- //ASSERT(!AtaReq->Flags);
- //ASSERT(chan->lun[GET_CDEV(Srb)]);
- UniataQueueRequest(chan, Srb);
-// AtaReq = (PATA_REQ)(Srb->SrbExtension);
- //ASSERT(!AtaReq->Flags);
- AtaReq->ReqState = REQ_STATE_QUEUED;
- //ASSERT(!AtaReq->Flags);
- }
-
-#ifndef NAVO_TEST
- if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
- if(!LunExt) {
- goto reject_srb;
- }
- if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
- if(UniataAnybodyHome(deviceExtension, chan->lChannel, DeviceNumber)) {
- if(!CheckDevice(HwDeviceExtension, chan->lChannel, DeviceNumber, TRUE)) {
- goto reject_srb;
- }
- }
- if(!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
- goto reject_srb;
- }
- } else
- if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
- // allow
- } else {
- goto reject_srb;
- }
- }
-#endif //NAVO_TEST
-
- if(atapiDev &&
- (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 {
- KdPrint2((PRINT_PREFIX "Try IDE send\n"));
-/* {
- ULONG __ebp__ = 0;
- ULONG __esp__ = 0;
-
- KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
- __asm {
- mov eax,ebp
- mov __ebp__, eax
- mov eax,esp
- mov __esp__, eax
- }
- KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
- }*/
- status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
- }
-/* KeBugCheckEx(0xc000000e,
- (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
- Srb->Function,
- status, 0x80000002);*/
-
- }
-//skip_exec:
- TopLevel = FALSE;
-
- break;
-
- case SRB_FUNCTION_ABORT_COMMAND:
-
- tmpSrb = ScsiPortGetSrb(HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun,
- Srb->QueueTag);
- // Verify that SRB to abort is still outstanding.
- if((tmpSrb != Srb->NextSrb) ||
- !chan->queue_depth) {
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB to abort already completed\n"));
-
- // Complete abort SRB.
- status = SRB_STATUS_ABORT_FAILED;
- break;
- }
-
- AtaReq = (PATA_REQ)(tmpSrb->SrbExtension);
- if(AtaReq->ReqState > REQ_STATE_READY_TO_TRANSFER) {
- if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_CURRENT)) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Abort command failed\n"));
- // Log reset failure.
- KdPrint3((PRINT_PREFIX
- "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
- HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
- ));
- ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
- status = SRB_STATUS_ERROR;
-
- } else {
- status = SRB_STATUS_SUCCESS;
- }
- } else {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove aborted srb %#x\n", tmpSrb));
- if (tmpSrb->SenseInfoBuffer &&
- tmpSrb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
-
- PSENSE_DATA senseBuffer = (PSENSE_DATA)tmpSrb->SenseInfoBuffer;
-
- senseBuffer->ErrorCode = 0;
- senseBuffer->Valid = 1;
- senseBuffer->AdditionalSenseLength = 0xb;
- senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
- senseBuffer->AdditionalSenseCode = 0;
- senseBuffer->AdditionalSenseCodeQualifier = 0;
-
- tmpSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- }
- AtapiDmaDBSync(chan, tmpSrb);
- UniataRemoveRequest(chan, tmpSrb);
- // Indicate command complete.
- ScsiPortNotification(RequestComplete,
- deviceExtension,
- tmpSrb);
- status = SRB_STATUS_SUCCESS;
- }
- break;
-
- // Abort function indicates that a request timed out.
- // Call reset routine. Card will only be reset if
- // status indicates something is wrong.
- // Fall through to reset code.
-
- case SRB_FUNCTION_RESET_DEVICE:
- case SRB_FUNCTION_RESET_LOGICAL_UNIT:
-
- // Reset single device.
- // For now we support only Lun=0
-
- // Note: reset is immediate command, it cannot be queued since it is usually used to
- // revert not-responding device to operational state
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device request received\n"));
- UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
- status = SRB_STATUS_SUCCESS;
- break;
-
- case SRB_FUNCTION_RESET_BUS:
-do_bus_reset:
- // Reset Atapi and SCSI bus.
-
- // Note: reset is immediate command, it cannot be queued since it is usually used to
- // revert not- responding device to operational state
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus request received\n"));
- if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_ALL)) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus failed\n"));
- // Log reset failure.
- KdPrint3((PRINT_PREFIX
- "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
- HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
- ));
- ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
- status = SRB_STATUS_ERROR;
-
- } else {
- status = SRB_STATUS_SUCCESS;
- }
-
- break;
-
- case SRB_FUNCTION_SHUTDOWN:
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown\n"));
- if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - no such device\n"));
- } else
- if(atapiDev) {
- // FLUSH ATAPI device - do nothing
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - ATAPI device\n"));
- } else {
- // FLUSH IDE/ATA device
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - IDE device\n"));
- AtapiDisableInterrupts(deviceExtension, lChannel);
- status = AtaCommand(deviceExtension, DeviceNumber, GET_CHANNEL(Srb),
- IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_IDLE);
- // If supported & allowed, reset write cacheing
- if(LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) {
-
- // Disable write cache
- status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
- IDE_COMMAND_SET_FEATURES, 0, 0, 0,
- 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
- // Check for errors.
- if (status & IDE_STATUS_ERROR) {
- KdPrint2((PRINT_PREFIX
- "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
- DeviceNumber));
- }
- LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
-
- // Re-enable write cache
- status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
- IDE_COMMAND_SET_FEATURES, 0, 0, 0,
- 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
- // Check for errors.
- if (status & IDE_STATUS_ERROR) {
- KdPrint2((PRINT_PREFIX
- "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
- DeviceNumber));
- LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
- } else {
- LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
- }
- }
-
- AtapiEnableInterrupts(deviceExtension, lChannel);
- }
- status = SRB_STATUS_SUCCESS;
-
- break;
-
- case SRB_FUNCTION_FLUSH:
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Flush (do nothing)\n"));
- status = SRB_STATUS_SUCCESS;
- break;
-
- case SRB_FUNCTION_IO_CONTROL: {
-
- ULONG len;
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
-
- len = Srb->DataTransferLength;
-
- 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));
-
- if(len < sizeof(SRB_IO_CONTROL)+sizeof(GETVERSIONINPARAMS)) {
- goto wrong_buffer_size;
- }
-
- 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;
- }
-
- 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()
-
- // 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.
-
- 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 non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
- targetId));
- // Indicate no device found at this address.
- goto reject_srb;
- }
- 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;
-
- 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
- // corresponding to this drive's target id.
- // The bit mask is as follows:
- //
- // -Sec Pri
- // S M S M
- // 3 2 1 0
-
- if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
- deviceNumberMap = 1 << lChannel;
- DeviceNumber = 0;
- } else
- if (deviceExtension->NumberChannels == 1) {
- if (chan->PrimaryAddress) {
- deviceNumberMap = 1 << DeviceNumber;
- } else {
- deviceNumberMap = 4 << DeviceNumber;
- }
- } else {
- deviceNumberMap = 1 << (DeviceNumber+lChannel*2);
- }
-
- versionParameters->bIDEDeviceMap = deviceNumberMap;
-
- status = SRB_STATUS_SUCCESS;
- break;
- }
-
- case IOCTL_SCSI_MINIPORT_IDENTIFY: {
-
- PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
- SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
- // Extract the target.
- KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
-
- switch(cmdInParameters.irDriveRegs.bCommandReg) {
- case ID_CMD:
- if(atapiDev) {
- KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n"));
- goto invalid_request;
- }
- /* FALL THROUGH */
- case ATAPI_ID_CMD:
-
- if(!atapiDev &&
- (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) {
- KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n"));
- goto invalid_request;
- }
-
- len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE);
- // Zero the output buffer
- RtlZeroMemory(cmdOutParameters, len);
-/* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
- ((PUCHAR)cmdOutParameters)[i] = 0;
- }*/
-
- // Build status block.
- cmdOutParameters->cBufferSize = min(IDENTIFY_BUFFER_SIZE, len - sizeof(SENDCMDOUTPARAMS) + 1);
- cmdOutParameters->DriverStatus.bDriverError = 0;
- cmdOutParameters->DriverStatus.bIDEError = 0;
-
- // Extract the identify data from the device extension.
- 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;
- default:
- KdPrint2((PRINT_PREFIX "AtapiStartIo: not supported ID code %x\n",
- cmdInParameters.irDriveRegs.bCommandReg));
- status = SRB_STATUS_INVALID_REQUEST;
- break;
- }
- 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_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:
-*/
- default:
- // *all* IOCTLs here are SMART
- if(commPort) {
- KdPrint2((PRINT_PREFIX
- "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
- }
- if (atapiDev) {
- goto invalid_request;
- }
-
- PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
-
- if(PostReq || TopLevel) {
- UniataQueueRequest(chan, Srb);
- AtaReq = (PATA_REQ)(Srb->SrbExtension);
- AtaReq->ReqState = REQ_STATE_QUEUED;
- }
-
- if(PostReq) {
-
- KdPrint2((PRINT_PREFIX "Non-empty queue (SMART)\n"));
- status = SRB_STATUS_PENDING;
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
- } else {
-
- status = IdeSendSmartCommand(HwDeviceExtension, Srb, targetId);
- }
- break;
-
- // 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)) {
-
- PUNIATA_CTL AtaCtl = (PUNIATA_CTL)(Srb->DataBuffer);
- //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
- ULONG DeviceNumber = AtaCtl->addr.TargetId;
- BOOLEAN bad_ldev;
- ULONG i, pos;
-
- pos = FIELD_OFFSET(UNIATA_CTL, RawData);
- //chan = &(deviceExtension->chan[lChannel]);
- if(len < pos) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
- FIELD_OFFSET(UNIATA_CTL, RawData) ));
- goto wrong_buffer_size;
- }
-
- if(AtaCtl->addr.Lun ||
- AtaCtl->addr.TargetId >= deviceExtension->NumberLuns ||
- AtaCtl->addr.PathId >= deviceExtension->NumberChannels) {
-
- chan = NULL;
- bad_ldev = TRUE;
- LunExt = NULL;
-
- } else {
- bad_ldev = FALSE;
- lChannel = AtaCtl->addr.PathId;
- chan = &(deviceExtension->chan[lChannel]);
- LunExt = chan->lun[DeviceNumber];
- }
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl->hdr.ControlCode, DeviceNumber));
-
- /* check for valid LUN */
- switch (AtaCtl->hdr.ControlCode) {
- case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
- case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE:
- // this would be BUS reset
- if(bad_ldev &&
- (AtaCtl->addr.PathId >= deviceExtension->NumberChannels ||
- AtaCtl->addr.TargetId != 0xff ||
- AtaCtl->addr.Lun != 0
- )) {
- if(AtaCtl->hdr.ControlCode == IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES &&
- DeviceNumber < deviceExtension->NumberLuns) { // AtaCtl->addr.TargetId != 0xff
- lChannel = AtaCtl->addr.PathId;
- chan = &(deviceExtension->chan[lChannel]);
- LunExt = chan->lun[DeviceNumber];
- // OK
- } else {
- goto handle_bad_ldev;
- }
- } else {
- lChannel = AtaCtl->addr.PathId;
- chan = &(deviceExtension->chan[lChannel]);
- }
- break;
- case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE:
- case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
- case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE:
- case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
-// case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
- if(bad_ldev) {
-handle_bad_ldev:
- KdPrint2((PRINT_PREFIX
- "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
- // Indicate no device found at this address.
- goto reject_srb;
- }
- }
-
- /* check if queueing is necessary */
- switch (AtaCtl->hdr.ControlCode) {
- case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
- if(!LunExt->nBadBlocks) {
- break;
- }
- goto uata_ctl_queue;
- case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
- if(len < pos+sizeof(AtaCtl->SetMode)) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
- pos+sizeof(AtaCtl->SetMode) ));
- goto wrong_buffer_size;
- }
- if(!AtaCtl->SetMode.ApplyImmediately) {
- break;
- }
- goto uata_ctl_queue;
- case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
- //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
-uata_ctl_queue:
- KdPrint2((PRINT_PREFIX "put to queue (UNIATA)\n"));
- PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
-
- if(PostReq || TopLevel) {
- UniataQueueRequest(chan, Srb);
- AtaReq = (PATA_REQ)(Srb->SrbExtension);
- AtaReq->ReqState = REQ_STATE_QUEUED;
- }
- if(PostReq) {
- KdPrint2((PRINT_PREFIX "Non-empty queue (UNIATA)\n"));
- status = SRB_STATUS_PENDING;
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
- goto complete_req;
- }
- } // end switch (AtaCtl->hdr.ControlCode)
-
- /* process request */
- switch (AtaCtl->hdr.ControlCode) {
- case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n"));
-
- if(len < pos+sizeof(AtaCtl->FindDelDev)) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
- pos+sizeof(AtaCtl->FindDelDev) ));
- goto wrong_buffer_size;
- }
- if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
- if(AtaCtl->addr.TargetId != 0xff) {
- LunExt->DeviceFlags &= ~DFLAGS_HIDDEN;
- } else {
- }
- }
-
- for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
- AtapiStallExecution(1000 * 1000);
- }
-
- FindDevices(HwDeviceExtension,
- ((AtaCtl->addr.TargetId == 0xff) && (AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE))
- ? UNIATA_FIND_DEV_UNHIDE : 0,
- AtaCtl->addr.PathId);
- status = SRB_STATUS_SUCCESS;
-
- break;
-
- case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: {
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId));
-
- if(len < pos+sizeof(AtaCtl->FindDelDev)) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
- pos+sizeof(AtaCtl->FindDelDev) ));
- goto wrong_buffer_size;
- }
- LunExt->DeviceFlags = 0;
- if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n"));
- //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
- UniataForgetDevice(LunExt);
- }
-
- for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
- AtapiStallExecution(1000 * 1000);
- }
-
- status = SRB_STATUS_SUCCESS;
- break;
- }
- case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: {
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n"));
-
- if(len < pos+sizeof(AtaCtl->SetMode)) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
- pos+sizeof(AtaCtl->SetMode) ));
- goto wrong_buffer_size;
- }
- if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
- LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
- }
- if(AtaCtl->SetMode.MaxMode != IOMODE_NOT_SPECIFIED) {
- LunExt->LimitedTransferMode = (UCHAR)(AtaCtl->SetMode.MaxMode);
- if(LunExt->LimitedTransferMode >
- LunExt->OrigTransferMode) {
- // check for incorrect value
- LunExt->LimitedTransferMode =
- LunExt->OrigTransferMode;
- }
- }
- LunExt->TransferMode = min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode);
-
- LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
- if(AtaCtl->SetMode.ApplyImmediately) {
- AtapiDmaInit__(deviceExtension, LunExt);
- }
-/* LunExt->TransferMode =
- LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
- status = SRB_STATUS_SUCCESS;
- break;
- }
- case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE: {
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Get transfer mode\n"));
-
- if(len < pos+sizeof(AtaCtl->GetMode)) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
- pos+sizeof(AtaCtl->GetMode) ));
- goto wrong_buffer_size;
- }
- AtaCtl->GetMode.OrigMode = LunExt->OrigTransferMode;
- AtaCtl->GetMode.MaxMode = LunExt->LimitedTransferMode;
- AtaCtl->GetMode.CurrentMode = LunExt->TransferMode;
- AtaCtl->GetMode.PhyMode = LunExt->PhyTransferMode;
-
- status = SRB_STATUS_SUCCESS;
- break;
- }
- case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION: {
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n"));
-
- if(len < pos+sizeof(AtaCtl->Version)) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
- pos+sizeof(AtaCtl->Version) ));
- goto wrong_buffer_size;
- }
- AtaCtl->Version.Length = sizeof(GETDRVVERSION);
- AtaCtl->Version.VersionMj = UNIATA_VER_MJ;
- AtaCtl->Version.VersionMn = UNIATA_VER_MN;
- AtaCtl->Version.SubVerMj = UNIATA_VER_SUB_MJ;
- AtaCtl->Version.SubVerMn = UNIATA_VER_SUB_MN;
-
- status = SRB_STATUS_SUCCESS;
- break;
- }
- case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO: {
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n"));
-
- if(len < pos+sizeof(AtaCtl->AdapterInfo)) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
- pos+sizeof(AtaCtl->AdapterInfo) ));
- goto wrong_buffer_size;
- }
- AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO);
-
- AtaCtl->AdapterInfo.DevID = deviceExtension->DevID;
- AtaCtl->AdapterInfo.RevID = deviceExtension->RevID;
- AtaCtl->AdapterInfo.slotNumber = deviceExtension->slotNumber;
- AtaCtl->AdapterInfo.SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
- AtaCtl->AdapterInfo.DevIndex = deviceExtension->DevIndex;
- AtaCtl->AdapterInfo.Channel = deviceExtension->Channel;
- AtaCtl->AdapterInfo.HbaCtrlFlags = deviceExtension->HbaCtrlFlags;
- AtaCtl->AdapterInfo.simplexOnly= deviceExtension->simplexOnly;
- AtaCtl->AdapterInfo.MemIo = FALSE;/*deviceExtension->MemIo;*/
- AtaCtl->AdapterInfo.UnknownDev = deviceExtension->UnknownDev;
- AtaCtl->AdapterInfo.MasterDev = deviceExtension->MasterDev;
- AtaCtl->AdapterInfo.MaxTransferMode = deviceExtension->MaxTransferMode;
- AtaCtl->AdapterInfo.HwFlags = deviceExtension->HwFlags;
- AtaCtl->AdapterInfo.OrigAdapterInterfaceType = deviceExtension->OrigAdapterInterfaceType;
- AtaCtl->AdapterInfo.BusInterruptLevel = deviceExtension->BusInterruptLevel;
- AtaCtl->AdapterInfo.InterruptMode = deviceExtension->InterruptMode;
- AtaCtl->AdapterInfo.BusInterruptVector = deviceExtension->BusInterruptVector;
- AtaCtl->AdapterInfo.NumberChannels = deviceExtension->NumberChannels;
- AtaCtl->AdapterInfo.NumberLuns = (UCHAR)deviceExtension->NumberLuns;
- AtaCtl->AdapterInfo.AdapterInterfaceType = deviceExtension->AdapterInterfaceType;
- if(deviceExtension->FullDevName) {
- strncpy(AtaCtl->AdapterInfo.DeviceName, deviceExtension->FullDevName, 64);
- }
- AtaCtl->AdapterInfo.ChanInfoValid = FALSE;
- AtaCtl->AdapterInfo.LunInfoValid = FALSE;
- AtaCtl->AdapterInfo.ChanHeaderLengthValid = TRUE;
-
- pos += AtaCtl->AdapterInfo.HeaderLength;
-
- // zero tail
- RtlZeroMemory(((PCHAR)AtaCtl)+pos,
- len-pos);
-
- if(len >= pos+AtaCtl->AdapterInfo.NumberChannels*sizeof(CHANINFO)) {
- PCHANINFO ChanInfo = (PCHANINFO)( ((PCHAR)AtaCtl)+pos );
- PHW_CHANNEL cur_chan;
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Fill channel info\n"));
- for(i=0;i<AtaCtl->AdapterInfo.NumberChannels;i++) {
- KdPrint2((PRINT_PREFIX "chan[%d] %x\n", i, cur_chan));
- cur_chan = &(deviceExtension->chan[i]);
- ChanInfo->MaxTransferMode = cur_chan->MaxTransferMode;
- ChanInfo->ChannelCtrlFlags = cur_chan->ChannelCtrlFlags;
- RtlCopyMemory(&(ChanInfo->QueueStat), &(cur_chan->QueueStat), sizeof(ChanInfo->QueueStat));
- ChanInfo->ReorderCount = cur_chan->ReorderCount;
- ChanInfo->IntersectCount = cur_chan->IntersectCount;
- ChanInfo->TryReorderCount = cur_chan->TryReorderCount;
- ChanInfo->TryReorderHeadCount = cur_chan->TryReorderHeadCount;
- ChanInfo->TryReorderTailCount = cur_chan->TryReorderTailCount;
- //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
- ChanInfo++;
- }
- AtaCtl->AdapterInfo.ChanInfoValid = TRUE;
- AtaCtl->AdapterInfo.ChanHeaderLength = sizeof(*ChanInfo);
- }
-
- status = SRB_STATUS_SUCCESS;
- break;
- }
- case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: {
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Forget BB list\n"));
-
- ForgetBadBlocks(LunExt);
-
- status = SRB_STATUS_SUCCESS;
- break;
- }
- case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: {
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device\n"));
-
- if(bad_ldev) {
- goto do_bus_reset;
- } else {
- UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId);
- }
-
- status = SRB_STATUS_SUCCESS;
- break;
- }
- default :
- KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
- AtaCtl->hdr.ControlCode ));
- status = SRB_STATUS_INVALID_REQUEST;
- break;
- }
-
- } else {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
- ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,
- "SCSIDISK", "-UNIATA-"));
-
- status = SRB_STATUS_INVALID_REQUEST;
- break;
- }
-
- break;
- } // end SRB_FUNCTION_IO_CONTROL
- default:
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Unknown IOCTL\n"));
- // Indicate unsupported command.
- status = SRB_STATUS_INVALID_REQUEST;
-
-// break;
-
- } // end switch
-
-complete_req:
-
- PathId = Srb->PathId;
- TargetId = Srb->TargetId;
- Lun = Srb->Lun;
-
- if (status != SRB_STATUS_PENDING) {
-
- KdPrint2((PRINT_PREFIX
- "AtapiStartIo: Srb %#x complete with status %#x\n",
- Srb,
- status));
-
- // Set status in SRB.
- Srb->SrbStatus = (UCHAR)status;
-
- 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.
- KdPrint2((PRINT_PREFIX "AtapiStartIo: ScsiPortNotification\n"));
- ScsiPortNotification(RequestComplete,
- deviceExtension,
- Srb);
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataGetCurRequest\n"));
- // Remove current Srb & get next one
- if((Srb = UniataGetCurRequest(chan))) {
- AtaReq = (PATA_REQ)(Srb->SrbExtension);
- if(AtaReq->ReqState > REQ_STATE_QUEUED) {
- // current request is under precessing, thus
- // we should do nothing here
- Srb = NULL;
- }
- }
- KdPrint2((PRINT_PREFIX "AtapiStartIo: chan %x, Src %x\n", chan, Srb));
- if(!chan) {
- //ASSERT(TopLevel);
- }
- }
- KdPrint2((PRINT_PREFIX "AtapiStartIo: next Srb %x\n", Srb));
-
- } while (Srb && (status != SRB_STATUS_PENDING));
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo: query PORT for next request\n"));
- // Indicate ready for next request.
- ScsiPortNotification(NextRequest,
- deviceExtension,
- NULL);
-
- ScsiPortNotification(NextLuRequest,
- deviceExtension,
- PathId,
- TargetId,
- Lun);
-
- return TRUE;
-
-} // end AtapiStartIo__()
-
-#if 0
-void
-NTAPI
-UniataInitAtaCommands()
-{
- int i;
- UCHAR command;
- UCHAR flags;
-
- KdPrint2((PRINT_PREFIX "UniataInitAtaCommands:\n"));
-
- for(i=0; i<256; i++) {
-
- flags = 0;
- command = i;
-
- //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
-
- switch(command) {
- case IDE_COMMAND_READ_DMA48:
- case IDE_COMMAND_READ_DMA_Q48:
- case IDE_COMMAND_READ_STREAM_DMA48:
- case IDE_COMMAND_READ_STREAM48:
- case IDE_COMMAND_WRITE_DMA48:
- case IDE_COMMAND_WRITE_DMA_Q48:
- case IDE_COMMAND_READ_DMA_Q:
- case IDE_COMMAND_READ_DMA:
- case IDE_COMMAND_WRITE_DMA:
- case IDE_COMMAND_WRITE_DMA_Q:
- case IDE_COMMAND_WRITE_STREAM_DMA48:
- case IDE_COMMAND_WRITE_STREAM48:
- case IDE_COMMAND_WRITE_FUA_DMA48:
- case IDE_COMMAND_WRITE_FUA_DMA_Q48:
- case IDE_COMMAND_READ_LOG_DMA48:
- case IDE_COMMAND_WRITE_LOG_DMA48:
- case IDE_COMMAND_TRUSTED_RCV_DMA:
- case IDE_COMMAND_TRUSTED_SEND_DMA:
- case IDE_COMMAND_DATA_SET_MGMT:
- //KdPrint2((PRINT_PREFIX "DMA "));
- flags |= ATA_CMD_FLAG_DMA;
- }
-
- switch(command) {
- case IDE_COMMAND_WRITE_FUA_DMA48:
- case IDE_COMMAND_WRITE_FUA_DMA_Q48:
- case IDE_COMMAND_WRITE_MUL_FUA48:
-
- flags |= ATA_CMD_FLAG_FUA;
- /* FALL THROUGH */
-
- case IDE_COMMAND_READ48:
- case IDE_COMMAND_READ_DMA48:
- case IDE_COMMAND_READ_DMA_Q48:
- case IDE_COMMAND_READ_MUL48:
- case IDE_COMMAND_READ_STREAM_DMA48:
- case IDE_COMMAND_READ_STREAM48:
- case IDE_COMMAND_WRITE48:
- case IDE_COMMAND_WRITE_DMA48:
- case IDE_COMMAND_WRITE_DMA_Q48:
- case IDE_COMMAND_WRITE_MUL48:
- case IDE_COMMAND_WRITE_STREAM_DMA48:
- case IDE_COMMAND_WRITE_STREAM48:
- case IDE_COMMAND_FLUSH_CACHE48:
- case IDE_COMMAND_VERIFY48:
-
- //KdPrint2((PRINT_PREFIX "48 "));
- flags |= ATA_CMD_FLAG_48;
- /* FALL THROUGH */
-
- case IDE_COMMAND_READ:
- case IDE_COMMAND_READ_MULTIPLE:
- case IDE_COMMAND_READ_DMA:
- case IDE_COMMAND_READ_DMA_Q:
- case IDE_COMMAND_WRITE:
- case IDE_COMMAND_WRITE_MULTIPLE:
- case IDE_COMMAND_WRITE_DMA:
- case IDE_COMMAND_WRITE_DMA_Q:
- case IDE_COMMAND_FLUSH_CACHE:
- case IDE_COMMAND_VERIFY:
-
- //KdPrint2((PRINT_PREFIX "LBA "));
- flags |= ATA_CMD_FLAG_LBAIOsupp;
- }
-
- switch(command) {
- case IDE_COMMAND_READ_NATIVE_SIZE48:
- case IDE_COMMAND_SET_NATIVE_SIZE48:
- // we cannot set LBA flag for these commands to avoid BadBlock handling
- //flags |= ATA_CMD_FLAG_LBAIOsupp;
- flags |= ATA_CMD_FLAG_48;
-
- case IDE_COMMAND_READ_NATIVE_SIZE:
- case IDE_COMMAND_SET_NATIVE_SIZE:
-
- flags |= ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_FUA;
- }
-
- flags |= ATA_CMD_FLAG_48supp;
-
- switch (command) {
- case IDE_COMMAND_READ:
- command = IDE_COMMAND_READ48; break;
- case IDE_COMMAND_READ_MULTIPLE:
- command = IDE_COMMAND_READ_MUL48; break;
- case IDE_COMMAND_READ_DMA:
- command = IDE_COMMAND_READ_DMA48; break;
- case IDE_COMMAND_READ_DMA_Q:
- command = IDE_COMMAND_READ_DMA_Q48; break;
- case IDE_COMMAND_WRITE:
- command = IDE_COMMAND_WRITE48; break;
- case IDE_COMMAND_WRITE_MULTIPLE:
- command = IDE_COMMAND_WRITE_MUL48; break;
- case IDE_COMMAND_WRITE_DMA:
- command = IDE_COMMAND_WRITE_DMA48; break;
- case IDE_COMMAND_WRITE_DMA_Q:
- command = IDE_COMMAND_WRITE_DMA_Q48; break;
- case IDE_COMMAND_FLUSH_CACHE:
- command = IDE_COMMAND_FLUSH_CACHE48; break;
- // case IDE_COMMAND_READ_NATIVE_SIZE:
- // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
- case IDE_COMMAND_SET_NATIVE_SIZE:
- command = IDE_COMMAND_SET_NATIVE_SIZE48; break;
- case IDE_COMMAND_VERIFY:
- command = IDE_COMMAND_VERIFY48; break;
- default:
- //KdPrint2((PRINT_PREFIX "!28->48 "));
- flags &= ~ATA_CMD_FLAG_48supp;
- }
-
- switch (command) {
- case IDE_COMMAND_READ:
- case IDE_COMMAND_READ_MULTIPLE:
- case IDE_COMMAND_READ_DMA48:
- case IDE_COMMAND_READ_DMA_Q48:
- case IDE_COMMAND_READ_STREAM_DMA48:
- case IDE_COMMAND_READ_STREAM48:
- case IDE_COMMAND_READ_DMA_Q:
- case IDE_COMMAND_READ_DMA:
- case IDE_COMMAND_READ_LOG_DMA48:
- case IDE_COMMAND_TRUSTED_RCV_DMA:
- case IDE_COMMAND_IDENTIFY:
- case IDE_COMMAND_ATAPI_IDENTIFY:
- //KdPrint2((PRINT_PREFIX "RD "));
- flags |= ATA_CMD_FLAG_In;
- break;
- case IDE_COMMAND_WRITE:
- case IDE_COMMAND_WRITE_MULTIPLE:
- case IDE_COMMAND_WRITE_DMA48:
- case IDE_COMMAND_WRITE_DMA_Q48:
- case IDE_COMMAND_WRITE_DMA:
- case IDE_COMMAND_WRITE_DMA_Q:
- case IDE_COMMAND_WRITE_STREAM_DMA48:
- case IDE_COMMAND_WRITE_STREAM48:
- case IDE_COMMAND_WRITE_FUA_DMA48:
- case IDE_COMMAND_WRITE_FUA_DMA_Q48:
- //KdPrint2((PRINT_PREFIX "WR "));
- flags |= ATA_CMD_FLAG_Out;
- break;
- }
-
- //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
- AtaCommands48[i] = command;
- AtaCommandFlags[i] = flags;
- }
-} // end UniataInitAtaCommands()
-#endif
-
-/*++
-
-Routine Description:
-
- Installable driver initialization entry point for system.
-
-Arguments:
-
- Driver Object
-
-Return Value:
-
- Status from ScsiPortInitialize()
-
---*/
-extern "C"
-ULONG
-NTAPI
-DriverEntry(
- IN PVOID DriverObject,
- IN PVOID Argument2
- )
-{
- HW_INITIALIZATION_DATA_COMMON hwInitializationData;
- ULONG adapterCount;
- ULONG i, c, alt, pref_alt;
- ULONG statusToReturn, newStatus;
- PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
- BOOLEAN ReEnter = FALSE;
-// WCHAR a;
-#ifndef USE_REACTOS_DDK
- NTSTATUS status;
-#endif
-
- PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation();
- BOOLEAN PrimaryClaimed = FALSE;
- BOOLEAN SecondaryClaimed = FALSE;
- BOOLEAN IgnoreIsaCompatiblePci = FALSE;
- BOOLEAN IgnoreNativePci = FALSE;
-
- LARGE_INTEGER t0, t1;
-
- KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string));
- //a = (WCHAR)strlen(ver_string);
-
- statusToReturn = 0xffffffff;
-
- // Zero out structure.
- RtlZeroMemory(((PCHAR)&hwInitializationData), sizeof(hwInitializationData));
-
- // Set size of hwInitializationData.
- hwInitializationData.comm.HwInitializationDataSize =
- sizeof(hwInitializationData.comm) +
-// sizeof(hwInitializationData.nt4) +
- ((WinVer_Id() <= WinVer_NT) ? 0 : sizeof(hwInitializationData.w2k));
- KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData.comm.HwInitializationDataSize));
-
- // Set entry points.
- hwInitializationData.comm.HwInitialize = (PHW_INITIALIZE)AtapiHwInitialize;
- hwInitializationData.comm.HwResetBus = (PHW_RESET_BUS)AtapiResetController;
- hwInitializationData.comm.HwStartIo = (PHW_STARTIO)AtapiStartIo;
- hwInitializationData.comm.HwInterrupt = (PHW_INTERRUPT)AtapiInterrupt;
-
- // Specify size of extensions.
- hwInitializationData.comm.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
- hwInitializationData.comm.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION);
- hwInitializationData.comm.SrbExtensionSize = sizeof(ATA_REQ);
-
- // Indicate PIO device.
- hwInitializationData.comm.MapBuffers = TRUE;
-
- // Request and parse arument string.
- KdPrint2((PRINT_PREFIX "\n\nUniATA: parse ArgumentString\n"));
- // Zero out structure.
- hwInitializationData.comm.NumberOfAccessRanges = 2;
- hwInitializationData.comm.HwFindAdapter = AtapiReadArgumentString;
- ScsiPortInitialize(DriverObject,
- Argument2,
- &hwInitializationData.comm,
- &adapterCount);
-
- if(!g_Dump) {
- Connect_DbgPrint();
- g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0);
- if(g_opt_Verbose) {
- _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR "\n");
- }
- IgnoreIsaCompatiblePci = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", IgnoreIsaCompatiblePci) ? TRUE : FALSE;
- IgnoreNativePci = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", IgnoreNativePci) ? TRUE : FALSE;
- } else {
- KdPrint(("crashdump mode\n"));
- }
-
- if(!SavedDriverObject) {
- SavedDriverObject = (PDRIVER_OBJECT)DriverObject;
-#ifdef USE_REACTOS_DDK
- KdPrint(("UniATA Init: OS should be ReactOS\n"));
- MajorVersion=0x04;
- MinorVersion=0x01;
- BuildNumber=1;
- CPU_num = KeNumberProcessors;
-#else
- // we are here for the 1st time
- // init CrossNT and get OS version
- if(!NT_SUCCESS(status = CrNtInit(SavedDriverObject, RegistryPath))) {
- KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status));
- //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
- return status;
- }
- CPU_num = *KeNumberProcessors;
-#endif // USE_REACTOS_DDK
- KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, CPU_num));
-
- KeQuerySystemTime(&t0);
- do {
- KeQuerySystemTime(&t1);
- } while(t0.QuadPart == t1.QuadPart);
- t0=t1;
- g_Perf=0;
- do {
- KeQuerySystemTime(&t1);
- g_Perf++;
- } while(t0.QuadPart == t1.QuadPart);
- g_PerfDt = (ULONG)((t1.QuadPart - t0.QuadPart)/10);
- KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt, g_Perf ));
- } else {
- KdPrint(("UniATA Init: ReEnter\n"));
- ReEnter = TRUE;
- }
-
- // (re)read bad block list
- InitBadBlocks(NULL);
-
- if(!ReEnter) {
- // init ATA command translation table
- //UniataInitAtaCommands();
-
- // get registry path to settings
- RtlCopyMemory(&SavedRegPath, RegistryPath, sizeof(UNICODE_STRING));
- SavedRegPath.Buffer = (PWCHAR)&SavedRegPathBuffer;
- SavedRegPath.Length = min(RegistryPath->Length, 255*sizeof(WCHAR));
- SavedRegPath.MaximumLength = 255*sizeof(WCHAR);
- RtlCopyMemory(SavedRegPath.Buffer, RegistryPath->Buffer, SavedRegPath.Length);
- SavedRegPath.Buffer[SavedRegPath.Length/sizeof(WCHAR)] = 0;
- }
-
- if(WinVer_Id() >= WinVer_2k) {
- if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"1", 0)) {
- KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
- WinVer_WDM_Model = TRUE;
- }
- if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"5", 0)) {
- KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
- WinVer_WDM_Model = TRUE;
- }
- }
-
- SkipRaids = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"SkipRaids", 1);
- ForceSimplex = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"ForceSimplex", 0);
-#ifdef _DEBUG
- g_LogToDisplay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"LogToDisplay", 0);
-#endif //_DEBUG
-
- // Set PnP-specific API
- if(WinVer_Id() > WinVer_NT) {
- KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
- hwInitializationData.comm.NeedPhysicalAddresses = TRUE;
- KdPrint(("set AtapiAdapterControl() ptr\n"));
- hwInitializationData.w2k.HwAdapterControl = (PHW_ADAPTER_CONTROL)AtapiAdapterControl;
- }
-
- KdPrint2((PRINT_PREFIX "\n\nUniATA init... (%d)\n", ReEnter));
- if(!ReEnter) {
-
- g_opt_VirtualMachine = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualMachineType", g_opt_VirtualMachine);
- if(g_opt_VirtualMachine > VM_MAX_KNOWN) {
- g_opt_VirtualMachine = 0;
- }
- if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualBox", (g_opt_VirtualMachine == VM_VBOX))) {
- g_opt_VirtualMachine = VM_VBOX;
- }
- // Pre-scan PCI bus, also check if we are under VM
- // But do not perform scan if PCI bus is claimed as unused
- if(!IgnoreIsaCompatiblePci || !IgnoreNativePci) {
- KdPrint2((PRINT_PREFIX "\nATAPI IDE enum supported PCI BusMaster Devices\n"));
- UniataEnumBusMasterController(DriverObject, Argument2);
- }
-
- switch(g_opt_VirtualMachine) {
- case VM_VBOX:
- KdPrint2((PRINT_PREFIX "adjust options for VirtualBox\n"));
- // adjust options for VirtualBox
- g_opt_WaitBusyCount = 20000;
- g_opt_WaitBusyDelay = 150;
- g_opt_WaitDrqDelay = 100;
- g_opt_WaitBusyLongCount = 20000;
- g_opt_MaxIsrWait = 200;
- g_opt_AtapiSendDisableIntr = FALSE;
- g_opt_AtapiDmaRawRead = FALSE;
- break;
- case VM_BOCHS:
- KdPrint2((PRINT_PREFIX "adjust options for Bochs\n"));
- g_opt_AtapiNoDma = TRUE;
- }
-
- if(!hasPCI) {
- KdPrint2((PRINT_PREFIX "old slow machine, adjust timings\n"));
- // old slow machine, adjust timings (us)
- g_opt_WaitBusyResetCount = 20000;
- g_opt_WaitBusyCount = 20000;
- g_opt_WaitBusyDelay = 150;
- g_opt_WaitDrqDelay = 100;
- g_opt_WaitBusyLongCount = 20000;
- g_opt_MaxIsrWait = 200;
- g_opt_DriveSelectNanoDelay = 400;
- }
- if(g_opt_VirtualMachine > VM_NONE) {
- g_opt_DriveSelectNanoDelay = 0;
- }
- if(CPU_num > 1) {
- g_opt_AtapiSendDisableIntr = TRUE;
- }
-
- g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000
- g_opt_WaitBusyDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyDelay", g_opt_WaitBusyDelay); // 10 vs 150
- g_opt_WaitDrqDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay", g_opt_WaitDrqDelay); // 10 vs 100
- g_opt_WaitBusyLongCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongCount", g_opt_WaitBusyLongCount); // 2000 vs 20000
- g_opt_WaitBusyLongDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongDelay", g_opt_WaitBusyLongDelay); // 250 vs 250
- g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr) ? TRUE : FALSE; // 1 vs 0
- g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead) ? TRUE : FALSE; // 1 vs 0
- g_opt_AtapiNoDma = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiNoDma", g_opt_AtapiNoDma) ? TRUE : FALSE; // 1 vs 0
- g_opt_MaxIsrWait = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"MaxIsrWait", g_opt_MaxIsrWait); // 40 vs xxx
- g_opt_DriveSelectNanoDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"DriveSelectNanoDelay", g_opt_DriveSelectNanoDelay);
- } // end !re-enter
-
- // Look for legacy ISA-bridged PCI IDE controller (onboard)
- KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
- KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: BMListLen %d\n", BMListLen));
- for (i=0; i <BMListLen; i++) {
-
- if(!BMList[i].MasterDev) {
- KdPrint2((PRINT_PREFIX "!BMList[i].MasterDev\n"));
- break;
- }
- if(IgnoreIsaCompatiblePci) {
- break;
- }
- if(ReEnter) {
- KdPrint2((PRINT_PREFIX "ReEnter, skip it\n"));
- if(BMList[i].ChanInitOk & 0x03) {
- KdPrint2((PRINT_PREFIX "Already initialized, skip it\n"));
- statusToReturn =
- newStatus = STATUS_SUCCESS;
- }
- continue;
- }
- //BMList[i].AltInitMasterDev = (UCHAR)0xff;
-
- if(GlobalConfig->AtDiskPrimaryAddressClaimed)
- PrimaryClaimed = TRUE;
- if(GlobalConfig->AtDiskSecondaryAddressClaimed)
- SecondaryClaimed = TRUE;
- pref_alt = 0;
-
- if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed && !g_Dump &&
- !(BMList[i].ChanInitOk & 0x80)) {
-
- // We just want to claim our PCI device in compatible mode, since we shall not
- // tell system that we use it inside HwInitialize
- // Even more, we shall cheat system, that work with ISA
- // Note: this call may (but not 'must' or 'can') cause IO resource
- // reallocation and switch to native mode if HAL supports this
- newStatus = (ULONG)UniataClaimLegacyPCIIDE(i);
- // Special check for NT3.51/NT4 (not ReactOS !!!)
- if(((NTSTATUS)newStatus == STATUS_CONFLICTING_ADDRESSES) &&
- //(BMList[i].ChanInitOk & 0x40) &&
- /*CPU_num > 1 &&*/
- (WinVer_Id() <= WinVer_NT)) {
- // Some NT3/4 SMP (but not only) HALs cannot reallocate IO resources of
- // BusMaster PCI controller
- // Since nobody claimed Primary/Secondary yet, try init and claim them
- // However it is not 100% safe way, especially under ReactOS, which doesn't resolve
- // conflicts yet.
- // We relay on ScsiPort internal checks
- KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster on SMP NT3/4 system, try init anyway.\n"));
- newStatus = STATUS_SUCCESS;
- // Prefer alternative init method (try to change Isa -> PCI in ConfigInfo first)
- pref_alt = 1;
- }
- 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:");
- }
-
- for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) {
-
- for(c=0; c<2; c++) {
- // check is channel is manually excluded
- if(AtapiRegCheckDevValue(NULL, c, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
- break;
- }
- if(c==0) {
- if(PrimaryClaimed) {
- KdPrint2((PRINT_PREFIX "Primary already claimed\n"));
- continue;
- }
- } else
- if(c==1) {
- if(SecondaryClaimed) {
- KdPrint2((PRINT_PREFIX "Secondary already claimed\n"));
- continue;
- }
- }
-
- if((WinVer_Id() < WinVer_2k)) {
- // do not even try if already claimed
- if(c==0) {
- GlobalConfig->AtDiskPrimaryAddressClaimed = FALSE;
- } else
- if(c==1) {
- GlobalConfig->AtDiskSecondaryAddressClaimed = FALSE;
- }
- }
- if(!WinVer_WDM_Model) {
- hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
- } else {
- // in WDM model things are different....
- hwInitializationData.comm.HwFindAdapter = (c == 0) ?
- UniataFindCompatBusMasterController1 : UniataFindCompatBusMasterController2;
- }
- hwInitializationData.comm.NumberOfAccessRanges = 6;
- hwInitializationData.comm.AdapterInterfaceType = Isa;
-
- if(!WinVer_WDM_Model) {
- BMList[i].channel = (UCHAR)c;
- }
-
- KdPrint2((PRINT_PREFIX "Try init channel %d, method %d\n", c, alt));
- newStatus = ScsiPortInitialize(DriverObject,
- Argument2,
- &hwInitializationData.comm,
- (PVOID)(i | ((alt ^ pref_alt) ? 0x80000000 : 0)));
- KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
- if (newStatus < statusToReturn) {
- statusToReturn = newStatus;
- }
- if (newStatus == STATUS_SUCCESS) {
- 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()
- BMList[i].ChanInitOk |= 0x01 << c;
- }
-*/
- }
- }
-/* 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 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"));
- }
- } // for(alt...)
- if(g_opt_Verbose) {
- if(BMList[i].ChanInitOk & 0x03) {
- _PrintNtConsole(" OK\n");
- } else {
- _PrintNtConsole(" failed\n");
- }
- }
-
- }
-
-/* KeBugCheckEx(0xc000000e,
- (i << 16) | BMList[0].ChanInitOk,
- c,
- newStatus, statusToReturn);*/
-
- // Look for PCI IDE controller
- KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for PCI IDE controller\n"));
- KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: i %d, BMListLen %d\n", i, BMListLen));
- for (; i <BMListLen; i++) {
-
- if(IgnoreNativePci) {
- break;
- }
-/* if(BMList[i].MasterDev)
- continue;*/
- if(g_opt_Verbose) {
- _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
- BMList[i].VendorId, BMList[i].DeviceId,
- BMList[i].busNumber,
- BMList[i].slotNumber % PCI_MAX_FUNCTION,
- (BMList[i].slotNumber / PCI_MAX_FUNCTION) % PCI_MAX_DEVICES);
- }
-
- hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
- hwInitializationData.comm.NumberOfAccessRanges = 6;
- hwInitializationData.comm.AdapterInterfaceType = PCIBus;
-
- hwInitializationData.comm.VendorId = (PVOID)BMList[i].VendorId;
- hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
- hwInitializationData.comm.DeviceId = (PVOID)BMList[i].DeviceId;
- hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
-
- BMList[i].channel = 0/*(UCHAR)c*/;
-
- KdPrint2((PRINT_PREFIX "Try init %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));
- if(newStatus == (ULONG)STATUS_DEVICE_DOES_NOT_EXIST && BMList[i].NeedAltInit) {
- // Note: this is actually a BUG in scsiport.sys
- // It stops scanning PCI bus when reaches empty PCI Function inside Slot
- // However, this PCI Slot may have higher non-empty Functions
- // UniATA will perform all staff instead of ScsiPort under NT,
- // but for ReactOS it is better to patch ScsiPort.
- KdPrint2((PRINT_PREFIX "STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
- hwInitializationData.comm.AdapterInterfaceType = Isa;
- newStatus = ScsiPortInitialize(DriverObject,
- Argument2,
- &hwInitializationData.comm,
- (PVOID)(i | 0x80000000));
- KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x (2)\n", newStatus));
- }
- if (newStatus < statusToReturn)
- statusToReturn = newStatus;
-
- if(g_opt_Verbose) {
- if(newStatus == STATUS_SUCCESS) {
- _PrintNtConsole(" OK\n");
- } else {
- _PrintNtConsole(" failed\n");
- }
- }
-
- }
-
-/* KeBugCheckEx(0xc000000e,
- i,
- c,
- newStatus, statusToReturn);*/
-
- // --------------
-
- hwInitializationData.comm.VendorId = 0;
- hwInitializationData.comm.VendorIdLength = 0;
- hwInitializationData.comm.DeviceId = 0;
- hwInitializationData.comm.DeviceIdLength = 0;
-
- if(!BMListLen) {
- hwInitializationData.comm.SrbExtensionSize = //FIELD_OFFSET(ATA_REQ, ata);
- sizeof(ATA_REQ);
- KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", hwInitializationData.comm.SrbExtensionSize));
- }
-
- // The adapter count is used by the find adapter routine to track how
- // which adapter addresses have been tested.
-
- // Indicate 2 access ranges and reset FindAdapter.
- hwInitializationData.comm.NumberOfAccessRanges = 2;
- hwInitializationData.comm.HwFindAdapter = AtapiFindIsaController;
-
- if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsa", 0)) {
- // Indicate ISA bustype.
- hwInitializationData.comm.AdapterInterfaceType = Isa;
- adapterCount = 0;
-
- // Call initialization for ISA bustype.
- KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for ISA Controllers\n"));
- newStatus = ScsiPortInitialize(DriverObject,
- Argument2,
- &hwInitializationData.comm,
- &adapterCount);
- KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
- if (newStatus < statusToReturn)
- statusToReturn = newStatus;
- }
- if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreMca", 0)) {
- // Set up for MCA
- KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for MCA Controllers\n"));
- hwInitializationData.comm.AdapterInterfaceType = MicroChannel;
- adapterCount = 0;
-
- newStatus = ScsiPortInitialize(DriverObject,
- Argument2,
- &hwInitializationData.comm,
- &adapterCount);
- KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
- if (newStatus < statusToReturn)
- statusToReturn = newStatus;
- }
- InDriverEntry = FALSE;
-
- KdPrint2((PRINT_PREFIX "\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn));
-
- return statusToReturn;
-
-} // end DriverEntry()
-
-
-PSCSI_REQUEST_BLOCK
-NTAPI
-BuildMechanismStatusSrb(
- IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PSCSI_REQUEST_BLOCK srb;
- PCDB cdb;
- PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
-
- srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
-
- RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
-
- srb->PathId = (UCHAR)(Srb->PathId);
- srb->TargetId = (UCHAR)(Srb->TargetId);
- srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
- srb->Length = sizeof(SCSI_REQUEST_BLOCK);
-
- // Set flags to disable synchronous negociation.
- srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
-
- // Set timeout to 4 seconds.
- srb->TimeOutValue = 4;
-
- srb->CdbLength = 6;
- srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusData);
- srb->DataTransferLength = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
- srb->SrbExtension = AtaReq;
-
- // Set CDB operation code.
- cdb = (PCDB)srb->Cdb;
- cdb->MECH_STATUS.OperationCode = SCSIOP_MECHANISM_STATUS;
- cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
-
- KdPrint2((PRINT_PREFIX " MechanismStatusSrb %#x\n", srb));
-
- return srb;
-} // end BuildMechanismStatusSrb()
-
-#endif //UNIATA_CORE
-
-PSCSI_REQUEST_BLOCK
-NTAPI
-BuildRequestSenseSrb (
- IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PSCSI_REQUEST_BLOCK srb;
- PCDB cdb;
- PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
-
- srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
-
- RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
-
- srb->PathId = (UCHAR)(Srb->PathId);
- srb->TargetId = (UCHAR)(Srb->TargetId);
- srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
- srb->Length = sizeof(SCSI_REQUEST_BLOCK);
-
- // Set flags to disable synchronous negociation.
- srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
-
- // Set timeout to 2 seconds.
- srb->TimeOutValue = 4;
-
- srb->CdbLength = 6;
- srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusSense);
- srb->DataTransferLength = sizeof(SENSE_DATA);
- srb->SrbExtension = AtaReq;
-
- // Set CDB operation code.
- cdb = (PCDB)srb->Cdb;
- cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
- cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
-
- KdPrint2((PRINT_PREFIX " RequestSenseSrb %#x\n", srb));
-
- return srb;
-} // end BuildRequestSenseSrb()
-
-#ifndef UNIATA_CORE
-
-ULONG
-NTAPI
-AtapiRegCheckDevLunValue(
- IN PVOID HwDeviceExtension,
- IN PCWCH NamePrefix,
- IN ULONG chan,
- IN ULONG dev,
- IN PCWSTR Name,
- IN ULONG Default
- )
-{
- WCHAR namex[160];
- ULONG val = Default;
-
- val = AtapiRegCheckParameterValue(
- HwDeviceExtension, NamePrefix, Name, val);
-
- if(chan != CHAN_NOT_SPECIFIED) {
- swprintf(namex, L"%s\\Chan_%1.1d", NamePrefix, chan);
- val = AtapiRegCheckParameterValue(
- HwDeviceExtension, namex, Name, val);
- if(dev != DEVNUM_NOT_SPECIFIED) {
- swprintf(namex, L"%s\\Chan_%1.1d\\%s", NamePrefix, chan, (dev & 0x01) ? L"Lun_1" : L"Lun_0");
- val = AtapiRegCheckParameterValue(
- HwDeviceExtension, namex, Name, val);
- }
- }
- return val;
-} // end AtapiRegCheckDevLunValue()
-
-ULONG
-NTAPI
-EncodeVendorStr(
- OUT PWCHAR Buffer,
- IN PUCHAR Str,
- IN ULONG Length
- )
-{
- ULONG i,j;
- WCHAR a;
-
- for(i=0, j=0; i<Length; i++, j++) {
- // fix byte-order
- a = Str[i ^ 0x01];
- if(!a) {
- Buffer[j] = 0;
- return j;
- } else
- if(a == ' ') {
- Buffer[j] = '_';
- } else
- if((a == '_') ||
- (a == '#') ||
- (a == '\\') ||
- (a == '\"') ||
- (a == '\'') ||
- (a < ' ') ||
- (a >= 127)) {
- Buffer[j] = '#';
- j++;
- swprintf(Buffer+j, L"%2.2x", a);
- j++;
- } else {
- Buffer[j] = a;
- }
- }
- Buffer[j] = 0;
- return j;
-} // end EncodeVendorStr()
-
-ULONG
-NTAPI
-AtapiRegCheckDevValue(
- IN PVOID HwDeviceExtension,
- IN ULONG chan,
- IN ULONG dev,
- IN PCWSTR Name,
- IN ULONG Default
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
-// WCHAR name0[11];
-// WCHAR name1[11+4+5];
-// WCHAR name2[11+4+4+10];
-// WCHAR name3[11+4+4+5+20];
-// WCHAR name3[11+4+4+5+20+1];
- WCHAR namex[160];
-
- WCHAR namev[16];
- WCHAR named[16];
- WCHAR names[20];
-
- IN ULONG VendorID;
- IN ULONG DeviceID;
- IN ULONG SlotNumber;
-
- ULONG val = Default;
-
- KdPrint(( " Parameter %ws\n", Name));
-
- if(deviceExtension) {
- VendorID = deviceExtension->DevID & 0xffff;
- DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
- SlotNumber = deviceExtension->slotNumber;
- } else {
- VendorID = 0xffff;
- DeviceID = 0xffff;
- SlotNumber = 0xffffffff;
- }
-
- val = AtapiRegCheckDevLunValue(
- HwDeviceExtension, L"Parameters", chan, dev, Name, val);
-
- if(deviceExtension) {
- if(deviceExtension->AdapterInterfaceType == PCIBus) {
- // PCI
- swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex);
- swprintf(namex, L"Parameters%s", namev);
- val = AtapiRegCheckDevLunValue(
- HwDeviceExtension, namex, chan, dev, Name, val);
-
-
- swprintf(namev, L"\\Ven_%4.4x", VendorID);
- swprintf(named, L"\\Dev_%4.4x", DeviceID);
- swprintf(names, L"\\Slot_%8.8x", SlotNumber);
-
- swprintf(namex, L"Parameters%s", namev);
- val = AtapiRegCheckDevLunValue(
- HwDeviceExtension, namex, chan, dev, Name, val);
-
- swprintf(namex, L"Parameters%s%s", namev, named);
- val = AtapiRegCheckDevLunValue(
- HwDeviceExtension, namex, chan, dev, Name, val);
-
- swprintf(namex, L"Parameters%s%s%s", namev, named, names);
- val = AtapiRegCheckDevLunValue(
- HwDeviceExtension, namex, chan, dev, Name, val);
- } else
- if(deviceExtension->AdapterInterfaceType == Isa) {
- // Isa
- swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen);
- swprintf(namex, L"Parameters%s", namev);
- val = AtapiRegCheckDevLunValue(
- HwDeviceExtension, namex, chan, dev, Name, val);
-
- swprintf(namev, L"\\ISA_%d", deviceExtension->DevIndex);
- swprintf(namex, L"Parameters%s", namev);
- val = AtapiRegCheckDevLunValue(
- HwDeviceExtension, namex, chan, dev, Name, val);
-
- } else
- if(deviceExtension->AdapterInterfaceType == MicroChannel) {
- // MicroChannel
- swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen+IsaCount);
- swprintf(namex, L"Parameters%s", namev);
- val = AtapiRegCheckDevLunValue(
- HwDeviceExtension, namex, chan, dev, Name, val);
-
- swprintf(namev, L"\\MCA_%d", deviceExtension->DevIndex);
- swprintf(namex, L"Parameters%s", namev);
- val = AtapiRegCheckDevLunValue(
- HwDeviceExtension, namex, chan, dev, Name, val);
-
- }
- }
-
- KdPrint(( " Parameter %ws = %#x\n", Name, val));
- return val;
-
-} // end AtapiRegCheckDevValue()
-
-/*
- The user must specify that Xxx is to run on the platform
- by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
- Services\UniATA\Xxx:REG_DWORD:Zzz.
-
- The user can override the global setting to enable or disable Xxx on a
- specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
- CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
-
- If this registry value does not exist or contains the value zero then
- the timer to check for media change does not run.
-
- Arguments:
-
- RegistryPath - pointer to the unicode string inside
- ...\CurrentControlSet\Services\UniATA
- DeviceNumber - The number of the HBA device object
-
- Returns: Registry Key value
- */
-ULONG
-NTAPI
-AtapiRegCheckParameterValue(
- IN PVOID HwDeviceExtension,
- IN PCWSTR PathSuffix,
- IN PCWSTR Name,
- IN ULONG Default
- )
-{
-#define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
-
-// PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- NTSTATUS status;
- LONG zero = Default;
-
- RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
-
-// LONG tmp = 0;
- LONG doRun = Default;
-
- PUNICODE_STRING RegistryPath = &SavedRegPath;
-
- UNICODE_STRING paramPath;
-
- if(g_Dump) {
- goto failed;
- }
-
- // <SavedRegPath>\<PathSuffix> -> <Name>
-// KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
-// KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
-
- paramPath.Length = 0;
- paramPath.MaximumLength = RegistryPath->Length +
- (wcslen(PathSuffix)+2)*sizeof(WCHAR);
- paramPath.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, paramPath.MaximumLength);
- if(!paramPath.Buffer) {
- KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
- return Default;
- }
-
- RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength);
- RtlAppendUnicodeToString(¶mPath, RegistryPath->Buffer);
- RtlAppendUnicodeToString(¶mPath, L"\\");
- RtlAppendUnicodeToString(¶mPath, REGRTL_STR_PTYPE PathSuffix);
-
- // Check for the Xxx value.
- RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
-
- parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
- parameters[0].Name = REGRTL_STR_PTYPE Name;
- parameters[0].EntryContext = &doRun;
- parameters[0].DefaultType = REG_DWORD;
- parameters[0].DefaultData = &zero;
- parameters[0].DefaultLength = sizeof(ULONG);
-
- status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
- paramPath.Buffer, parameters, NULL, NULL);
- if(NT_SUCCESS(status)) {
- KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
- }
-
- ExFreePool(paramPath.Buffer);
-
- if(!NT_SUCCESS(status)) {
-failed:
- doRun = Default;
- }
-
- return doRun;
-
-#undef ITEMS_TO_QUERY
-
-} // end AtapiRegCheckParameterValue()
-
-
-SCSI_ADAPTER_CONTROL_STATUS
-NTAPI
-AtapiAdapterControl(
- IN PVOID HwDeviceExtension,
- IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
- IN PVOID Parameters
- )
-{
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList;
- ULONG numberChannels = deviceExtension->NumberChannels;
- ULONG c;
- NTSTATUS status;
-
- KdPrint(( "AtapiAdapterControl: %#x\n", ControlType));
-
- switch(ControlType) {
- case ScsiQuerySupportedControlTypes: {
- BOOLEAN supportedTypes[ScsiAdapterControlMax] = {
- TRUE, // ScsiQuerySupportedControlTypes
- TRUE, // ScsiStopAdapter
- TRUE, // ScsiRestartAdapter
- FALSE, // ScsiSetBootConfig
- FALSE // ScsiSetRunningConfig
- };
-
- ULONG lim = ScsiAdapterControlMax;
- ULONG i;
-
- pControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST) Parameters;
-
- if(pControlTypeList->MaxControlType < lim) {
- lim = pControlTypeList->MaxControlType;
- }
-
- for(i = 0; i < lim; i++) {
- pControlTypeList->SupportedTypeList[i] = supportedTypes[i];
- }
-
- break;
-
- }
- case ScsiStopAdapter: {
-
- KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
- // Shut down all interrupts on the adapter. They'll get re-enabled
- // by the initialization routines.
- for (c = 0; c < numberChannels; c++) {
- AtapiResetController(deviceExtension, c);
- AtapiDisableInterrupts(deviceExtension, c);
- }
- if(deviceExtension->AdapterInterfaceType == PCIBus) {
- // we must never get here for non-PCI
- /*status =*/ UniataDisconnectIntr2(HwDeviceExtension);
- BMList[deviceExtension->DevIndex].Isr2Enable = FALSE;
- }
- break;
- }
- case ScsiRestartAdapter: {
-
- KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
- // Enable all the interrupts on the adapter while port driver call
- // for power up an HBA that was shut down for power management
-
- AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
- status = UniataConnectIntr2(HwDeviceExtension);
- 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;
- }
-
- default: {
- KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
- return ScsiAdapterControlUnsuccessful;
- }
- }
-
- return ScsiAdapterControlSuccess;
-} // end AtapiAdapterControl()
-
-#endif //UNIATA_CORE
-
-extern "C"
-NTHALAPI
-VOID
-NTAPI
-HalDisplayString (
- PUCHAR String
- );
-
-#define DEBUG_MSG_BUFFER_SIZE 512
-
-extern "C"
-VOID
-_cdecl
-_PrintNtConsole(
- PCCH DebugMessage,
- ...
- )
-{
- //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], DEBUG_MSG_BUFFER_SIZE-1, DebugMessage, ap);
-
- dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE-1] = 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()
-