/drivers/storage/ide/uniata/id_ata.cpp
C++ | 9575 lines | 6997 code | 1343 blank | 1235 comment | 1413 complexity | a9c6a1e31e8b6930e2482b6edb54b0e8 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-3.0, CC-BY-SA-3.0, AGPL-3.0, GPL-3.0, CPL-1.0
- /*++
- Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
- Module Name:
- id_ata.cpp
- Abstract:
- This is the miniport driver for ATA/ATAPI IDE 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 greatly changed/updated by
- Alter, Copyright (c) 2002-2007:
- 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) support
- 9. NT 3.51 support (binary compatibility)
- etc. (See todo.txt)
- --*/
- #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_WaitBusyCount = 200; // 20000
- ULONG g_opt_WaitBusyDelay = 10; // 150
- ULONG g_opt_WaitDrqDelay = 10; // 100
- BOOLEAN g_opt_AtapiSendDisableIntr = 1; // 0
- BOOLEAN g_opt_AtapiDmaRawRead = 1; // 0
- ULONG g_opt_VirtualMachine = 0; // Auto
- BOOLEAN InDriverEntry = TRUE;
- BOOLEAN g_opt_Verbose = 0;
- BOOLEAN WinVer_WDM_Model = FALSE;
- //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
- );
- #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) { \
- } else \
- 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) { \
- } else \
- 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) { \
- return 0; \
- } else \
- 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) { \
- return 0; \
- } else \
- 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;
- 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);
- } else {
- break;
- }
- }
- if(i) {
- KdPrint2((PRINT_PREFIX "AtapiSuckPort2: overrun detected (%#x words)\n", i ));
- }
- return statusByte;
- } // AtapiSuckPort2()
- UCHAR
- DDKFASTAPI
- WaitOnBusy(
- IN PHW_CHANNEL chan
- )
- {
- ULONG i;
- UCHAR Status;
- for (i=0; i<200; i++) {
- GetStatus(chan, Status);
- if (Status & IDE_STATUS_BUSY) {
- AtapiStallExecution(10);
- 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<2000; i++) {
- GetStatus(chan, Status);
- if (Status & IDE_STATUS_BUSY) {
- AtapiStallExecution(250);
- continue;
- } else {
- break;
- }
- }
- return Status;
- } // end WaitOnBusyLong()
- UCHAR
- DDKFASTAPI
- WaitOnBaseBusy(
- IN PHW_CHANNEL chan
- )
- {
- ULONG i;
- UCHAR Status = 0xff;
- 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 == 0xff) {
- return 0xff;
- }
- 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 == 0xff) {
- // 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,
- ULONG DeviceNumber
- )
- {
- //ULONG c = chan->lChannel;
- ULONG i = 30 * 1000;
- UCHAR dma_status = 0;
- KdPrint2((PRINT_PREFIX "AtapiSoftReset:\n"));
- UCHAR 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);
- AtapiStallExecution(500);
- AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
- // 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);
- }
- 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()
- /*
- 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 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"));
- RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
- if(!UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
- &(AHCI_CMD->cfis[0]),
- command,
- lba,
- count,
- feature,
- ATA_IMMEDIATE
- )) {
- return 0xff;
- }
- if(UniataAhciSendCommand(deviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) {
- KdPrint2((" timeout\n"));
- return 0xff;
- }
- return IDE_STATUS_IDLE;
- }
- 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) &&
- 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 (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 == 0xff) {
- // no drive ?
- break;
- } else
- if(statusByte & IDE_STATUS_ERROR) {
- break;
- } else
- if(statusByte & IDE_STATUS_BUSY) {
- AtapiStallExecution(100);
- continue;
- } else
- if(statusByte == 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;
- }
- chan->ExpectingInterrupt = TRUE;
- // !!!!!
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- statusByte = 0;
- 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 flags
- )
- {
- if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
- return AtaCommand48(deviceExtension, DeviceNumber, lChannel,
- command,
- (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
- count, feature, flags);
- } else {
- PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
- PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
- KdPrint3(("AtaCommand(ahci)\n"));
- RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
- if(!UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
- &(AHCI_CMD->cfis[0]),
- command,
- (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
- count,
- feature,
- ATA_IMMEDIATE
- )) {
- return 0xff;
- }
- if(UniataAhciSendCommand(deviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) {
- KdPrint2((" timeout\n"));
- return 0xff;
- }
- return IDE_STATUS_IDLE;
- }
- } // 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 -1;
- } // 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 -1;
- } // end AtaWmode()
- LONG
- NTAPI
- AtaUmode(PIDENTIFY_DATA2 ident)
- {
- if (!ident->UdmaModesValid)
- return -1;
- 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 -1;
- } // end AtaUmode()
- #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 channles 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
- 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));
- }
- 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()
- /*++
- 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;
- PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
- 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(deviceExtension->HwFlags & UNIATA_AHCI) {
- statusByte = WaitOnBusyLong(chan);
- } else {
- SelectDrive(chan, DeviceNumber);
- AtapiStallExecution(10);
- statusByte = WaitOnBusyLong(chan);
- // Check that the status register makes sense.
- GetBaseStatus(chan, statusByte2);
- UniataDumpATARegs(chan);
- }
- 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);
- } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
- GetBaseStatus(chan, statusByte2);
- SelectDrive(chan, DeviceNumber);
- } else {
- GetBaseStatus(chan, statusByte2);
- }
- // 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(!(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(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- j = 4; // skip old-style checks
- } else {
- j = 0;
- }
- for (; j < 4*2; j++) {
- // Send IDENTIFY command.
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, 0, 0, 0, (j >= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR);
- // Clear interrupt
- 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 chances.
- 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;
- }
- 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));
- if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
- KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
- #if 0
- USHORT w;
- ULONG i;
- // ATI/SII chipsets with memory-mapped IO hangs when
- // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
- // Unfortunately, I don't know yet how to workaround it except the way you see below.
- KdPrint2((PRINT_PREFIX
- " IO_%#x (%#x), %s:\n",
- IDX_IO1_i_Data,
- chan->RegTranslation[IDX_IO1_i_Data].Addr,
- chan->RegTranslation[IDX_IO1_i_Data].MemIo ? "Mem" : "IO"));
- for(i=0; i<256; i++) {
- /*
- KdPrint2((PRINT_PREFIX
- " IO_%#x (%#x):\n",
- IDX_IO1_i_Data,
- chan->RegTranslation[IDX_IO1_i_Data].Addr));
- */
- w = AtapiReadPort2(chan, IDX_IO1_i_Data);
- KdPrint2((PRINT_PREFIX
- " %x\n", w));
- AtapiStallExecution(1);
- ((PUSHORT)&deviceExtension->FullIdentifyData)[i] = w;
- }
- #else
- ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
- #endif
- // Work around for some IDE and one model Atapi that will present more than
- // 256 bytes for the Identify data.
- KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
- statusByte = AtapiSuckPort2(chan);
- } else {
- KdPrint2((PRINT_PREFIX " use 32bit IO\n"));
- ReadBuffer2(chan, (PUSHORT)&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));
- 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\n", deviceExtension->FullIdentifyData.UltraDMAActive));
- }
- KdPrint2((PRINT_PREFIX "SATA: %x\n", deviceExtension->FullIdentifyData.SataEnable));
- // 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 (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;
- // 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) &&*/
- (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 "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.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)) {
- 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)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)) {
- 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;
- }
- }
- }
- }
-
- 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)) {
- 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));
- tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *
- deviceExtension->FullIdentifyData.NumberOfCurrentHeads);
- 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;
- }
- }
- }
- KdPrint2((PRINT_PREFIX "final LunExt->opt_GeomType=%x\n", LunExt->opt_GeomType));
- 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;
- }*/
- }
- 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));
- }
- } 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
- )
- {
- LunExt->DeviceFlags &= DFLAGS_HIDDEN;
- } // end UniataForgetDevice()
- /*++
- Routine Description:
- Reset IDE controller and/or Atapi device.
- 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()\n"));
- 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;
- UCHAR tmp16;
- KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber));
- 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 channel %d\n", j));
- chan = &deviceExtension->chan[j];
- KdPrint2((PRINT_PREFIX " CompleteType %#x\n", CompleteType));
- //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
- MaxLuns = chan->NumberLuns;
- if(CompleteType != RESET_COMPLETE_NONE) {
- #ifndef UNIATA_CORE
- while((CurSrb = UniataGetCurRequest(chan))) {
- PATA_REQ AtaReq = (PATA_REQ)(CurSrb->SrbExtension);
- KdPrint2((PRINT_PREFIX "AtapiResetController: pending SRB %#x\n", CurSrb));
- // 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;
- 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 PathId = 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;
- 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;
- }
- }
- // Clear request tracking fields.
- AtaReq->WordsLeft = 0;
- AtaReq->DataBuffer = NULL;
- AtaReq->TransferLength = 0;
- ScsiPortNotification(RequestComplete,
- deviceExtension,
- CurSrb);
- // Indicate ready for next request.
- ScsiPortNotification(NextLuRequest,
- deviceExtension,
- PathId,
- TargetId,
- Lun);
- }
- if(CompleteType != RESET_COMPLETE_ALL)
- break;
- } // end while()
- #endif //UNIATA_CORE
- } // end if (!CompleteType != RESET_COMPLETE_NONE)
- // Save control flags
- ChannelCtrlFlags = chan->ChannelCtrlFlags;
- // Clear expecting interrupt flag.
- chan->ExpectingInterrupt = FALSE;
- chan->RDP = FALSE;
- chan->ChannelCtrlFlags = 0;
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
-
- // Reset controller
- if(ChipFlags & UNIATA_AHCI) {
- KdPrint2((PRINT_PREFIX " AHCI path\n"));
- UniataAhciReset(HwDeviceExtension, j);
- } else {
- KdPrint2((PRINT_PREFIX " ATA path\n"));
- KdPrint2((PRINT_PREFIX " disable intr (0)\n"));
- AtapiDisableInterrupts(deviceExtension, j);
- KdPrint2((PRINT_PREFIX " done\n"));
- switch(VendorID) {
- case ATA_INTEL_ID: {
- ULONG mask;
- 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))
- mask = mask << 8;
- else
- mask = mask << 4;
- while (timeout--) {
- AtapiStallExecution(10000);
- GetPciConfig2(0x92, tmp16);
- if ((tmp16 & mask) == mask) {
- AtapiStallExecution(10000);
- break;
- }
- }
- break; }
- case ATA_SIS_ID:
- case ATA_NVIDIA_ID: {
- KdPrint2((PRINT_PREFIX " SIS/nVidia\n"));
- if(!(ChipFlags & UNIATA_SATA))
- goto default_reset;
- break; }
- 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:
- KdPrint2((PRINT_PREFIX " send reset\n"));
- AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
- IDE_DC_RESET_CONTROLLER );
- 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);
- 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\n"));
- // Do special processing for ATAPI and IDE disk devices.
- for (i = 0; i < MaxLuns; i++) {
- // Check if device present.
- 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,
- (chan->lun[i]->DeviceFlags & DFLAGS_ATAPI_DEVICE) ?
- 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 == 0xff) {
- KdPrint2((PRINT_PREFIX
- "no drive, status %#x\n",
- statusByte));
- UniataForgetDevice(chan->lun[i]);
- } else
- // Check for ATAPI disk.
- if (chan->lun[i]->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
- // 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) {
- 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
- chan->lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
- }
- #endif //0
- // Enable interrupts, note, the 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;
- UCHAR srbStatus = SRB_STATUS_SUCCESS;
- UCHAR scsiStatus;
- ULONG DeviceNumber = GET_CDEV(Srb);
- PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
- // Read the error register.
- 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)) {
- 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
- 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);
- }
- /* 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;
- 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)) {
- 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,
- LunExt->MaximumBlockXfer, 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->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_ENAB_WCACHE, ATA_WAIT_BASE_READY);
- LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
- }
- }
- } 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) {
- 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->OrigTransferMode =
- LunExt->LimitedTransferMode =
- LunExt->TransferMode =
- (CHAR)PreferedMode;
- AtapiDmaInit__(deviceExtension, LunExt);
- LunExt->OrigTransferMode =
- 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);
- 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
- 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 DBG
- 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-1; _c++) {
- c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
- 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);
- }
- #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;
- KdPrint2((PRINT_PREFIX "Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- 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;
- }
- }
- for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
- checked[_c] = FALSE;
- }
- // fc =
- for(pass=0; pass<2; pass++) {
- for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
- c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
- if(checked[c])
- continue;
- // check non-empty and expecting interrupt channels first
- if(!pass && !deviceExtension->chan[c].ExpectingInterrupt)
- continue;
- checked[c] = TRUE;
- KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
- if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
- 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;
- }
- // 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
- )
- {
- 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;
- // 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) {
- 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;
- }
- }
- for(c=0; c<deviceExtension->NumberChannels; c++) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, 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;
- if(c >= deviceExtension->NumberChannels) {
- KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG 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, 0);
- } else {
- AtapiWritePort1(chan, IDX_IO2_o_Control,
- IDE_DC_A_4BIT );
- }
- chan->ChannelCtrlFlags &= ~CTRFLAGS_INTR_DISABLED;
- } 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,
- (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
- ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
- ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) |
- 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 {
- AtapiWritePort1(chan, IDX_IO2_o_Control,
- IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
- }
- chan->ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED;
- }
- return;
- } // end AtapiDisableInterrupts()
- /*
- 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;
- ULONG slotNumber = deviceExtension->slotNumber;
- ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
- ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
- UCHAR Channel;
- UCHAR lChannel;
- BOOLEAN DmaTransfer = FALSE;
- BOOLEAN OurInterrupt = FALSE;
- // ULONG k;
- UCHAR interruptReason;
- BOOLEAN EarlyIntr = FALSE;
- KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__:\n"));
- lChannel = c;
- Channel = (UCHAR)(deviceExtension->Channel + lChannel);
- if((ChipFlags & UNIATA_AHCI) &&
- UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, -1);
- 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:
- status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x0040);
- if(ChipFlags & PRSATA) {
- pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c);
- AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c, pr_status & 0x000000ff);
- }
- if(pr_status & (0x11 << Channel)) {
- // TODO: reset channel
- KdPrint2((PRINT_PREFIX " Promise mio unexpected + reset req\n"));
- return INTERRUPT_REASON_IGNORE;
- }
- if(!(status & (0x01 << Channel))) {
- KdPrint2((PRINT_PREFIX " Promise mio unexpected\n"));
- 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 : 2);
- /* 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\n", pr_status));
- /* 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);
- 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 {
- 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)) {
- AtapiStallExecution(1);
- }
- LunExt = chan->lun[chan->cur_cdev];
- /* if drive is busy it didn't interrupt */
- /* the exception is DCS + BSY state of ATAPI devices */
- 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 == 0xff) {
- // 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_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);
- 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 == 0xff) {
- // 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(!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);
- KdPrint2((PRINT_PREFIX " set REQ_STATE_EARLY_INTR.\n"));
- if(AtaReq) {
- AtaReq->ReqState = 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) & 0x3);
- 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;
- UCHAR Channel;
- UCHAR lChannel;
- UCHAR DeviceNumber;
- BOOLEAN DmaTransfer = FALSE;
- UCHAR error = 0;
- ULONG TimerValue = 1000;
- #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;
- 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;
- Channel = (UCHAR)(deviceExtension->Channel + lChannel);
- KdPrint2((PRINT_PREFIX " cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c));
- if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
- (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ) {
- 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_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) {
- 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) {
- 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:
- // 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 & 0xff);
- } 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(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint3((PRINT_PREFIX " AHCI branch\n"));
- } else
- if (!atapiDev) {
- // IDE
- 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 (statusByte & IDE_STATUS_BUSY) {
- //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
- KdPrint3((PRINT_PREFIX " BUSY on ATAPI device, waiting\n"));
- for(k=20; k; k--) {
- GetStatus(chan, statusByte);
- KdPrint3((PRINT_PREFIX " status re-check %#x\n", statusByte));
- KdPrint3((PRINT_PREFIX " Error reg (%#x)\n",
- AtapiReadPort1(chan, IDX_IO1_i_Error)));
- if (!(statusByte & IDE_STATUS_BUSY)) {
- KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n"));
- break;
- }
- if(k <= 18) {
- 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
- goto CallTimerDpc2;
- #else //UNIATA_CORE
- AtapiStallExecution(TimerValue);
- #endif //UNIATA_CORE
- }
- AtapiStallExecution(10);
- }
- 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 = (UCHAR)((AtaReq->ahci.in_status >> 8) && 0xff);
- } 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(!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--) {
- GetStatus(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)*/) {
- if(AtaReq->retry < MAX_RETRIES) {
- //fallback_pio:
- 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++;
- }
- KdPrint2((PRINT_PREFIX "Errors in PIO mode\n"));
- }
- }
- } else {
- interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason));
- if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) &&
- ((error >> 4) == SCSI_SENSE_HARDWARE_ERROR)) {
- if(AtaReq->retry < MAX_RETRIES) {
- //fallback_pio:
- 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,
- chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry],
- chan->lun[DeviceNumber]->BlockIoCount
- ));
- chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry]++;
- if(chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
- (deviceExtension->HwFlags & UNIATA_NO80CHK)
- ) {
- #else
- if(deviceExtension->HwFlags & UNIATA_NO80CHK) {
- #endif //IO_STATISTICS
- KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", deviceExtension->lun[DeviceNumber].TransferMode));
- deviceExtension->lun[DeviceNumber].LimitedTransferMode =
- deviceExtension->lun[DeviceNumber].TransferMode;
- }
- }
- #ifdef IO_STATISTICS
- if(AtaReq->bcount) {
- // we need stats for Read/Write operations
- chan->lun[DeviceNumber]->BlockIoCount++;
- }
- chan->lun[DeviceNumber]->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) & 0x3);
- 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 = 0x2;
- } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
- interruptReason = 0x0;
- } 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 {
- 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++) {
- GetStatus(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) ? 0x2 : 0x0;
- }
- } else {
- // Command complete - verify, write, or the SMART enable/disable.
- // Also get_media_status
- interruptReason = 0x3;
- }
- }
- }
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason, statusByte));
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint2((PRINT_PREFIX " AHCI path\n"));
- goto ReturnEnableIntr;
- } else
- if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) {
- // Write the packet.
- KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
- // Send CDB to device.
- WriteBuffer(chan, (PUSHORT)srb->Cdb, 6, 0);
- 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 == 0x0 && (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 |=
- 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);
- 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*/) {
- 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 write %#x.\n",
- interruptReason,
- srb));
- // Fail this request.
- status = SRB_STATUS_ERROR;
- goto CompleteRequest;
- }
- // Advance data buffer pointer and bytes left.
- AtaReq->DataBuffer += wordCount;
- AtaReq->WordsLeft -= wordCount;
- if (atapiDev) {
- AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
- }
- goto ReturnEnableIntr;
- } else if (interruptReason == 0x2 && (statusByte & IDE_STATUS_DRQ)) {
- if (atapiDev) {
- // Pick up bytes to transfer and convert to words.
- wordCount =
- AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow) |
- (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8);
- // Covert bytes to words.
- wordCount /= 2;
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: get R 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;
- 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)) {
- //ASSERT(AtaReq->WordsLeft == wordCount);
- 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 (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
- 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);
- }
- GetStatus(chan, statusByte);
- KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte));
- if(DataOverrun) {
- KdPrint2((PRINT_PREFIX " DataOverrun\n"));
- AtapiSuckPort2(chan);
- }
- } else {
- KdPrint2((PRINT_PREFIX
- "IdeIntr: Read %#x Dwords\n", wordCount/2));
- ReadBuffer2(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;
- goto CompleteRequest;
- }
- // Advance data buffer pointer and bytes left.
- AtaReq->DataBuffer += wordCount;
- AtaReq->WordsLeft -= wordCount;
- // Check for read command complete.
- if (AtaReq->WordsLeft == 0) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
- if (atapiDev) {
- // 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) &&
- (LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM)) {
- AtaReq->DataBuffer -= wordCount;
- if (AtaReq->DataBuffer[0] == 0x00) {
- *((ULONG *) &(AtaReq->DataBuffer[0])) = 0xFFFFFF7F;
- }
- *((ULONG *) &(AtaReq->DataBuffer[2])) = 0x00080000;
- AtaReq->DataBuffer += wordCount;
- }
- } 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;
- }
- }
- goto ReturnEnableIntr;
- } else if (interruptReason == 0x3 && !(statusByte & IDE_STATUS_DRQ)) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n"));
- // Command complete.
- if(DmaTransfer) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
- AtaReq->WordsLeft = 0;
- }
- 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(("VendorID+DeviceID/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\n"));
- // Check and see if we are processing our secret (mechanism status/request sense) srb
- if (AtaReq->OriginalSrb) {
- ULONG srbStatus;
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: OriginalSrb != NULL\n"));
- if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
- 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 { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
- PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer;
- 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
- if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) &&
- 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 {
- // last request was illegal. No point trying again
- AtapiHwInitializeChanger (HwDeviceExtension,
- srb,
- (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
- // 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) {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
- AtapiHwInitializeChanger (HwDeviceExtension,
- srb,
- (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
- 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++) {
- GetStatus(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++) {
- GetStatus(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.
- chan->ExpectingInterrupt = FALSE;
- 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) {
- 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"));
- PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
- if (status != SRB_STATUS_SUCCESS) {
- error = AtapiReadPort1(chan, IDX_IO1_i_Error);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error));
- }
- // Build the SMART status block depending upon the completion status.
- cmdOutParameters->cBufferSize = wordCount;
- cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
- cmdOutParameters->DriverStatus.bIDEError = error;
- // If the sub-command is return smart status, jam the value from cylinder low and high, into the
- // data buffer.
- if (chan->SmartCommand == RETURN_SMART_STATUS) {
- cmdOutParameters->bBuffer[0] = RETURN_SMART_STATUS;
- cmdOutParameters->bBuffer[1] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason);
- cmdOutParameters->bBuffer[2] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Unused1);
- cmdOutParameters->bBuffer[3] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
- cmdOutParameters->bBuffer[4] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh);
- cmdOutParameters->bBuffer[5] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_DriveSelect);
- cmdOutParameters->bBuffer[6] = SMART_CMD;
- cmdOutParameters->cBufferSize = 8;
- }
- // Indicate command complete.
- goto IntrCompleteReq;
- }
- } else {
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: No SRB!\n"));
- }
- if (chan->RDP) {
- // Check DSC
- for (i = 0; i < 5; i++) {
- GetStatus(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));
- }
- ReturnEnableIntr:
- KdPrint2((PRINT_PREFIX "AtapiInterrupt: ReturnEnableIntr\n",srb));
- 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
- )
- {
- PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- ULONG c = GET_CHANNEL(Srb);
- PHW_CHANNEL chan = &(deviceExtension->chan[c]);
- PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
- PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
- SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
- PIDEREGS regs = &cmdInParameters.irDriveRegs;
- // ULONG i;
- UCHAR statusByte,targetId;
- if (regs->bCommandReg != SMART_CMD) {
- KdPrint2((PRINT_PREFIX
- "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
- return SRB_STATUS_INVALID_REQUEST;
- }
- targetId = cmdInParameters.bDriveNumber;
- //TODO optimize this check
- if ((!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) ||
- (deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
- return SRB_STATUS_SELECTION_TIMEOUT;
- }
- chan->SmartCommand = regs->bFeaturesReg;
- // Determine which of the commands to carry out.
- switch(regs->bFeaturesReg) {
- case READ_ATTRIBUTES:
- case READ_THRESHOLDS:
- 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, targetId & 0x1, 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:
- 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, targetId & 0x1, 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;
- } // end switch(regs->bFeaturesReg)
- return SRB_STATUS_INVALID_REQUEST;
- } // end IdeSendSmartCommand()
- #endif //UNIATA_CORE
- ULONGLONG
- NTAPI
- UniAtaCalculateLBARegs(
- PHW_LU_EXTENSION LunExt,
- ULONG startingSector,
- PULONG max_bcount
- )
- {
- UCHAR drvSelect,sectorNumber;
- USHORT cylinder;
- ULONG tmp;
- if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
- 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)));
- }
- (*max_bcount) = 0;
- 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);;
- ULONG startingSector;
- ULONG max_bcount;
- 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 = (ULONG)(UniAtaCalculateLBARegsBack(LunExt, AtaReq->lba)) /* latest lba */ + AtaReq->bcount /* previous bcount */;
- AtaReq->bcount = (AtaReq->TransferLength - AtaReq->WordsTransfered*2 + DEV_BSIZE-1) / DEV_BSIZE;
- KdPrint2((PRINT_PREFIX "IdeReadWrite (Chained REQ): Starting sector %#x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
- startingSector,
- AtaReq->TransferLength/2,
- AtaReq->WordsTransfered,
- AtaReq->bcount));
- } else {
- AtaReq->DataBuffer = (PUSHORT)(Srb->DataBuffer);
- AtaReq->TransferLength = Srb->DataTransferLength;
- // Set up 1st block.
- MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
- MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
- KdPrint2((PRINT_PREFIX "IdeReadWrite (Orig REQ): Starting sector %#x, OrigWordsRequested %#x, DevSize %#x\n",
- 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 %#x, Number of WORDS %#x, DevSize %#x\n",
- startingSector,
- AtaReq->WordsLeft,
- AtaReq->bcount));
- AtaReq->lba = lba;
- // assume best case here
- // we cannot reinit Dma until previous request is completed
- 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(use_dma && (deviceExtension->HwFlags & UNIATA_AHCI)) {
- UniataAhciSetupCmdPtr(AtaReq);
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: 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*/ IDE_COMMAND_READ_DMA,
- lba,
- (USHORT)(AtaReq->bcount),
- 0,
- ATA_IMMEDIATE
- );
- if(!fis_size) {
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
- return SRB_STATUS_ERROR;
- }
- AtaReq->ahci.io_cmd_flags = (USHORT)(((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) |
- /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/
- (fis_size / sizeof(ULONG)) |
- (DeviceNumber << 12));
- 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(use_dma && (deviceExtension->HwFlags & UNIATA_AHCI)) {
- //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
- UniataAhciBeginTransaction(HwDeviceExtension, DeviceNumber, lChannel, Srb);
- return SRB_STATUS_PENDING;
- }
- if ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) ||
- use_dma) {
- statusByte2 = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
- cmd, lba,
- (USHORT)(AtaReq->bcount),
- // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
- 0, ATA_IMMEDIATE);
- if(statusByte2 != 0xff) {
- GetStatus(chan, statusByte2);
- }
- if(statusByte2 & IDE_STATUS_ERROR) {
- 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) {
- 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 == 0xff) {
- if(statusByte == 0xff) {
- 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.
- chan->ExpectingInterrupt = FALSE;
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- // Clear current SRB.
- UniataRemoveRequest(chan, Srb);
- return (statusByte == 0xff) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT;
- }
- chan->ExpectingInterrupt = TRUE;
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- // Write next DEV_BSIZE/2*N words.
- if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED)) {
- 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;
- // 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;
- ULONG startingSector;
- ULONG max_bcount;
- ULONG sectors;
- ULONG endSector;
- USHORT sectorCount;
- 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.
- MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
- MOV_DW_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
- KdPrint2((PRINT_PREFIX
- "IdeVerify: Starting sector %#x. Number of blocks %#x\n",
- startingSector,
- sectorCount));
- endSector = startingSector + sectorCount;
- KdPrint2((PRINT_PREFIX
- "IdeVerify: Ending sector %#x\n",
- endSector));
- if (endSector > sectors) {
- // Too big, round down.
- KdPrint2((PRINT_PREFIX
- "IdeVerify: Truncating request to %#x blocks\n",
- sectors - startingSector - 1));
- sectorCount = (USHORT)(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,
- 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 i;
- ULONG flags;
- UCHAR statusByte,byteCountLow,byteCountHigh;
- BOOLEAN use_dma = FALSE;
- BOOLEAN dma_reinited = FALSE;
- BOOLEAN retried = FALSE;
- ULONG fis_size;
- 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(("VendorID+DeviceID/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_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\n"));
- switch (Srb->Cdb[0]) {
- case SCSIOP_READ:
- case SCSIOP_WRITE:
- case SCSIOP_READ12:
- case SCSIOP_WRITE12:
- // all right
- break;
- default:
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY\n"));
- return SRB_STATUS_BUSY;
- }
- //
- if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
- !AtaReq->OriginalSrb) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
- return SRB_STATUS_BUSY;
- }
- }
- if((CmdAction & CMD_ACTION_PREPARE) &&
- (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x\n", Srb->Cdb[0]));
- // 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;
- // check if reorderable
- switch(Srb->Cdb[0]) {
- 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);
- AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
- AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
- AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE || Srb->Cdb[0] == SCSIOP_WRITE12) ?
- REQ_FLAG_WRITE : REQ_FLAG_READ;
- break;
- }
- // check if DMA read/write
- if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
- } else
- if(AtaReq->TransferLength) {
- // try use DMA
- switch(Srb->Cdb[0]) {
- case SCSIOP_WRITE:
- case SCSIOP_WRITE12:
- if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO)
- break;
- /* FALLTHROUGH */
- case SCSIOP_READ:
- case SCSIOP_READ12:
- if(deviceExtension->opt_AtapiDmaReadWrite) {
- call_dma_setup:
- 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:
- 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
- if(use_dma) {
- 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 transfer, no DMA setup\n"));
- }
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- UniataAhciSetupCmdPtr(AtaReq);
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
- RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
- RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, 16);
- fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
- &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
- IDE_COMMAND_ATAPI_PACKET /* command */,
- 0 /* lba */,
- (Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength),
- use_dma ? ATA_F_DMA : 0/* feature */,
- ATA_IMMEDIATE /* flags */
- );
- if(!fis_size) {
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
- return SRB_STATUS_ERROR;
- }
- AtaReq->ahci.io_cmd_flags = (USHORT)(((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) |
- /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/
- (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) |
- (fis_size / sizeof(ULONG)) |
- (DeviceNumber << 12));
- 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\n", use_dma));
- if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
- KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
- }
- if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
- 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) {
- 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"));
- #ifndef UNIATA_CORE
- // 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.
- 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 {
- AtaReq->Srb = AtaReq->OriginalSrb;
- AtaReq->OriginalSrb = NULL;
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiHwInitializeChanger()\n"));
- AtapiHwInitializeChanger (HwDeviceExtension, Srb,
- (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
- // fall out
- }
- }
- #endif //UNIATA_CORE
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
- 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:
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n"));
- if(use_dma) {
- chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
- } else {
- chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
- }
- UniataAhciBeginTransaction(HwDeviceExtension, DeviceNumber, lChannel, Srb);
- return SRB_STATUS_PENDING;
- }
- // Select device 0 or 1.
- 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 == 0xff) {
- 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(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.
- for (i = 0; i < 0x10000; i++) {
- GetStatus(chan, statusByte);
- if(statusByte & IDE_STATUS_DRQ) {
- AtapiReadPort2(chan, IDX_IO1_i_Data);
- } else {
- break;
- }
- }
- if (i == 0x10000) {
- make_reset:
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
- 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.
- chan->ExpectingInterrupt = 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;
- }
- statusByte = WaitOnBusy(chan);
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n",
- statusByte));
- AtapiWritePort1(chan, IDX_IO1_o_Feature,
- use_dma ? ATA_F_DMA : 0);
- // Write transfer byte count to registers.
- byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
- byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
- if (Srb->DataTransferLength >= 0x10000) {
- byteCountLow = byteCountHigh = 0xFF;
- }
- AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow);
- AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh);
- 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));
- chan->ExpectingInterrupt = TRUE;
- AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR;
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- // Write ATAPI packet command.
- AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
- return SRB_STATUS_PENDING;
- }
- // 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));
- chan->ExpectingInterrupt = TRUE;
- AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR;
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- if(g_opt_AtapiSendDisableIntr) {
- AtapiDisableInterrupts(deviceExtension, lChannel);
- }
- // Write ATAPI packet command.
- AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
- // Wait for DRQ.
- WaitOnBusy(chan);
- 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));
- // Send CDB to device.
- statusByte = WaitOnBaseBusy(chan);
- // Indicate expecting an interrupt and wait for it.
- chan->ExpectingInterrupt = TRUE;
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
- GetBaseStatus(chan, statusByte);
- if(g_opt_AtapiSendDisableIntr) {
- AtapiEnableInterrupts(deviceExtension, lChannel);
- }
- WriteBuffer(chan,
- (PUSHORT)Srb->Cdb,
- 6,
- 0);
- if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
- AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
- }
- 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;
- SetCheckPoint(4);
- UCHAR statusByte,errorByte;
- ULONG status;
- ULONG i;
- PMODE_PARAMETER_HEADER modeData;
- //ULONG ldev;
- ULONG DeviceNumber;
- PATA_REQ AtaReq;
- 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);
- SetCheckPoint(0x40);
- if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
- AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
- if(CmdAction == CMD_ACTION_PREPARE) {
- switch (Srb->Cdb[0]) {
- #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_REQUEST_SENSE:
- // all right
- KdPrint2((PRINT_PREFIX "** Ide: Command continue prep\n"));
- SetCheckPoint(50);
- break;
- default:
- 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 all TIDs but 0 and 1 since this is an IDE interface
- // which support up to two devices.
- 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 = &(chan->lun[DeviceNumber]->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 (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
- KdPrint2((PRINT_PREFIX
- "RemovableMedia\n"));
- inquiryData->RemovableMedia = 1;
- }
- // Set the Relative Addressing (LBA) bit, if applicable.
- if (chan->lun[DeviceNumber]->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->VendorId[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_MODE_SENSE:
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
- Srb->PathId, Srb->Lun, Srb->TargetId));
- // This is used to determine if the media is write-protected.
- // Since IDE does not support mode sense then we will modify just the portion we need
- // so the higher level driver can determine if media is protected.
- if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
- SelectDrive(chan, DeviceNumber);
- AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
- statusByte = WaitOnBusy(chan);
- if (!(statusByte & IDE_STATUS_ERROR)){
- // no error occured return success, media is not protected
- chan->ExpectingInterrupt = 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);
- chan->ExpectingInterrupt = 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);
- if (!(statusByte & IDE_STATUS_ERROR)){
- chan->ExpectingInterrupt = 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);
- chan->ExpectingInterrupt = FALSE;
- InterlockedExchange(&(chan->CheckIntr),
- CHECK_INTR_IDLE);
- status = SRB_STATUS_SUCCESS;
- } else {
- // Request sense buffer to be build
- chan->ExpectingInterrupt = 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;
- MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i );
- // Calculate last sector.
- if(!(i = (ULONG)chan->lun[DeviceNumber]->NumOfSectors)) {
- i = chan->lun[DeviceNumber]->IdentifyData.SectorsPerTrack *
- chan->lun[DeviceNumber]->IdentifyData.NumberOfHeads *
- chan->lun[DeviceNumber]->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,
- chan->lun[DeviceNumber]->IdentifyData.SectorsPerTrack,
- chan->lun[DeviceNumber]->IdentifyData.NumberOfHeads,
- chan->lun[DeviceNumber]->IdentifyData.NumberOfCylinders));
- status = SRB_STATUS_SUCCESS;
- break;
- case SCSIOP_VERIFY:
- 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:
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
- (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ",
- Srb->PathId, Srb->Lun, Srb->TargetId));
- AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
- AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE) ? REQ_FLAG_WRITE : REQ_FLAG_READ;
- status = IdeReadWrite(HwDeviceExtension,
- Srb, CmdAction);
- break;
- case SCSIOP_START_STOP_UNIT:
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
- Srb->PathId, Srb->Lun, Srb->TargetId));
- //Determine what type of operation we should perform
- cdb = (PCDB)Srb->Cdb;
- if (cdb->START_STOP.LoadEject == 1){
- statusByte = WaitOnBaseBusy(chan);
- // Eject media,
- // first select device 0 or 1.
- SelectDrive(chan, DeviceNumber);
- AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
- }
- status = SRB_STATUS_SUCCESS;
- break;
- case SCSIOP_MEDIUM_REMOVAL:
- cdb = (PCDB)Srb->Cdb;
- statusByte = WaitOnBaseBusy(chan);
- SelectDrive(chan, DeviceNumber);
- if (cdb->MEDIA_REMOVAL.Prevent == TRUE) {
- AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
- } else {
- AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
- }
- status = SRB_STATUS_SUCCESS;
- break;
- // 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.
- #if 0
- 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 (chan->lun[DeviceNumber]->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]);
- lChannel = Srb->TargetId >> 1;
- regs->bDriveHeadReg &= 0x0f;
- regs->bDriveHeadReg |= (UCHAR) (((Srb->TargetId & 0x1) << 4) | 0xA0);
- if((regs->bOpFlags & 1) == 0) { // execute ATA command
- KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
- Srb->PathId, Srb->Lun, Srb->TargetId));
- AtapiDisableInterrupts(deviceExtension, lChannel);
- if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) {
- if((chan->lun[Srb->TargetId & 0x1]->LimitedTransferMode >= ATA_DMA)) {
- use_dma = TRUE;
- // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
- if(!AtapiDmaSetup(HwDeviceExtension, Srb->TargetId & 0x1, lChannel, Srb,
- (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((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, (Srb->TargetId & 0x1), lChannel, Srb);
- }
- ScsiPortStallExecution(1); // wait for busy to be set
- if(regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) {
- to_lim = Srb->TimeOutValue;
- } else {
- if(Srb->TimeOutValue <= 2) {
- to_lim = Srb->TimeOutValue*900;
- } else {
- to_lim = (Srb->TimeOutValue*999) - 500;
- }
- }
- for(i=0; i<to_lim;i+=2) { // 2 msec from WaitOnBaseBusy()
- statusByte = WaitOnBaseBusy(chan); // wait for busy to be clear, up to 2 msec
- GetBaseStatus(chan, statusByte);
- if(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, (Srb->TargetId & 0x1), 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;
- }
- AtapiEnableInterrupts(deviceExtension, lChannel);
- } else { // read task register
- regs = (PIDEREGS_EX) Srb->DataBuffer;
- regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
- if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command
- regs->bFeaturesReg = AtapiReadPort1(chan, IDX_IO1_i_Error);
- regs->bSectorCountReg = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
- regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
- regs->bCylLowReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- regs->bCylHighReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
- } else {
- regs->bFeaturesReg = AtapiReadPort1(chan, IDX_IO1_i_Error);
- regs->bFeaturesRegH = AtapiReadPort1(chan, IDX_IO1_i_Error);
- regs->bSectorCountReg = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
- regs->bSectorCountRegH = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
- regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
- regs->bSectorNumberRegH= AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
- regs->bCylLowReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- regs->bCylLowRegH = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- regs->bCylHighReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
- regs->bCylHighRegH = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
- }
- regs->bCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status);
- status = SRB_STATUS_SUCCESS;
- }
- break;
- }
- default:
- 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]);
- if (EnableMSN == TRUE){
- // 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 == TRUE
- // 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 PathId
- )
- {
- ULONG i;
- AtapiDisableInterrupts(deviceExtension, PathId);
- if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
- KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n"));
- AtapiSoftReset(&(deviceExtension->chan[PathId]), LunExt->Lun);
- } else {
- KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
- AtapiResetController__(deviceExtension, PathId, RESET_COMPLETE_NONE);
- for(i=0; i<deviceExtension->NumberLuns; i++) {
- deviceExtension->chan[PathId].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
- }
- }
- LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
- AtapiEnableInterrupts(deviceExtension, PathId);
- 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.
- 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));
- }
- do {
- lChannel = GET_CHANNEL(Srb);
- //ldev = GET_LDEV(Srb);
- chan = NULL;
- LunExt = NULL;
- DeviceNumber = GET_CDEV(Srb);
- //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 " VendorID+DeviceID/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))
- ) {
- KdPrint2((PRINT_PREFIX
- "AtapiStartIo: Communication port\n"));
- if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
- 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;
- //}
- }
- 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;
- //}
- }
- }
- /*
- __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\n"));
- 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)) {
- KdPrint3((PRINT_PREFIX "Try ATAPI send\n"));
- 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_SHUTDOWN:
- case SRB_FUNCTION_FLUSH:
- // Flush device's cache.
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Device flush received\n"));
- if (chan->CurrentSrb) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo (SRB_FUNCTION_FLUSH): Already have a request!\n"));
- Srb->SrbStatus = SRB_STATUS_BUSY;
- ScsiPortNotification(RequestComplete,
- deviceExtension,
- Srb);
- return FALSE;
- }
- if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
- status = SRB_STATUS_SUCCESS;
- } else {
- status = AtaCommand(deviceExtension, GET_CDEV(Srb), GET_CHANNEL(Srb),
- IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR);
- if (status & IDE_STATUS_DRQ) {
- status = SRB_STATUS_SUCCESS;
- } else {
- status = SRB_STATUS_SELECTION_TIMEOUT;
- }
- }
- 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)) {
- switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
- case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
- PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
- UCHAR deviceNumber;
- KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
- // 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);
- // This is done because of how the IOCTL_SCSI_MINIPORT
- // determines 'targetid's'. Disk.sys places the real target id value
- // in the DeviceMap field. Once we do some parameter checking, the value passed
- // back to the application will be determined.
- deviceNumber = versionParameters->bIDEDeviceMap;
- if(commPort) {
- KdPrint2((PRINT_PREFIX
- "AtapiStartIo: SCSIDISK IOCTL for commPort -> 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;
- }
- if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) ||
- atapiDev) {
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
- }
- // 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 (deviceExtension->NumberChannels == 1) {
- if (chan->PrimaryAddress) {
- deviceNumber = 1 << DeviceNumber;
- } else {
- deviceNumber = 4 << DeviceNumber;
- }
- } else {
- deviceNumber = (1 << DeviceNumber) << lChannel;
- }
- versionParameters->bIDEDeviceMap = deviceNumber;
- 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));
- UCHAR targetId;
- KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
- // Extract the target.
- targetId = cmdInParameters.bDriveNumber;
- KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
- if((targetId >= deviceExtension->NumberChannels*2) ||
- !(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
- KdPrint2((PRINT_PREFIX "Error: xxx_ID_CMD for non-existant device\n"));
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
- }
- switch(cmdInParameters.irDriveRegs.bCommandReg) {
- case ID_CMD:
- if((deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
- KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n"));
- status = SRB_STATUS_INVALID_REQUEST;
- break;
- }
- /* FALL THROUGH */
- case ATAPI_ID_CMD:
- if(!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
- (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) {
- KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n"));
- status = SRB_STATUS_INVALID_REQUEST;
- break;
- }
- 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, &deviceExtension->lun[targetId].IdentifyData,
- cmdOutParameters->cBufferSize);
- 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:
- if(commPort) {
- KdPrint2((PRINT_PREFIX
- "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
- // Indicate no device found at this address.
- KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
- }
- 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);
- }
- break;
- 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;
- //chan = &(deviceExtension->chan[lChannel]);
- 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(!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(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));
- LunExt->DeviceFlags = 0;
- if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n"));
- LunExt->DeviceFlags |= DFLAGS_HIDDEN;
- }
- 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(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"));
- AtaCtl->GetMode.OrigMode = LunExt->OrigTransferMode;
- AtaCtl->GetMode.MaxMode = LunExt->LimitedTransferMode;
- AtaCtl->GetMode.CurrentMode = LunExt->TransferMode;
- status = SRB_STATUS_SUCCESS;
- break;
- }
- case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION: {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n"));
- 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"));
- AtaCtl->AdapterInfo.HeaderLength = FIELD_OFFSET(ADAPTERINFO, Chan);
- if(len < AtaCtl->AdapterInfo.HeaderLength + sizeof(AtaCtl->AdapterInfo.Chan)) {
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", len,
- AtaCtl->AdapterInfo.HeaderLength + sizeof(AtaCtl->AdapterInfo.Chan)));
- status = SRB_STATUS_DATA_OVERRUN;
- break;
- }
- 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;
- RtlZeroMemory(&AtaCtl->AdapterInfo.Chan, sizeof(AtaCtl->AdapterInfo.Chan));
- 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;
- AtapiDmaDBSync(chan, Srb);
- UniataRemoveRequest(chan, Srb);
- // Indicate command complete.
- ScsiPortNotification(RequestComplete,
- deviceExtension,
- Srb);
- // 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;
- }
- }
- 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__()
- 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:
- KdPrint2((PRINT_PREFIX "DMA "));
- flags |= ATA_CMD_FLAG_DMA;
- }
- switch(command) {
- 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_WRITE_FUA_DMA48:
- case IDE_COMMAND_WRITE_FUA_DMA_Q48:
- case IDE_COMMAND_WRITE_MUL_FUA48:
- 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;
- }
- 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;
- }
- KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
- AtaCommands48[i] = command;
- AtaCommandFlags[i] = flags;
- }
- } // end UniataInitAtaCommands()
- /*++
- 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;
- 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;
- LARGE_INTEGER t0, t1;
- Connect_DbgPrint();
- KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string));
- a = (WCHAR)strlen(ver_string);
- g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0);
- if(g_opt_Verbose) {
- _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR "\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;
- #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;
- }
- #endif // USE_REACTOS_DDK
- KdPrint(("UniATA Init: OS ver %x.%x (%d)\n", MajorVersion, MinorVersion, BuildNumber));
- 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
- 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;
- // 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\nATAPI IDE enum supported BusMaster Devices\n"));
- 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
- UniataEnumBusMasterController(DriverObject, Argument2);
- switch(g_opt_VirtualMachine) {
- case VM_VBOX:
- // adjust options for VirtualBox
- g_opt_WaitBusyCount = 20000;
- g_opt_WaitBusyDelay = 150;
- g_opt_WaitDrqDelay = 100;
- g_opt_AtapiSendDisableIntr = 0;
- g_opt_AtapiDmaRawRead = FALSE;
- break;
- }
- 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_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr); // 1 vs 0
- g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead); // 1 vs 0
- }
- // 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(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
- 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;
- 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++) {
- 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 ? 0x80000000 : 0)));
- KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
- if (newStatus < statusToReturn) {
- statusToReturn = newStatus;
- }
- if (newStatus == STATUS_SUCCESS) {
- BMList[i].ChanInitOk |= 0x01 << c;
- /*
- 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 doesn't work under higher OSes
- KdPrint2((PRINT_PREFIX "make still one attempt\n"));
- continue;
- }
- if(BMList[i].ChanInitOk & 0x03) {
- // under NT we receive status immediately, so
- // we can omit alternative init method id STATUS_SUCCESS returned
- KdPrint2((PRINT_PREFIX "Ok, no more retries required\n"));
- break;
- }
- // if (WinVer_Id() == WinVer_NT) and some error occured
- // try alternative init method
- } // for(alt...)
- #if 0
- if(WinVer_WDM_Model) {
- hwInitializationData.comm.HwFindAdapter = UniataFindFakeBusMasterController;
- hwInitializationData.comm.NumberOfAccessRanges = 5;
- hwInitializationData.comm.AdapterInterfaceType = PCIBus;
- hwInitializationData.comm.VendorId = BMList[i].VendorId;
- hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
- hwInitializationData.comm.DeviceId = BMList[i].DeviceId;
- hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
- //BMList[i].channel = 0/*(UCHAR)c*/;
- KdPrint2((PRINT_PREFIX "Try init fake: %4.4s %4.4s \n",
- hwInitializationData.comm.VendorId,
- hwInitializationData.comm.DeviceId));
- newStatus = ScsiPortInitialize(DriverObject,
- Argument2,
- &hwInitializationData.comm,
- (PVOID)i);
- KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
- }
- #endif //0
- if(g_opt_Verbose) {
- if(BMList[i].ChanInitOk & 0x03) {
- _PrintNtConsole(" OK\n");
- } 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(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", 0)) {
- 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 = BMList[i].VendorId;
- hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
- hwInitializationData.comm.DeviceId = BMList[i].DeviceId;
- hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
- BMList[i].channel = 0/*(UCHAR)c*/;
- KdPrint2((PRINT_PREFIX "Try init %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;
- // 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 = AtapiFindController;
- 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);
- 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);
- 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;
- // <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);
- KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
- ExFreePool(paramPath.Buffer);
- if(!NT_SUCCESS(status)) {
- 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);
- 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
- );
- extern "C"
- VOID
- _cdecl
- _PrintNtConsole(
- PCCH DebugMessage,
- ...
- )
- {
- int len;
- UCHAR dbg_print_tmp_buff[512];
- // UNICODE_STRING msgBuff;
- va_list ap;
- va_start(ap, DebugMessage);
- len = _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], 511, DebugMessage, ap);
- dbg_print_tmp_buff[511] = 0;
- KdPrint(((PCHAR)&(dbg_print_tmp_buff[0])));
- HalDisplayString(dbg_print_tmp_buff);
- va_end(ap);
- } // end PrintNtConsole()