ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

id_ata.cpp
Go to the documentation of this file.
00001 /*++
00002 
00003 Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
00004 
00005 Module Name:
00006     id_ata.cpp
00007 
00008 Abstract:
00009     This is the miniport driver for ATA/ATAPI IDE controllers
00010     with Busmaster DMA and Serial ATA support
00011 
00012 Author:
00013     Alexander A. Telyatnikov (Alter)
00014 
00015 Environment:
00016     kernel mode only
00017 
00018 Notes:
00019 
00020     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00021     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00022     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00023     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00024     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00025     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00026     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00027     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00029     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 
00031 Revision History:
00032 
00033     The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
00034          Mike Glass (MGlass)
00035          Chuck Park (ChuckP)
00036 
00037     Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
00038          Søren Schmidt, Copyright (c) 1998-2007
00039 
00040     All parts of code are greatly changed/updated by
00041          Alter, Copyright (c) 2002-2007:
00042 
00043     1. Internal command queueing/reordering
00044     2. Drive identification
00045     3. Support for 2 _independent_ channels in a single PCI device
00046     4. Smart host<->drive transfer rate slowdown (for bad cable)
00047     5. W2k support (binary compatibility)
00048     6. HDD hot swap under NT4
00049     7. XP support (binary compatibility)
00050     8. Serial ATA (SATA/SATA2) support
00051     9. NT 3.51 support (binary compatibility)
00052 
00053     etc. (See todo.txt)
00054 
00055 
00056 --*/
00057 
00058 #include "stdafx.h"
00059 
00060 #ifndef UNIATA_CORE
00061 
00062 static const CHAR ver_string[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR "\n";
00063 
00064 static const CHAR uniata_comm_name[] = UNIATA_COMM_PORT_VENDOR_STR "    \n";
00065 
00066 UNICODE_STRING SavedRegPath;
00067 WCHAR SavedRegPathBuffer[256];
00068 
00069 #endif //UNIATA_CORE
00070 
00071 UCHAR AtaCommands48[256];
00072 UCHAR AtaCommandFlags[256];
00073 
00074 ULONG  SkipRaids = 1;
00075 ULONG  ForceSimplex = 0;
00076 
00077 LONGLONG g_Perf = 0;
00078 ULONG    g_PerfDt = 0;
00079 
00080 #ifdef _DEBUG
00081 ULONG  g_LogToDisplay = 0;
00082 #endif //_DEBUG
00083 
00084 ULONG  g_WaitBusyInISR = 1;
00085 
00086 ULONG  g_opt_WaitBusyCount = 200; // 20000
00087 ULONG  g_opt_WaitBusyDelay = 10;  // 150
00088 ULONG  g_opt_WaitDrqDelay  = 10; // 100
00089 BOOLEAN g_opt_AtapiSendDisableIntr = 1; // 0
00090 BOOLEAN g_opt_AtapiDmaRawRead = 1; // 0
00091 
00092 ULONG g_opt_VirtualMachine = 0; // Auto
00093 
00094 BOOLEAN InDriverEntry = TRUE;
00095 
00096 BOOLEAN g_opt_Verbose = 0;
00097 
00098 BOOLEAN WinVer_WDM_Model = FALSE;
00099 
00100 //UCHAR EnableDma = FALSE;
00101 //UCHAR EnableReorder = FALSE;
00102 
00103 UCHAR g_foo = 0;
00104 
00105 BOOLEAN
00106 NTAPI
00107 AtapiResetController__(
00108     IN PVOID HwDeviceExtension,
00109     IN ULONG PathId,
00110     IN UCHAR CompleteType
00111     );
00112 
00113 VOID
00114 NTAPI
00115 AtapiHwInitialize__(
00116     IN PHW_DEVICE_EXTENSION deviceExtension,
00117     IN ULONG lChannel
00118     );
00119 
00120 #define RESET_COMPLETE_CURRENT  0x00
00121 #define RESET_COMPLETE_ALL      0x01
00122 #define RESET_COMPLETE_NONE     0x02
00123 
00124 #ifndef UNIATA_CORE
00125 
00126 VOID
00127 NTAPI
00128 AtapiCallBack_X(
00129     IN PVOID HwDeviceExtension
00130     );
00131 
00132 #ifdef UNIATA_USE_XXableInterrupts
00133   #define RETTYPE_XXableInterrupts   BOOLEAN
00134   #define RETVAL_XXableInterrupts    TRUE
00135 #else
00136   #define RETTYPE_XXableInterrupts   VOID
00137   #define RETVAL_XXableInterrupts
00138 #endif
00139 
00140 RETTYPE_XXableInterrupts
00141 NTAPI
00142 AtapiInterruptDpc(
00143     IN PVOID HwDeviceExtension
00144     );
00145 
00146 RETTYPE_XXableInterrupts
00147 NTAPI
00148 AtapiEnableInterrupts__(
00149     IN PVOID HwDeviceExtension
00150     );
00151 
00152 VOID
00153 NTAPI
00154 AtapiQueueTimerDpc(
00155     IN PVOID HwDeviceExtension,
00156     IN ULONG lChannel,
00157     IN PHW_TIMER HwScsiTimer,
00158     IN ULONG MiniportTimerValue
00159     );
00160 
00161 SCSI_ADAPTER_CONTROL_STATUS
00162 NTAPI
00163 AtapiAdapterControl(
00164     IN PVOID HwDeviceExtension,
00165     IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
00166     IN PVOID Parameters
00167     );
00168 
00169 #endif //UNIATA_CORE
00170 
00171 #ifndef UNIATA_CORE
00172 
00173 BOOLEAN
00174 NTAPI
00175 AtapiRegGetStringParameterValue(
00176     IN PWSTR RegistryPath,
00177     IN PWSTR Name,
00178     IN PWCHAR Str,
00179     IN ULONG MaxLen
00180     )
00181 {
00182 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched 
00183     NTSTATUS          status;
00184     RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
00185     UNICODE_STRING ustr;
00186 
00187     ustr.Buffer = Str;
00188     ustr.Length =
00189     ustr.MaximumLength = (USHORT)MaxLen;
00190     RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
00191 
00192     parameters[0].Flags         = RTL_QUERY_REGISTRY_DIRECT;
00193     parameters[0].Name          = Name;
00194     parameters[0].EntryContext  = &ustr;
00195     parameters[0].DefaultType   = REG_SZ;
00196     parameters[0].DefaultData   = Str;
00197     parameters[0].DefaultLength = MaxLen;
00198 
00199     status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
00200                                     RegistryPath, parameters, NULL, NULL);
00201 
00202     if(!NT_SUCCESS(status))
00203         return FALSE;
00204 
00205     return TRUE;
00206 
00207 #undef ITEMS_TO_QUERY
00208 } // end AtapiRegGetStringParameterValue()
00209 
00210 
00211 #endif //UNIATA_CORE
00212 
00213 VOID
00214 DDKFASTAPI
00215 UniataNanoSleep(
00216     ULONG nano
00217     )
00218 {
00219     LONGLONG t;
00220     LARGE_INTEGER t0;
00221 
00222 #ifdef NAVO_TEST
00223     return;
00224 #endif //NAVO_TEST
00225 
00226     if(!nano || !g_Perf || !g_PerfDt)
00227         return;
00228     t = (g_Perf * nano) / g_PerfDt / 1000;
00229     if(!t) {
00230         t = 1;
00231     }
00232     do {
00233         KeQuerySystemTime(&t0);
00234         t--;
00235     } while(t);
00236 } // end UniataNanoSleep()
00237 
00238 #define AtapiWritePortN_template(_type, _Type, sz) \
00239 VOID \
00240 DDKFASTAPI \
00241 AtapiWritePort##sz( \
00242     IN PHW_CHANNEL chan, \
00243     IN ULONGIO_PTR _port, \
00244     IN _type  data \
00245     ) \
00246 { \
00247     PIORES res; \
00248     if(_port >= IDX_MAX_REG) { \
00249         res = (PIORES)(_port);  \
00250     } else \
00251     if(chan) { \
00252         res = &chan->RegTranslation[_port];  \
00253     } else {                                     \
00254         KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
00255         return; \
00256     } \
00257     if(res->Proc) {             \
00258     } else  \
00259     if(!res->MemIo) {             \
00260         ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
00261     } else {                                      \
00262         /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
00263         ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
00264     }                                                        \
00265     return;                                                  \
00266 }
00267 
00268 AtapiWritePortN_template(ULONG,  Ulong,  4);
00269 AtapiWritePortN_template(USHORT, Ushort, 2);
00270 AtapiWritePortN_template(UCHAR,  Uchar,  1);
00271 
00272 #define AtapiWritePortExN_template(_type, _Type, sz) \
00273 VOID \
00274 DDKFASTAPI \
00275 AtapiWritePortEx##sz( \
00276     IN PHW_CHANNEL chan, \
00277     IN ULONGIO_PTR _port, \
00278     IN ULONG offs, \
00279     IN _type  data \
00280     ) \
00281 { \
00282     PIORES res; \
00283     if(_port >= IDX_MAX_REG) { \
00284         res = (PIORES)(_port);  \
00285     } else \
00286     if(chan) { \
00287         res = &chan->RegTranslation[_port];  \
00288     } else {                                     \
00289         KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
00290         return; \
00291     } \
00292     if(res->Proc) {             \
00293     } else  \
00294     if(!res->MemIo) {             \
00295         ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
00296     } else {                                      \
00297         /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
00298         ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
00299     }                                                        \
00300     return;                                                  \
00301 }
00302 
00303 AtapiWritePortExN_template(ULONG,  Ulong,  4);
00304 //AtapiWritePortExN_template(USHORT, Ushort, 2);
00305 AtapiWritePortExN_template(UCHAR,  Uchar,  1);
00306 
00307 #define AtapiReadPortN_template(_type, _Type, sz) \
00308 _type \
00309 DDKFASTAPI \
00310 AtapiReadPort##sz( \
00311     IN PHW_CHANNEL chan, \
00312     IN ULONGIO_PTR _port \
00313     ) \
00314 { \
00315     PIORES res; \
00316     if(_port >= IDX_MAX_REG) { \
00317         res = (PIORES)(_port);  \
00318     } else \
00319     if(chan) { \
00320         res = &chan->RegTranslation[_port];  \
00321     } else {                                     \
00322         KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
00323         return (_type)(-1); \
00324     } \
00325     if(res->Proc) {             \
00326         return 0; \
00327     } else  \
00328     if(!res->MemIo) {             \
00329         /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
00330         return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
00331     } else {                                      \
00332         /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
00333         return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
00334     }                                                        \
00335 }
00336 
00337 AtapiReadPortN_template(ULONG,  Ulong,  4);
00338 AtapiReadPortN_template(USHORT, Ushort, 2);
00339 AtapiReadPortN_template(UCHAR,  Uchar,  1);
00340 
00341 #define AtapiReadPortExN_template(_type, _Type, sz) \
00342 _type \
00343 DDKFASTAPI \
00344 AtapiReadPortEx##sz( \
00345     IN PHW_CHANNEL chan, \
00346     IN ULONGIO_PTR _port, \
00347     IN ULONG offs \
00348     ) \
00349 { \
00350     PIORES res; \
00351     if(_port >= IDX_MAX_REG) { \
00352         res = (PIORES)(_port);  \
00353     } else \
00354     if(chan) { \
00355         res = &chan->RegTranslation[_port];  \
00356     } else {                                     \
00357         KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
00358         return (_type)(-1); \
00359     } \
00360     if(res->Proc) {             \
00361         return 0; \
00362     } else  \
00363     if(!res->MemIo) {             \
00364         return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
00365     } else {                                      \
00366         /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
00367         return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
00368     }                                                        \
00369 }
00370 
00371 AtapiReadPortExN_template(ULONG,  Ulong,  4);
00372 //AtapiReadPortExN_template(USHORT, Ushort, 2);
00373 AtapiReadPortExN_template(UCHAR,  Uchar,  1);
00374 
00375 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
00376 VOID \
00377 DDKFASTAPI \
00378 AtapiReadBuffer##sz( \
00379     IN PHW_CHANNEL chan, \
00380     IN ULONGIO_PTR _port, \
00381     IN PVOID Buffer, \
00382     IN ULONG Count,   \
00383     IN ULONG Timing   \
00384     ) \
00385 { \
00386     PIORES res; \
00387                  \
00388     if(Timing) { \
00389         while(Count) { \
00390             (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
00391             Count--; \
00392             Buffer = ((_type*)Buffer)+1; \
00393             UniataNanoSleep(Timing); \
00394         } \
00395         return; \
00396     } \
00397            \
00398     if(_port >= IDX_MAX_REG) { \
00399         res = (PIORES)(_port);  \
00400     } else \
00401     if(chan) { \
00402         res = &chan->RegTranslation[_port];  \
00403     } else {                                     \
00404         KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
00405         return; \
00406     } \
00407     if(!res->MemIo) {             \
00408         /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
00409         ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
00410         return; \
00411     }                                                        \
00412     while(Count) { \
00413         (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
00414         Count--; \
00415         Buffer = ((_type*)Buffer)+1; \
00416     } \
00417     return;                                                  \
00418 }
00419 
00420 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
00421 VOID \
00422 DDKFASTAPI \
00423 AtapiWriteBuffer##sz( \
00424     IN PHW_CHANNEL chan, \
00425     IN ULONGIO_PTR _port, \
00426     IN PVOID Buffer, \
00427     IN ULONG Count,   \
00428     IN ULONG Timing   \
00429     ) \
00430 { \
00431     PIORES res; \
00432                  \
00433     if(Timing) { \
00434         while(Count) { \
00435             AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
00436             Buffer = ((_type*)Buffer)+1; \
00437             Count--; \
00438             UniataNanoSleep(Timing); \
00439         } \
00440         return;                                                  \
00441     } \
00442            \
00443     if(_port >= IDX_MAX_REG) { \
00444         res = (PIORES)(_port);  \
00445     } else \
00446     if(chan) { \
00447         res = &chan->RegTranslation[_port];  \
00448     } else {                                     \
00449         KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
00450         return; \
00451     } \
00452     if(!res->MemIo) {             \
00453         /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
00454         ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
00455         return; \
00456     }                                                        \
00457     while(Count) { \
00458         ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
00459         Count--; \
00460         Buffer = ((_type*)Buffer)+1; \
00461     } \
00462     return;                                                  \
00463 }
00464 
00465 AtapiWritePortBufferN_template(ULONG,  Ulong,  4);
00466 AtapiWritePortBufferN_template(USHORT, Ushort, 2);
00467 
00468 AtapiReadPortBufferN_template(ULONG,  Ulong,  4);
00469 AtapiReadPortBufferN_template(USHORT, Ushort, 2);
00470 
00471 
00472 UCHAR
00473 DDKFASTAPI
00474 AtapiSuckPort2(
00475     IN PHW_CHANNEL chan
00476     )
00477 {
00478     UCHAR statusByte;
00479     ULONG i;
00480 
00481     WaitOnBusyLong(chan);
00482     for (i = 0; i < 0x10000; i++) {
00483 
00484         GetStatus(chan, statusByte);
00485         if (statusByte & IDE_STATUS_DRQ) {
00486             // Suck out any remaining bytes and throw away.
00487             AtapiReadPort2(chan, IDX_IO1_i_Data);
00488         } else {
00489             break;
00490         }
00491     }
00492     if(i) {
00493         KdPrint2((PRINT_PREFIX "AtapiSuckPort2: overrun detected (%#x words)\n", i ));
00494     }
00495     return statusByte;
00496 } // AtapiSuckPort2()
00497 
00498 UCHAR
00499 DDKFASTAPI
00500 WaitOnBusy(
00501     IN PHW_CHANNEL   chan
00502     )
00503 {
00504     ULONG i;
00505     UCHAR Status;
00506     for (i=0; i<200; i++) {
00507         GetStatus(chan, Status);
00508         if (Status & IDE_STATUS_BUSY) {
00509             AtapiStallExecution(10);
00510             continue;
00511         } else {
00512             break;
00513         }
00514     }
00515     return Status;
00516 } // end WaitOnBusy()
00517 
00518 UCHAR
00519 DDKFASTAPI
00520 WaitOnBusyLong(
00521     IN PHW_CHANNEL   chan
00522     )
00523 {
00524     ULONG i;
00525     UCHAR Status;
00526 
00527     Status = WaitOnBusy(chan);
00528     if(!(Status & IDE_STATUS_BUSY))
00529         return Status;
00530     for (i=0; i<2000; i++) {
00531         GetStatus(chan, Status);
00532         if (Status & IDE_STATUS_BUSY) {
00533             AtapiStallExecution(250);
00534             continue;
00535         } else {
00536             break;
00537         }
00538     }
00539     return Status;
00540 } // end WaitOnBusyLong()
00541 
00542 UCHAR
00543 DDKFASTAPI
00544 WaitOnBaseBusy(
00545     IN PHW_CHANNEL   chan
00546     )
00547 {
00548     ULONG i;
00549     UCHAR Status = 0xff;
00550     for (i=0; i<g_opt_WaitBusyCount; i++) {
00551         GetBaseStatus(chan, Status);
00552         if (Status & IDE_STATUS_BUSY) {
00553             AtapiStallExecution(g_opt_WaitBusyDelay);
00554             continue;
00555         } else {
00556             break;
00557         }
00558     }
00559     return Status;
00560 } // end WaitOnBaseBusy()
00561 
00562 UCHAR
00563 DDKFASTAPI
00564 WaitOnBaseBusyLong(
00565     IN PHW_CHANNEL   chan
00566     )
00567 {
00568     ULONG i;
00569     UCHAR Status;
00570 
00571     Status = WaitOnBaseBusy(chan);
00572     if(!(Status & IDE_STATUS_BUSY))
00573         return Status;
00574     for (i=0; i<2000; i++) {
00575         GetBaseStatus(chan, Status);
00576         if (Status & IDE_STATUS_BUSY) {
00577             AtapiStallExecution(250);
00578             continue;
00579         } else {
00580             break;
00581         }
00582     }
00583     return Status;
00584 } // end WaitOnBaseBusyLong()
00585 
00586 UCHAR
00587 DDKFASTAPI
00588 UniataIsIdle(
00589     IN struct _HW_DEVICE_EXTENSION* deviceExtension,
00590     IN UCHAR Status
00591     )
00592 {
00593     UCHAR Status2;
00594 
00595     if(Status == 0xff) {
00596         return 0xff;
00597     }
00598     if(Status & IDE_STATUS_BUSY) {
00599         return Status;
00600     }
00601 //    if(deviceExtension->HwFlags & UNIATA_SATA) {
00602     if(UniataIsSATARangeAvailable(deviceExtension, 0)) {
00603         if(Status & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
00604             return Status;
00605         }
00606     } else {
00607         Status2 = Status & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX);
00608         if ((Status & IDE_STATUS_BUSY) ||
00609             (Status2 != IDE_STATUS_IDLE && Status2 != IDE_STATUS_DRDY)) {
00610             return Status;
00611         }
00612     }
00613     return IDE_STATUS_IDLE;
00614 } // end UniataIsIdle()
00615 
00616 UCHAR
00617 DDKFASTAPI
00618 WaitForIdleLong(
00619     IN PHW_CHANNEL   chan
00620     )
00621 {
00622     ULONG i;
00623     UCHAR Status;
00624     UCHAR Status2;
00625     for (i=0; i<20000; i++) {
00626         GetStatus(chan, Status);
00627         Status2 = UniataIsIdle(chan->DeviceExtension, Status);
00628         if(Status2 == 0xff) {
00629             // no drive ?
00630             break;
00631         } else
00632         if(Status2 & IDE_STATUS_BUSY) {
00633             AtapiStallExecution(10);
00634             continue;
00635         } else {
00636             break;
00637         }
00638     }
00639     return Status;
00640 } // end WaitForIdleLong()
00641 
00642 UCHAR
00643 DDKFASTAPI
00644 WaitForDrq(
00645     IN PHW_CHANNEL   chan
00646     )
00647 {
00648     ULONG i;
00649     UCHAR Status;
00650     for (i=0; i<1000; i++) {
00651         GetStatus(chan, Status);
00652         if (Status & IDE_STATUS_BUSY) {
00653             AtapiStallExecution(g_opt_WaitDrqDelay);
00654         } else if (Status & IDE_STATUS_DRQ) {
00655             break;
00656         } else {
00657             AtapiStallExecution(g_opt_WaitDrqDelay*2);
00658         }
00659     }
00660     return Status;
00661 } // end WaitForDrq()
00662 
00663 UCHAR
00664 DDKFASTAPI
00665 WaitShortForDrq(
00666     IN PHW_CHANNEL   chan
00667     )
00668 {
00669     ULONG i;
00670     UCHAR Status;
00671     for (i=0; i<2; i++) {
00672         GetStatus(chan, Status);
00673         if (Status & IDE_STATUS_BUSY) {
00674             AtapiStallExecution(g_opt_WaitDrqDelay);
00675         } else if (Status & IDE_STATUS_DRQ) {
00676             break;
00677         } else {
00678             AtapiStallExecution(g_opt_WaitDrqDelay);
00679         }
00680     }
00681     return Status;
00682 } // end WaitShortForDrq()
00683 
00684 VOID
00685 DDKFASTAPI
00686 AtapiSoftReset(
00687     IN PHW_CHANNEL   chan,
00688     ULONG            DeviceNumber
00689     )
00690 {
00691     //ULONG c = chan->lChannel;
00692     ULONG i = 30 * 1000;
00693     UCHAR dma_status = 0;
00694     KdPrint2((PRINT_PREFIX "AtapiSoftReset:\n"));
00695     UCHAR statusByte2;
00696 
00697     if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
00698         UniataAhciSoftReset(chan->DeviceExtension, chan->lChannel, DeviceNumber);
00699         return;
00700     }
00701 
00702     GetBaseStatus(chan, statusByte2);
00703     KdPrint2((PRINT_PREFIX "  statusByte2 %x:\n", statusByte2));
00704     SelectDrive(chan, DeviceNumber);
00705     AtapiStallExecution(500);
00706     AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
00707 
00708     // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
00709     // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
00710     // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
00711     // implementation. (which is around 1 second)
00712     while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
00713            i--)
00714     {
00715         AtapiStallExecution(30);
00716     }
00717 
00718     SelectDrive(chan, DeviceNumber);
00719     WaitOnBusy(chan);
00720     GetBaseStatus(chan, statusByte2);
00721     AtapiStallExecution(500);
00722 
00723     GetBaseStatus(chan, statusByte2);
00724     if(chan && chan->DeviceExtension) {
00725         dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
00726         KdPrint2((PRINT_PREFIX "  DMA status %#x\n", dma_status));
00727     } else {
00728         KdPrint2((PRINT_PREFIX "  can't get DMA status\n"));
00729     }
00730     if(dma_status & BM_STATUS_INTR) {
00731         // bullshit, we have DMA interrupt, but had never initiate DMA operation
00732         KdPrint2((PRINT_PREFIX "  clear unexpected DMA intr on ATAPI reset\n"));
00733         AtapiDmaDone(chan->DeviceExtension, DeviceNumber, chan->lChannel, NULL);
00734         GetBaseStatus(chan, statusByte2);
00735     }
00736     if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
00737         UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, DeviceNumber);
00738 /*        if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
00739             UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
00740         }*/
00741     }
00742     return;
00743 
00744 } // end AtapiSoftReset()
00745 
00746 /*
00747     Send command to device.
00748     Translate to 48-Lba form if required
00749 */
00750 UCHAR
00751 NTAPI
00752 AtaCommand48(
00753     IN PHW_DEVICE_EXTENSION deviceExtension,
00754     IN ULONG DeviceNumber,
00755     IN ULONG lChannel,
00756     IN UCHAR command,
00757     IN ULONGLONG lba,
00758     IN USHORT count,
00759     IN USHORT feature,
00760     IN ULONG flags
00761     )
00762 {
00763     PHW_CHANNEL          chan = &deviceExtension->chan[lChannel];
00764     UCHAR                statusByte;
00765     ULONG i;
00766     PUCHAR plba;
00767 
00768     KdPrint2((PRINT_PREFIX "AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
00769                  deviceExtension->DevIndex, deviceExtension->Channel, DeviceNumber, command, lba, count, feature ));
00770 
00771     if(deviceExtension->HwFlags & UNIATA_AHCI) {
00772         PIDE_AHCI_CMD  AHCI_CMD = &(chan->AhciCtlBlock->cmd);
00773 
00774         KdPrint3(("  (ahci)\n"));
00775 
00776         RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
00777 
00778         if(!UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
00779                &(AHCI_CMD->cfis[0]),
00780                 command,
00781                 lba,
00782                 count,
00783                 feature,
00784                 ATA_IMMEDIATE
00785                 )) {
00786             return 0xff;
00787         }
00788         if(UniataAhciSendCommand(deviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) {
00789             KdPrint2(("  timeout\n"));
00790             return 0xff;
00791         }
00792         return IDE_STATUS_IDLE;
00793     }
00794 
00795     SelectDrive(chan, DeviceNumber);
00796 
00797     statusByte = WaitOnBusy(chan);
00798 
00799     /* ready to issue command ? */
00800     if (statusByte & IDE_STATUS_BUSY) {
00801         KdPrint2((PRINT_PREFIX "  Returning BUSY status\n"));
00802         return statusByte;
00803     }
00804     // !!! We should not check ERROR condition here
00805     // ERROR bit may be asserted durring previous operation
00806     // and not cleared after SELECT
00807 
00808     //>>>>>> NV: 2006/08/03
00809     if((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) &&
00810        CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) {
00811         KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
00812         return IDE_STATUS_ERROR;
00813         //return SRB_STATUS_ERROR;
00814     }
00815     //<<<<<< NV:  2006/08/03
00816 
00817     /* only use 48bit addressing if needed because of the overhead */
00818     if (UniAta_need_lba48(command, lba, count,
00819         chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48)) {
00820 
00821         KdPrint2((PRINT_PREFIX "  dev %#x USE_LBA_48\n", DeviceNumber ));
00822         /* translate command into 48bit version */
00823         if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) {
00824             command = AtaCommands48[command];
00825         } else {
00826             KdPrint2((PRINT_PREFIX "  unhandled LBA48 command\n"));
00827             return (UCHAR)-1;
00828         }
00829 
00830         chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
00831         plba = (PUCHAR)&lba;
00832 
00833         AtapiWritePort1(chan, IDX_IO1_o_Feature,      (UCHAR)(feature>>8));
00834         AtapiWritePort1(chan, IDX_IO1_o_Feature,      (UCHAR)feature);
00835         AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   (UCHAR)(count>>8));
00836         AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   (UCHAR)count);
00837         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  (UCHAR)(plba[3]));
00838         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  (UCHAR)(plba[0]));
00839         AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  (UCHAR)(plba[4]));
00840         AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  (UCHAR)(plba[1]));
00841         AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[5]));
00842         AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[2]));
00843 
00844         //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
00845         AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
00846     } else {
00847 
00848         plba = (PUCHAR)&lba; //ktp
00849         chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
00850         
00851         //if(feature ||
00852         //   (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
00853             AtapiWritePort1(chan, IDX_IO1_o_Feature,      (UCHAR)feature);
00854         //}
00855         AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   (UCHAR)count);
00856         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  (UCHAR)plba[0]);
00857         AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  (UCHAR)plba[1]);
00858         AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)plba[2]);
00859         if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) {
00860             //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
00861             AtapiWritePort1(chan, IDX_IO1_o_DriveSelect,  (UCHAR)(plba[3] & 0xf) | IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
00862         } else {
00863             //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
00864             AtapiWritePort1(chan, IDX_IO1_o_DriveSelect,  (UCHAR)(plba[3] & 0xf) | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
00865         }
00866     }
00867 
00868     // write command code to device
00869     AtapiWritePort1(chan, IDX_IO1_o_Command, command);
00870 
00871     switch (flags) {
00872     case ATA_WAIT_INTR:
00873 
00874         // caller requested wait for interrupt
00875         for(i=0;i<4;i++) {
00876             WaitOnBusy(chan);
00877             statusByte = WaitForDrq(chan);
00878             if (statusByte & IDE_STATUS_DRQ)
00879                 break;
00880             AtapiStallExecution(500);
00881             KdPrint2((PRINT_PREFIX "  retry waiting DRQ, status %#x\n", statusByte));
00882         }
00883 
00884         return statusByte;
00885 
00886     case ATA_WAIT_IDLE:
00887 
00888         // caller requested wait for entering Wait state
00889         for (i=0; i<30 * 1000; i++) {
00890 
00891             GetStatus(chan, statusByte);
00892             statusByte = UniataIsIdle(deviceExtension, statusByte);
00893             if(statusByte == 0xff) {
00894                 // no drive ?
00895                 break;
00896             } else
00897             if(statusByte & IDE_STATUS_ERROR) {
00898                 break;
00899             } else
00900             if(statusByte & IDE_STATUS_BUSY) {
00901                 AtapiStallExecution(100);
00902                 continue;
00903             } else
00904             if(statusByte == IDE_STATUS_IDLE) {
00905                 break;
00906             } else {
00907                 //if(deviceExtension->HwFlags & UNIATA_SATA) {
00908                 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
00909                     break;
00910                 }
00911                 AtapiStallExecution(100);
00912             }
00913         }
00914         //statusByte |= IDE_STATUS_BUSY;
00915         break;
00916 
00917     case ATA_WAIT_READY:
00918         statusByte = WaitOnBusyLong(chan);
00919         break;
00920     case ATA_WAIT_BASE_READY:
00921         statusByte = WaitOnBaseBusyLong(chan);
00922         break;
00923     case ATA_IMMEDIATE:
00924         GetStatus(chan, statusByte);
00925         if (statusByte & IDE_STATUS_ERROR) {
00926             KdPrint2((PRINT_PREFIX "  Warning: Immed Status %#x :(\n", statusByte));
00927             if(statusByte == (IDE_STATUS_IDLE | IDE_STATUS_ERROR)) {
00928                 break;
00929             }
00930             KdPrint2((PRINT_PREFIX "  try to continue\n"));
00931             statusByte &= ~IDE_STATUS_ERROR;
00932         }
00933         chan->ExpectingInterrupt = TRUE;
00934         // !!!!!
00935         InterlockedExchange(&(chan->CheckIntr),
00936                                       CHECK_INTR_IDLE);
00937         statusByte = 0;
00938         break;
00939     }
00940 
00941     KdPrint2((PRINT_PREFIX "  Status %#x\n", statusByte));
00942 
00943     return statusByte;
00944 } // end AtaCommand48()
00945 
00946 /*
00947     Send command to device.
00948     This is simply wrapper for AtaCommand48()
00949 */
00950 UCHAR
00951 NTAPI
00952 AtaCommand(
00953     IN PHW_DEVICE_EXTENSION deviceExtension,
00954     IN ULONG DeviceNumber,
00955     IN ULONG lChannel,
00956     IN UCHAR command,
00957     IN USHORT cylinder,
00958     IN UCHAR head,
00959     IN UCHAR sector,
00960     IN UCHAR count,
00961     IN UCHAR feature,
00962     IN ULONG flags
00963     )
00964 {
00965     if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
00966         return AtaCommand48(deviceExtension, DeviceNumber, lChannel,
00967                             command,
00968                             (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
00969                             count, feature, flags);
00970     } else {
00971         PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
00972         PIDE_AHCI_CMD  AHCI_CMD = &(chan->AhciCtlBlock->cmd);
00973 
00974         KdPrint3(("AtaCommand(ahci)\n"));
00975 
00976         RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
00977 
00978         if(!UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
00979                &(AHCI_CMD->cfis[0]),
00980                 command,
00981                 (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
00982                 count,
00983                 feature,
00984                 ATA_IMMEDIATE
00985                 )) {
00986             return 0xff;
00987         }
00988         if(UniataAhciSendCommand(deviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) {
00989             KdPrint2(("  timeout\n"));
00990             return 0xff;
00991         }
00992         return IDE_STATUS_IDLE;
00993     }
00994 } // end AtaCommand()
00995 
00996 LONG
00997 NTAPI
00998 AtaPio2Mode(LONG pio)
00999 {
01000     switch (pio) {
01001     default: return ATA_PIO;
01002     case 0: return ATA_PIO0;
01003     case 1: return ATA_PIO1;
01004     case 2: return ATA_PIO2;
01005     case 3: return ATA_PIO3;
01006     case 4: return ATA_PIO4;
01007     case 5: return ATA_PIO5;
01008     }
01009 } // end AtaPio2Mode()
01010 
01011 LONG
01012 NTAPI
01013 AtaPioMode(PIDENTIFY_DATA2 ident)
01014 {
01015     if (ident->PioTimingsValid) {
01016         if (ident->AdvancedPIOModes & AdvancedPIOModes_5)
01017             return 5;
01018         if (ident->AdvancedPIOModes & AdvancedPIOModes_4)
01019             return 4;
01020         if (ident->AdvancedPIOModes & AdvancedPIOModes_3)
01021             return 3;
01022     }
01023     if (ident->PioCycleTimingMode == 2)
01024         return 2;
01025     if (ident->PioCycleTimingMode == 1)
01026         return 1;
01027     if (ident->PioCycleTimingMode == 0)
01028         return 0;
01029     return -1;
01030 } // end AtaPioMode()
01031 
01032 LONG
01033 NTAPI
01034 AtaWmode(PIDENTIFY_DATA2 ident)
01035 {
01036     if (ident->MultiWordDMASupport & 0x04)
01037         return 2;
01038     if (ident->MultiWordDMASupport & 0x02)
01039         return 1;
01040     if (ident->MultiWordDMASupport & 0x01)
01041         return 0;
01042     return -1;
01043 } // end AtaWmode()
01044 
01045 LONG
01046 NTAPI
01047 AtaUmode(PIDENTIFY_DATA2 ident)
01048 {
01049     if (!ident->UdmaModesValid)
01050         return -1;
01051     if (ident->UltraDMASupport & 0x40)
01052         return 6;
01053     if (ident->UltraDMASupport & 0x20)
01054         return 5;
01055     if (ident->UltraDMASupport & 0x10)
01056         return 4;
01057     if (ident->UltraDMASupport & 0x08)
01058         return 3;
01059     if (ident->UltraDMASupport & 0x04)
01060         return 2;
01061     if (ident->UltraDMASupport & 0x02)
01062         return 1;
01063     if (ident->UltraDMASupport & 0x01)
01064         return 0;
01065     return -1;
01066 } // end AtaUmode()
01067 
01068 
01069 #ifndef UNIATA_CORE
01070 
01071 VOID
01072 NTAPI
01073 AtapiTimerDpc(
01074     IN PVOID HwDeviceExtension
01075     )
01076 {
01077     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
01078     PHW_TIMER HwScsiTimer;
01079     LARGE_INTEGER time;
01080     ULONG MiniportTimerValue;
01081     BOOLEAN recall = FALSE;
01082     ULONG lChannel;
01083     PHW_CHANNEL chan;
01084 
01085     KdPrint2((PRINT_PREFIX "AtapiTimerDpc:\n"));
01086 
01087     lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
01088     if(lChannel == CHAN_NOT_SPECIFIED) {
01089         KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no items\n"));
01090         return;
01091     }
01092     chan = &deviceExtension->chan[lChannel];
01093 
01094     while(TRUE) {
01095 
01096         HwScsiTimer = chan->HwScsiTimer;
01097         chan->HwScsiTimer = NULL;
01098 
01099         deviceExtension->FirstDpcChan = chan->NextDpcChan;
01100         if(deviceExtension->FirstDpcChan != CHAN_NOT_SPECIFIED) {
01101             recall = TRUE;
01102         }
01103 
01104         HwScsiTimer(HwDeviceExtension);
01105 
01106         chan->NextDpcChan = CHAN_NOT_SPECIFIED;
01107 
01108         lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
01109         if(lChannel == CHAN_NOT_SPECIFIED) {
01110             KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no more items\n"));
01111             deviceExtension->FirstDpcChan =
01112             deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
01113             return;
01114         }
01115 
01116         KeQuerySystemTime(&time);
01117         KdPrint2((PRINT_PREFIX "AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
01118 
01119         chan = &deviceExtension->chan[lChannel];
01120         if(time.QuadPart >= chan->DpcTime - 10) {
01121             // call now
01122             KdPrint2((PRINT_PREFIX "AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
01123                          (ULONG)(chan->DpcTime >> 32), (ULONG)(chan->DpcTime)));
01124             continue;
01125         }
01126         break;
01127     }
01128 
01129     if(recall) {
01130         deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
01131         MiniportTimerValue = (ULONG)(time.QuadPart - chan->DpcTime)/10;
01132         if(!MiniportTimerValue)
01133             MiniportTimerValue = 1;
01134 
01135         KdPrint2((PRINT_PREFIX "AtapiTimerDpc: recall AtapiTimerDpc\n"));
01136         ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
01137                              AtapiTimerDpc,
01138                              MiniportTimerValue
01139                              );
01140     }
01141     return;
01142 
01143 } // end AtapiTimerDpc()
01144 
01145 /*
01146     Wrapper for ScsiPort, that implements smart Dpc
01147     queueing. We need it to allow parallel functioning
01148     of IDE channles with shared interrupt. Standard Dpc mechanism
01149     cancels previous Dpc request (if any), but we need Dpc queue.
01150 */
01151 VOID
01152 NTAPI
01153 AtapiQueueTimerDpc(
01154     IN PVOID HwDeviceExtension,
01155     IN ULONG lChannel,
01156     IN PHW_TIMER HwScsiTimer,
01157     IN ULONG MiniportTimerValue
01158     )
01159 {
01160     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
01161     LARGE_INTEGER time;
01162     LARGE_INTEGER time2;
01163     ULONG i;
01164     PHW_CHANNEL prev_chan;
01165     PHW_CHANNEL chan;
01166 //    BOOLEAN UseRequestTimerCall = TRUE;
01167 
01168     KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
01169     KeQuerySystemTime(&time);
01170     time2 = time;
01171     KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
01172     time.QuadPart += MiniportTimerValue*10;
01173     KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time.HighPart, time.LowPart));
01174 
01175     KdPrint2((PRINT_PREFIX "  ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension->ActiveDpcChan, deviceExtension->FirstDpcChan));
01176 
01177     i = deviceExtension->FirstDpcChan;
01178     chan = prev_chan = NULL;
01179     while(i != CHAN_NOT_SPECIFIED) {
01180         prev_chan = chan;
01181         chan = &deviceExtension->chan[i];
01182         if(chan->DpcTime > time.QuadPart) {
01183             break;
01184         }
01185         i = chan->NextDpcChan;
01186     }
01187     chan = &deviceExtension->chan[lChannel];
01188     if(!prev_chan) {
01189         deviceExtension->FirstDpcChan = lChannel;
01190     } else {
01191         prev_chan->NextDpcChan = lChannel;
01192     }
01193     chan->NextDpcChan = i;
01194     chan->HwScsiTimer = HwScsiTimer;
01195     chan->DpcTime     = time.QuadPart;
01196 
01197     KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2.HighPart, time2.LowPart));
01198     if(time.QuadPart <= time2.QuadPart) {
01199         MiniportTimerValue = 1;
01200     } else {
01201         MiniportTimerValue = (ULONG)((time.QuadPart - time2.QuadPart) / 10);
01202     }
01203 
01204     KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
01205     ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
01206                          AtapiTimerDpc,
01207                          MiniportTimerValue);
01208 
01209 } // end AtapiQueueTimerDpc()
01210 
01211 #endif //UNIATA_CORE
01212 
01213 VOID
01214 NTAPI
01215 UniataDumpATARegs(
01216     IN PHW_CHANNEL chan
01217     )
01218 {
01219     ULONG                j;
01220     UCHAR                statusByteAlt;
01221 
01222     GetStatus(chan, statusByteAlt);
01223     KdPrint2((PRINT_PREFIX "  AltStatus (%#x)\n", statusByteAlt));
01224 
01225     for(j=1; j<IDX_IO1_SZ; j++) {
01226         statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
01227         KdPrint2((PRINT_PREFIX
01228                    "  Reg_%#x (%#x) = %#x\n",
01229                    j,
01230                    chan->RegTranslation[IDX_IO1+j].Addr,
01231                    statusByteAlt));
01232     }
01233     for(j=0; j<IDX_BM_IO_SZ-1; j++) {
01234         statusByteAlt = AtapiReadPort1(chan, IDX_BM_IO+j);
01235         KdPrint2((PRINT_PREFIX
01236                    "  BM_%#x (%#x) = %#x\n",
01237                    j,
01238                    chan->RegTranslation[IDX_BM_IO+j].Addr,
01239                    statusByteAlt));
01240     }
01241     return;
01242 } // end UniataDumpATARegs()
01243 
01244 /*++
01245 
01246 Routine Description:
01247 
01248     Issue IDENTIFY command to a device.
01249 
01250 Arguments:
01251 
01252     HwDeviceExtension - HBA miniport driver's adapter data storage
01253     DeviceNumber - Indicates which device.
01254     Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
01255 
01256 Return Value:
01257 
01258     TRUE if all goes well.
01259 
01260 --*/
01261 BOOLEAN
01262 NTAPI
01263 IssueIdentify(
01264     IN PVOID HwDeviceExtension,
01265     IN ULONG DeviceNumber,
01266     IN ULONG lChannel,
01267     IN UCHAR Command,
01268     IN BOOLEAN NoSetup
01269     )
01270 {
01271     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
01272     PHW_CHANNEL          chan = &deviceExtension->chan[lChannel];
01273     ULONG                waitCount = 50000;
01274     ULONG                j;
01275     UCHAR                statusByte;
01276     UCHAR                statusByte2;
01277     UCHAR                signatureLow,
01278                          signatureHigh;
01279     BOOLEAN              atapiDev = FALSE;
01280     PHW_LU_EXTENSION     LunExt = chan->lun[DeviceNumber];
01281 
01282     if(chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) {
01283         if(chan->PmLunMap & (1 << DeviceNumber)) {
01284             // OK
01285         } else {
01286             KdPrint2((PRINT_PREFIX "IssueIdentify: PM empty port\n"));
01287             return FALSE;
01288         }
01289     } else
01290     if(DeviceNumber && (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
01291         KdPrint2((PRINT_PREFIX "IssueIdentify: NO SLAVE\n"));
01292         return FALSE;
01293     }
01294     if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
01295         KdPrint2((PRINT_PREFIX "IssueIdentify: HIDDEN\n"));
01296         return FALSE;
01297     }
01298 
01299     if(deviceExtension->HwFlags & UNIATA_AHCI) {
01300         statusByte = WaitOnBusyLong(chan);
01301     } else {
01302         SelectDrive(chan, DeviceNumber);
01303         AtapiStallExecution(10);
01304         statusByte = WaitOnBusyLong(chan);
01305         // Check that the status register makes sense.
01306         GetBaseStatus(chan, statusByte2);
01307 
01308         UniataDumpATARegs(chan);
01309     }
01310 
01311     if (Command == IDE_COMMAND_IDENTIFY) {
01312         // Mask status byte ERROR bits.
01313         statusByte = UniataIsIdle(deviceExtension, statusByte & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX));
01314         KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte));
01315         // Check if register value is reasonable.
01316 
01317         if(statusByte != IDE_STATUS_IDLE) {
01318 
01319             // No reset here !!!
01320             KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
01321 
01322             //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
01323             if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
01324                 SelectDrive(chan, DeviceNumber);
01325                 WaitOnBusyLong(chan);
01326 
01327                 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
01328                 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
01329 
01330                 if (signatureLow == ATAPI_MAGIC_LSB &&
01331                     signatureHigh == ATAPI_MAGIC_MSB) {
01332                     // Device is Atapi.
01333                     KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber));
01334                     return FALSE;
01335                 }
01336 
01337                 // We really should wait up to 31 seconds
01338                 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
01339                 // (30 seconds for device 1)
01340                 do {
01341                     // Wait for Busy to drop.
01342                     AtapiStallExecution(100);
01343                     GetStatus(chan, statusByte);
01344 
01345                 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
01346                 GetBaseStatus(chan, statusByte2);
01347 
01348                 SelectDrive(chan, DeviceNumber);
01349             } else {
01350                 GetBaseStatus(chan, statusByte2);
01351             }
01352             // Another check for signature, to deal with one model Atapi that doesn't assert signature after
01353             // a soft reset.
01354             signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
01355             signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
01356 
01357             if (signatureLow == ATAPI_MAGIC_LSB &&
01358                 signatureHigh == ATAPI_MAGIC_MSB) {
01359                 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber));
01360                 // Device is Atapi.
01361                 return FALSE;
01362             }
01363 
01364             statusByte = UniataIsIdle(deviceExtension, statusByte) & ~IDE_STATUS_INDEX;
01365             if (statusByte != IDE_STATUS_IDLE) {
01366                 // Give up on this.
01367                 KdPrint2((PRINT_PREFIX "IssueIdentify: no dev (dev %d)\n", DeviceNumber));
01368                 return FALSE;
01369             }
01370         }
01371     } else {
01372         KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte));
01373         //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
01374         if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
01375             statusByte = WaitForIdleLong(chan);
01376             KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte));
01377         }
01378         atapiDev = TRUE;
01379     }
01380 
01381 //    if(deviceExtension->HwFlags & UNIATA_SATA) {
01382     if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
01383         j = 4; // skip old-style checks
01384     } else {
01385         j = 0;
01386     }
01387     for (; j < 4*2; j++) {
01388         // Send IDENTIFY command.
01389         statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, 0, 0, 0, (j >= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR);
01390         // Clear interrupt
01391 
01392         if (statusByte & IDE_STATUS_DRQ) {
01393             // Read status to acknowledge any interrupts generated.
01394             KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte));
01395             GetBaseStatus(chan, statusByte);
01396             // One last check for Atapi.
01397             if (Command == IDE_COMMAND_IDENTIFY) {
01398                 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
01399                 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
01400 
01401                 if (signatureLow == ATAPI_MAGIC_LSB &&
01402                     signatureHigh == ATAPI_MAGIC_MSB) {
01403                     KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber));
01404                     // Device is Atapi.
01405                     return FALSE;
01406                 }
01407             }
01408             break;
01409         } else {
01410             KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte));
01411             if (Command == IDE_COMMAND_IDENTIFY) {
01412                 // Check the signature. If DRQ didn't come up it's likely Atapi.
01413                 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
01414                 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
01415 
01416                 if (signatureLow == ATAPI_MAGIC_LSB &&
01417                     signatureHigh == ATAPI_MAGIC_MSB) {
01418                     // Device is Atapi.
01419                     KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber));
01420                     return FALSE;
01421                 }
01422             } else {
01423                 if(!(statusByte & IDE_STATUS_ERROR) && (statusByte & IDE_STATUS_BUSY)) {
01424                     KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
01425                     break;
01426                 }
01427             }
01428             // Device didn't respond correctly. It will be given one more chances.
01429             KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
01430                         statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error)));
01431             GetBaseStatus(chan, statusByte);
01432             AtapiSoftReset(chan,DeviceNumber);
01433 
01434             AtapiDisableInterrupts(deviceExtension, lChannel);
01435             AtapiEnableInterrupts(deviceExtension, lChannel);
01436 
01437             GetBaseStatus(chan, statusByte);
01438             //GetStatus(chan, statusByte);
01439             KdPrint2((PRINT_PREFIX "IssueIdentify: Status after soft reset (%#x)\n", statusByte));
01440         }
01441     }
01442     // Check for error on really stupid master devices that assert random
01443     // patterns of bits in the status register at the slave address.
01444     if ((Command == IDE_COMMAND_IDENTIFY) && (statusByte & IDE_STATUS_ERROR)) {
01445         KdPrint2((PRINT_PREFIX "IssueIdentify: Exit on error (%#x)\n", statusByte));
01446         return FALSE;
01447     }
01448 
01449     KdPrint2((PRINT_PREFIX "IssueIdentify: Status before read words %#x\n", statusByte));
01450     // Suck out 256 words. After waiting for one model that asserts busy
01451     // after receiving the Packet Identify command.
01452     statusByte = WaitForDrq(chan);
01453     statusByte = WaitOnBusyLong(chan);
01454         KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
01455 
01456     if (!(statusByte & IDE_STATUS_DRQ)) {
01457         KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte));
01458         GetBaseStatus(chan, statusByte);
01459         return FALSE;
01460     }
01461     GetBaseStatus(chan, statusByte);
01462     KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte));
01463 
01464     if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) ) {
01465 
01466         KdPrint2((PRINT_PREFIX "  use 16bit IO\n"));
01467 #if 0
01468         USHORT w;
01469         ULONG i;
01470         // ATI/SII chipsets with memory-mapped IO hangs when
01471         // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
01472         // Unfortunately, I don't know yet how to workaround it except the way you see below.
01473         KdPrint2((PRINT_PREFIX 
01474                    "  IO_%#x (%#x), %s:\n",
01475                    IDX_IO1_i_Data,
01476                    chan->RegTranslation[IDX_IO1_i_Data].Addr,
01477                    chan->RegTranslation[IDX_IO1_i_Data].MemIo ? "Mem" : "IO"));
01478         for(i=0; i<256; i++) {
01479 /*
01480             KdPrint2((PRINT_PREFIX 
01481                        "  IO_%#x (%#x):\n",
01482                        IDX_IO1_i_Data,
01483                        chan->RegTranslation[IDX_IO1_i_Data].Addr));
01484 */
01485             w = AtapiReadPort2(chan, IDX_IO1_i_Data);
01486             KdPrint2((PRINT_PREFIX 
01487                        "    %x\n", w));
01488             AtapiStallExecution(1);
01489             ((PUSHORT)&deviceExtension->FullIdentifyData)[i] = w;
01490         }
01491 #else
01492         ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
01493 #endif
01494         // Work around for some IDE and one model Atapi that will present more than
01495         // 256 bytes for the Identify data.
01496         KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
01497         statusByte = AtapiSuckPort2(chan);
01498     } else {
01499         KdPrint2((PRINT_PREFIX "  use 32bit IO\n"));
01500         ReadBuffer2(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256/2, PIO0_TIMING);
01501     }
01502 
01503     KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
01504     statusByte = WaitForDrq(chan);
01505     KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
01506     GetBaseStatus(chan, statusByte);
01507 
01508     KdPrint2((PRINT_PREFIX "IssueIdentify: Status after read words %#x\n", statusByte));
01509 
01510     if(NoSetup) {
01511         KdPrint2((PRINT_PREFIX "IssueIdentify: no setup, exiting\n"));
01512         return TRUE;
01513     }
01514 
01515     KdPrint2((PRINT_PREFIX "Model: %20.20s\n", deviceExtension->FullIdentifyData.ModelNumber));
01516     KdPrint2((PRINT_PREFIX "FW:    %4.4s\n", deviceExtension->FullIdentifyData.FirmwareRevision));
01517     KdPrint2((PRINT_PREFIX "S/N:   %20.20s\n", deviceExtension->FullIdentifyData.SerialNumber));
01518     KdPrint2((PRINT_PREFIX "Pio:   %x\n", deviceExtension->FullIdentifyData.PioCycleTimingMode));
01519     if(deviceExtension->FullIdentifyData.PioTimingsValid) {
01520         KdPrint2((PRINT_PREFIX "APio:  %x\n", deviceExtension->FullIdentifyData.AdvancedPIOModes));
01521     }
01522     KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive));
01523     KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive));
01524     if(deviceExtension->FullIdentifyData.UdmaModesValid) {
01525         KdPrint2((PRINT_PREFIX "UDMA:  %x\n", deviceExtension->FullIdentifyData.UltraDMAActive));
01526     }
01527     KdPrint2((PRINT_PREFIX "SATA:  %x\n", deviceExtension->FullIdentifyData.SataEnable));
01528 
01529     // Check out a few capabilities / limitations of the device.
01530     if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
01531         // Determine if this drive supports the MSN functions.
01532         KdPrint2((PRINT_PREFIX "IssueIdentify: Marking drive %d as removable. SFE = %d\n",
01533                     DeviceNumber,
01534                     deviceExtension->FullIdentifyData.RemovableStatus));
01535         LunExt->DeviceFlags |= DFLAGS_REMOVABLE_DRIVE;
01536     }
01537     if (deviceExtension->FullIdentifyData.MaximumBlockTransfer) {
01538         // Determine max. block transfer for this device.
01539         LunExt->MaximumBlockXfer =
01540             (UCHAR)(deviceExtension->FullIdentifyData.MaximumBlockTransfer & 0xFF);
01541     }
01542     LunExt->NumOfSectors = 0;
01543     if (Command == IDE_COMMAND_IDENTIFY) {
01544         ULONGLONG NumOfSectors=0;
01545         ULONGLONG NativeNumOfSectors=0;
01546         ULONGLONG cylinders=0;
01547         ULONGLONG tmp_cylinders=0;
01548         // Read very-old-style drive geometry
01549         KdPrint2((PRINT_PREFIX "CHS %#x:%#x:%#x\n", 
01550                 deviceExtension->FullIdentifyData.NumberOfCylinders,
01551                 deviceExtension->FullIdentifyData.NumberOfHeads,
01552                 deviceExtension->FullIdentifyData.SectorsPerTrack
01553                 ));
01554         NumOfSectors = deviceExtension->FullIdentifyData.NumberOfCylinders *
01555                        deviceExtension->FullIdentifyData.NumberOfHeads *
01556                        deviceExtension->FullIdentifyData.SectorsPerTrack;
01557         KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
01558         // Check for HDDs > 8Gb
01559         if ((deviceExtension->FullIdentifyData.NumberOfCylinders == 0x3fff) &&
01560 /*            (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
01561             (NumOfSectors < deviceExtension->FullIdentifyData.UserAddressableSectors)) {
01562             KdPrint2((PRINT_PREFIX "NumberOfCylinders == 0x3fff\n"));
01563             cylinders = 
01564                 (deviceExtension->FullIdentifyData.UserAddressableSectors /
01565                     (deviceExtension->FullIdentifyData.NumberOfHeads *
01566                        deviceExtension->FullIdentifyData.SectorsPerTrack));
01567 
01568             KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
01569 
01570             NumOfSectors = cylinders *
01571                            deviceExtension->FullIdentifyData.NumberOfHeads *
01572                            deviceExtension->FullIdentifyData.SectorsPerTrack;
01573 
01574             KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
01575         } else {
01576 
01577         }
01578         // Check for LBA mode
01579         KdPrint2((PRINT_PREFIX "SupportLba flag %#x\n", deviceExtension->FullIdentifyData.SupportLba));
01580         KdPrint2((PRINT_PREFIX "MajorRevision %#x\n", deviceExtension->FullIdentifyData.MajorRevision));
01581         KdPrint2((PRINT_PREFIX "UserAddressableSectors %#x\n", deviceExtension->FullIdentifyData.UserAddressableSectors));
01582         if ( deviceExtension->FullIdentifyData.SupportLba
01583                             ||
01584             (deviceExtension->FullIdentifyData.MajorRevision &&
01585 /*             deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
01586              deviceExtension->FullIdentifyData.UserAddressableSectors)) {
01587             KdPrint2((PRINT_PREFIX "LBA mode\n"));
01588             LunExt->DeviceFlags |= DFLAGS_LBA_ENABLED;
01589         } else {
01590             KdPrint2((PRINT_PREFIX "Keep orig geometry\n"));
01591             LunExt->DeviceFlags |= DFLAGS_ORIG_GEOMETRY;
01592             goto skip_lba_staff;
01593         }
01594         // Check for LBA48 support
01595         if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
01596             if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48 &&
01597                deviceExtension->FullIdentifyData.FeaturesEnabled.Address48 &&
01598                (deviceExtension->FullIdentifyData.UserAddressableSectors48 > NumOfSectors)
01599                ) {
01600                 KdPrint2((PRINT_PREFIX "LBA48\n"));
01601                 cylinders = 
01602                     (deviceExtension->FullIdentifyData.UserAddressableSectors48 /
01603                         (deviceExtension->FullIdentifyData.NumberOfHeads *
01604                            deviceExtension->FullIdentifyData.SectorsPerTrack));
01605 
01606                 KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
01607                 
01608                 NativeNumOfSectors = cylinders *
01609                                deviceExtension->FullIdentifyData.NumberOfHeads *
01610                                deviceExtension->FullIdentifyData.SectorsPerTrack;
01611 
01612                 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
01613 
01614                 if(NativeNumOfSectors > NumOfSectors) {
01615                     KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
01616                     NumOfSectors = NativeNumOfSectors;
01617                 }
01618             }
01619 
01620             // Check drive capacity report for LBA48-capable drives.
01621             if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48) {
01622                 ULONG hNativeNumOfSectors;
01623                 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
01624 
01625                 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
01626                              IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
01627 
01628                 if(!(statusByte & IDE_STATUS_ERROR)) {
01629                     NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
01630                                         ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow)  << 8) |
01631                                         ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) ;
01632 
01633                     AtapiWritePort1(chan, IDX_IO2_o_Control,
01634                                            IDE_DC_USE_HOB );
01635 
01636                     KdPrint2((PRINT_PREFIX "Read high order bytes\n"));
01637                     NativeNumOfSectors |=
01638                                         ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber)  << 24 );
01639                     hNativeNumOfSectors= 
01640                                          (ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) |
01641                                         ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 8) ;
01642                     ((PULONG)&NativeNumOfSectors)[1] = hNativeNumOfSectors;
01643 
01644                     KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
01645 
01646                     // Some drives report LBA48 capability while has capacity below 128Gb
01647                     // Probably they support large block-counters.
01648                     // But the problem is that some of them reports higher part of Max LBA equal to lower part.
01649                     // Here we check this
01650                     if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
01651                         KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!!\n"));
01652 
01653                         statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
01654                                      IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
01655 
01656                         if(!(statusByte & IDE_STATUS_ERROR)) {
01657                             NativeNumOfSectors = (ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
01658                                                 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber)  << 24) |
01659                                                 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow)  << 8 ) |
01660                                                 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow)  << 32) |
01661                                                 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
01662                                                 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 40) 
01663                                                 ;
01664                         }
01665 
01666                         if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
01667                             KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!! (2)\n"));
01668                             NativeNumOfSectors = 0;
01669                         }
01670                     }
01671 
01672                     if(NumOfSectors <= ATA_MAX_LBA28 &&
01673                        NativeNumOfSectors > NumOfSectors) {
01674 
01675                         KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
01676                         KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
01677 
01678                         statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
01679                                      IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
01680                         if(!(statusByte & IDE_STATUS_ERROR)) {
01681                             NumOfSectors = NativeNumOfSectors;
01682                         }
01683                     }
01684                 }
01685             }
01686     
01687             if(NumOfSectors < 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
01688                 // check for native LBA size
01689                 // some drives report ~32Gb in Identify Block
01690                 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
01691 
01692                 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_READ_NATIVE_SIZE,
01693                              0, IDE_USE_LBA, 0, 0, 0, ATA_WAIT_READY);
01694 
01695                 if(!(statusByte & IDE_STATUS_ERROR)) {
01696                     NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
01697                                         ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
01698                                         ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
01699                                        (((ULONG)AtapiReadPort1(chan, IDX_IO1_i_DriveSelect) & 0xf) << 24);
01700 
01701                     KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
01702 
01703                     if(NativeNumOfSectors > NumOfSectors) {
01704 
01705                         KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
01706                         KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
01707 
01708                         statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
01709                                      IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
01710                         if(!(statusByte & IDE_STATUS_ERROR)) {
01711                             NumOfSectors = NativeNumOfSectors;
01712                         }
01713                     }
01714                 }
01715             }
01716 
01717         } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
01718 
01719         // fill IdentifyData with bogus geometry
01720         KdPrint2((PRINT_PREFIX "requested LunExt->GeomType=%x\n", LunExt->opt_GeomType));
01721         tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *
01722                                         deviceExtension->FullIdentifyData.NumberOfCurrentHeads);
01723         KdPrint2((PRINT_PREFIX "tmp_cylinders = %#I64x\n", tmp_cylinders));
01724         if((tmp_cylinders < 0xffff) || (LunExt->opt_GeomType == GEOM_ORIG)) {
01725             // ok, we can keep original values
01726             if(LunExt->opt_GeomType == GEOM_AUTO) {
01727                 LunExt->opt_GeomType = GEOM_ORIG;
01728             }
01729         } else {
01730             tmp_cylinders = NumOfSectors / (255*63);
01731             if(tmp_cylinders < 0xffff) {
01732                 // we can use generic values for H/S for generic geometry approach
01733                 if(LunExt->opt_GeomType == GEOM_AUTO) {
01734                     LunExt->opt_GeomType = GEOM_STD;
01735                 }
01736             } else {
01737                 // we should use UNIATA geometry approach
01738                 if(LunExt->opt_GeomType == GEOM_AUTO) {
01739                     LunExt->opt_GeomType = GEOM_UNIATA;
01740                 }
01741             }
01742         }
01743         KdPrint2((PRINT_PREFIX "final LunExt->opt_GeomType=%x\n", LunExt->opt_GeomType));
01744 
01745         if(LunExt->opt_GeomType == GEOM_STD) {
01746             deviceExtension->FullIdentifyData.CurrentSectorsPerTrack =
01747             deviceExtension->FullIdentifyData.SectorsPerTrack = 63;
01748 
01749             deviceExtension->FullIdentifyData.NumberOfCurrentHeads =
01750             deviceExtension->FullIdentifyData.NumberOfHeads   = 255;
01751 
01752             cylinders = NumOfSectors / (255*63);
01753             KdPrint2((PRINT_PREFIX "Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders, 255, 63));
01754         } else
01755         if(LunExt->opt_GeomType == GEOM_UNIATA) {
01756             while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x80)) {
01757                 cylinders /= 2;
01758                 KdPrint2((PRINT_PREFIX "cylinders /= 2\n"));
01759                 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
01760                 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
01761             }
01762             while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x80)) {
01763                 cylinders /= 2;
01764                 KdPrint2((PRINT_PREFIX "cylinders /= 2 (2)\n"));
01765                 deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
01766                 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
01767             }
01768             while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x8000)) {
01769                 cylinders /= 2;
01770                 KdPrint2((PRINT_PREFIX "cylinders /= 2 (3)\n"));
01771                 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
01772                 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
01773             }
01774             while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x8000)) {
01775                 cylinders /= 2;
01776                 KdPrint2((PRINT_PREFIX "cylinders /= 2 (4)\n"));
01777                 deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
01778                 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
01779             }
01780             KdPrint2((PRINT_PREFIX "Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders,
01781                 deviceExtension->FullIdentifyData.NumberOfCurrentHeads,
01782                 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack));
01783         }
01784         if(!cylinders) {
01785             KdPrint2((PRINT_PREFIX "cylinders = tmp_cylinders (%x = %x)\n", cylinders, tmp_cylinders));
01786             cylinders = tmp_cylinders;
01787         }
01788         deviceExtension->FullIdentifyData.NumberOfCurrentCylinders =
01789         deviceExtension->FullIdentifyData.NumberOfCylinders = (USHORT)cylinders;
01790 
01791 skip_lba_staff:
01792 
01793         KdPrint2((PRINT_PREFIX "Geometry: C %#x (%#x)\n",
01794                   deviceExtension->FullIdentifyData.NumberOfCylinders,
01795                   deviceExtension->FullIdentifyData.NumberOfCurrentCylinders
01796                   ));
01797         KdPrint2((PRINT_PREFIX "Geometry: H %#x (%#x)\n",
01798                   deviceExtension->FullIdentifyData.NumberOfHeads,
01799                   deviceExtension->FullIdentifyData.NumberOfCurrentHeads
01800                   ));
01801         KdPrint2((PRINT_PREFIX "Geometry: S %#x (%#x)\n",
01802                   deviceExtension->FullIdentifyData.SectorsPerTrack,
01803                   deviceExtension->FullIdentifyData.CurrentSectorsPerTrack
01804                   ));
01805 
01806         if(NumOfSectors)
01807             LunExt->NumOfSectors = NumOfSectors;
01808 /*        if(deviceExtension->FullIdentifyData.MajorRevision &&
01809            deviceExtension->FullIdentifyData.DoubleWordIo) {
01810             LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
01811         }*/
01812     }
01813 
01814     ScsiPortMoveMemory(&LunExt->IdentifyData,
01815                        &deviceExtension->FullIdentifyData,sizeof(IDENTIFY_DATA2));
01816 
01817     InitBadBlocks(LunExt);
01818 
01819     if ((LunExt->IdentifyData.DrqType & ATAPI_DRQT_INTR) &&
01820         (Command != IDE_COMMAND_IDENTIFY)) {
01821 
01822         // This device interrupts with the assertion of DRQ after receiving
01823         // Atapi Packet Command
01824         LunExt->DeviceFlags |= DFLAGS_INT_DRQ;
01825         KdPrint2((PRINT_PREFIX "IssueIdentify: Device interrupts on assertion of DRQ.\n"));
01826 
01827     } else {
01828         KdPrint2((PRINT_PREFIX "IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
01829     }
01830 
01831     if(Command != IDE_COMMAND_IDENTIFY) {
01832         // ATAPI branch
01833         if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_TAPE) {
01834             // This is a tape.
01835             LunExt->DeviceFlags |= DFLAGS_TAPE_DEVICE;
01836             KdPrint2((PRINT_PREFIX "IssueIdentify: Device is a tape drive.\n"));
01837         } else
01838         if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM ||
01839             LunExt->IdentifyData.DeviceType == ATAPI_TYPE_OPTICAL) {
01840             KdPrint2((PRINT_PREFIX "IssueIdentify: Device is CD/Optical drive.\n"));
01841             // set CD default costs
01842             LunExt->RwSwitchCost  = REORDER_COST_SWITCH_RW_CD;
01843             LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_CD;
01844             LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_CD;
01845             statusByte = WaitForDrq(chan);
01846         } else {
01847             KdPrint2((PRINT_PREFIX "IssueIdentify: ATAPI drive type %#x.\n",
01848                 LunExt->IdentifyData.DeviceType));
01849         }
01850     } else {
01851         KdPrint2((PRINT_PREFIX "IssueIdentify: hard drive.\n"));
01852     }
01853 
01854     GetBaseStatus(chan, statusByte);
01855     KdPrint2((PRINT_PREFIX "IssueIdentify: final Status on exit (%#x)\n", statusByte));
01856     return TRUE;
01857 
01858 } // end IssueIdentify()
01859 
01860 
01861 /*++
01862 
01863 Routine Description:
01864     Set drive parameters using the IDENTIFY data.
01865 
01866 Arguments:
01867     HwDeviceExtension - HBA miniport driver's adapter data storage
01868     DeviceNumber - Indicates which device.
01869 
01870 Return Value:
01871     TRUE if all goes well.
01872 
01873 --*/
01874 BOOLEAN
01875 NTAPI
01876 SetDriveParameters(
01877     IN PVOID HwDeviceExtension,
01878     IN ULONG DeviceNumber,
01879     IN ULONG lChannel
01880     )
01881 {
01882     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
01883     PIDENTIFY_DATA2      identifyData;
01884     PHW_LU_EXTENSION     LunExt;
01885 //    ULONG i;
01886     UCHAR statusByte;
01887     UCHAR errorByte;
01888 
01889     LunExt = deviceExtension->chan[lChannel].lun[DeviceNumber];
01890     identifyData = &(LunExt->IdentifyData);
01891 
01892     if(LunExt->DeviceFlags &
01893           (DFLAGS_LBA_ENABLED | DFLAGS_ORIG_GEOMETRY))
01894        return TRUE;
01895 
01896     KdPrint2((PRINT_PREFIX "SetDriveParameters: Number of heads %#x\n", identifyData->NumberOfHeads));
01897     KdPrint2((PRINT_PREFIX "SetDriveParameters: Sectors per track %#x\n", identifyData->SectorsPerTrack));
01898 
01899     // Send SET PARAMETER command.
01900     statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
01901                             IDE_COMMAND_SET_DRIVE_PARAMETERS, 0,
01902                             (identifyData->NumberOfHeads - 1), 0,
01903                             (UCHAR)identifyData->SectorsPerTrack, 0, ATA_WAIT_IDLE);
01904 
01905     statusByte = UniataIsIdle(deviceExtension, statusByte);
01906     if(statusByte & IDE_STATUS_ERROR) {
01907         errorByte = AtapiReadPort1(&deviceExtension->chan[lChannel], IDX_IO1_i_Error);
01908         KdPrint2((PRINT_PREFIX "SetDriveParameters: Error bit set. Status %#x, error %#x\n",
01909                     errorByte, statusByte));
01910         return FALSE;
01911     }
01912 
01913     if(statusByte == IDE_STATUS_IDLE) {
01914         return TRUE;
01915     }
01916 
01917     return FALSE;
01918 
01919 } // end SetDriveParameters()
01920 
01921 VOID
01922 NTAPI
01923 UniataForgetDevice(
01924     PHW_LU_EXTENSION   LunExt
01925     )
01926 {
01927     LunExt->DeviceFlags &= DFLAGS_HIDDEN;
01928 } // end UniataForgetDevice()
01929 
01930 
01931 /*++
01932 
01933 Routine Description:
01934     Reset IDE controller and/or Atapi device.
01935 
01936 Arguments:
01937     HwDeviceExtension - HBA miniport driver's adapter data storage
01938 
01939 Return Value:
01940     Nothing.
01941 
01942 
01943 --*/
01944 BOOLEAN
01945 NTAPI
01946 AtapiResetController(
01947     IN PVOID HwDeviceExtension,
01948     IN ULONG PathId
01949     )
01950 {
01951     KdPrint2((PRINT_PREFIX "AtapiResetController()\n"));
01952     return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
01953 } // end AtapiResetController()
01954 
01955 
01956 BOOLEAN
01957 NTAPI
01958 AtapiResetController__(
01959     IN PVOID HwDeviceExtension,
01960     IN ULONG PathId,
01961     IN BOOLEAN CompleteType
01962     )
01963 {
01964     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
01965     ULONG                numberChannels  = deviceExtension->NumberChannels;
01966     PHW_CHANNEL          chan = NULL;
01967     ULONG i,j;
01968     ULONG MaxLuns;
01969     UCHAR statusByte;
01970     PSCSI_REQUEST_BLOCK CurSrb;
01971     ULONG ChannelCtrlFlags;
01972     UCHAR dma_status = 0;
01973 
01974     ULONG slotNumber = deviceExtension->slotNumber;
01975     ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
01976     ULONG VendorID =  deviceExtension->DevID        & 0xffff;
01977 #ifdef _DEBUG
01978     ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
01979 #endif
01980     //ULONG RevID    =  deviceExtension->RevID;
01981     ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
01982     //UCHAR tmp8;
01983     UCHAR tmp16;
01984 
01985     KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber));
01986 
01987     if(!deviceExtension->simplexOnly && (PathId != CHAN_NOT_SPECIFIED)) {
01988         // we shall reset both channels on SimplexOnly devices,
01989         // It's not worth doing so on normal controllers
01990         j = PathId;
01991         numberChannels = min(j+1, deviceExtension->NumberChannels);
01992     } else {
01993         j=0;
01994         numberChannels = deviceExtension->NumberChannels;
01995     }
01996 
01997     for (; j < numberChannels; j++) {
01998 
01999         KdPrint2((PRINT_PREFIX "AtapiResetController: Reset channel %d\n", j));
02000         chan = &deviceExtension->chan[j];
02001         KdPrint2((PRINT_PREFIX "  CompleteType %#x\n", CompleteType));
02002         //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
02003         MaxLuns = chan->NumberLuns;
02004         if(CompleteType != RESET_COMPLETE_NONE) {
02005 #ifndef UNIATA_CORE
02006             while((CurSrb = UniataGetCurRequest(chan))) {
02007 
02008                 PATA_REQ AtaReq = (PATA_REQ)(CurSrb->SrbExtension);
02009 
02010                 KdPrint2((PRINT_PREFIX "AtapiResetController: pending SRB %#x\n", CurSrb));
02011                 // Check and see if we are processing an internal srb
02012                 if (AtaReq->OriginalSrb) {
02013                     KdPrint2((PRINT_PREFIX "  restore original SRB %#x\n", AtaReq->OriginalSrb));
02014                     AtaReq->Srb = AtaReq->OriginalSrb;
02015                     AtaReq->OriginalSrb = NULL;
02016                     // NOTE: internal SRB doesn't get to SRB queue !!!
02017                     CurSrb = AtaReq->Srb;
02018                 }
02019 
02020                 // Remove current request from queue
02021                 UniataRemoveRequest(chan, CurSrb);
02022 
02023                 // Check if request is in progress.
02024                 ASSERT(AtaReq->Srb == CurSrb);
02025                 if (CurSrb) {
02026                     // Complete outstanding request with SRB_STATUS_BUS_RESET.
02027                     UCHAR PathId   = CurSrb->PathId;
02028                     UCHAR TargetId = CurSrb->TargetId;
02029                     UCHAR Lun = CurSrb->Lun;
02030 
02031                     CurSrb->SrbStatus = ((CompleteType == RESET_COMPLETE_ALL) ? SRB_STATUS_BUS_RESET : SRB_STATUS_ABORTED) | SRB_STATUS_AUTOSENSE_VALID;
02032                     CurSrb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
02033 
02034                     if (CurSrb->SenseInfoBuffer) {
02035 
02036                         PSENSE_DATA  senseBuffer = (PSENSE_DATA)CurSrb->SenseInfoBuffer;
02037 
02038                         senseBuffer->ErrorCode = 0x70;
02039                         senseBuffer->Valid     = 1;
02040                         senseBuffer->AdditionalSenseLength = 0xb;
02041                         if(CompleteType == RESET_COMPLETE_ALL) {
02042                             KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
02043                             senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
02044                             senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_BUS_RESET;
02045                             senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_SCSI_BUS;
02046                         } else {
02047                             KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
02048                             senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
02049                             senseBuffer->AdditionalSenseCode = 0;
02050                             senseBuffer->AdditionalSenseCodeQualifier = 0;
02051                         }
02052                     }
02053 
02054                     // Clear request tracking fields.
02055                     AtaReq->WordsLeft = 0;
02056                     AtaReq->DataBuffer = NULL;
02057                     AtaReq->TransferLength = 0;
02058 
02059                     ScsiPortNotification(RequestComplete,
02060                                          deviceExtension,
02061                                          CurSrb);
02062 
02063                     // Indicate ready for next request.
02064                     ScsiPortNotification(NextLuRequest,
02065                                          deviceExtension, 
02066                                          PathId,
02067                                          TargetId,
02068                                          Lun);
02069                 }
02070                 if(CompleteType != RESET_COMPLETE_ALL)
02071                     break;
02072             } // end while()
02073 #endif //UNIATA_CORE
02074         } // end if (!CompleteType != RESET_COMPLETE_NONE)
02075 
02076         // Save control flags
02077         ChannelCtrlFlags = chan->ChannelCtrlFlags;
02078         // Clear expecting interrupt flag.
02079         chan->ExpectingInterrupt = FALSE;
02080         chan->RDP = FALSE;
02081         chan->ChannelCtrlFlags = 0;
02082         InterlockedExchange(&(chan->CheckIntr),
02083                                       CHECK_INTR_IDLE);
02084         
02085         // Reset controller
02086         if(ChipFlags & UNIATA_AHCI) {
02087             KdPrint2((PRINT_PREFIX "  AHCI path\n"));
02088             UniataAhciReset(HwDeviceExtension, j);
02089         } else {
02090             KdPrint2((PRINT_PREFIX "  ATA path\n"));
02091             KdPrint2((PRINT_PREFIX "  disable intr (0)\n"));
02092             AtapiDisableInterrupts(deviceExtension, j);
02093             KdPrint2((PRINT_PREFIX "  done\n"));
02094             switch(VendorID) {
02095             case ATA_INTEL_ID: {
02096                 ULONG mask;
02097                 ULONG timeout;
02098                 if(!(ChipFlags & UNIATA_SATA))
02099                     goto default_reset;
02100                 if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
02101                     goto default_reset;
02102                 }
02103 
02104 #if 0
02105                 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
02106                 if(ChipFlags & UNIATA_AHCI) {
02107                     mask = 0x0005 << j;
02108                 } else {
02109                     /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
02110                     GetPciConfig1(0x90, tmp8);
02111                     if(tmp8 & 0x04) {
02112                         mask = 0x0003;
02113                     } else {
02114                         mask = 0x0001 << j;
02115                     }
02116                 }
02117 #else
02118                 mask = 1 << chan->lun[0]->SATA_lun_map;
02119                 if (MaxLuns > 1) {
02120                     mask |= (1 << chan->lun[1]->SATA_lun_map);
02121                 }
02122 #endif
02123                 ChangePciConfig2(0x92, a & ~mask);
02124                 AtapiStallExecution(10);
02125                 ChangePciConfig2(0x92, a | mask);
02126                 timeout = 100;
02127 
02128                 /* Wait up to 1 sec for "connect well". */
02129                 if (ChipFlags & (I6CH | I6CH2))
02130                     mask = mask << 8;
02131                 else
02132                     mask = mask << 4;
02133 
02134                 while (timeout--) {
02135                     AtapiStallExecution(10000);
02136                     GetPciConfig2(0x92, tmp16);
02137                     if ((tmp16 & mask) == mask) {
02138                         AtapiStallExecution(10000);
02139                         break;
02140                     }
02141                 }
02142                 break; }
02143             case ATA_SIS_ID:
02144             case ATA_NVIDIA_ID: {
02145                 KdPrint2((PRINT_PREFIX "  SIS/nVidia\n"));
02146                 if(!(ChipFlags & UNIATA_SATA))
02147                     goto default_reset;
02148                 break; }
02149             case ATA_SILICON_IMAGE_ID: {
02150                 ULONG offset;
02151                 ULONG Channel = deviceExtension->Channel + j;
02152                 if(!(ChipFlags & UNIATA_SATA))
02153                     goto default_reset;
02154                 offset = ((Channel & 1) << 7) + ((Channel & 2) << 8);
02155                 /* disable PHY state change interrupt */
02156                 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + offset, 0);
02157 
02158                 UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
02159 
02160                 /* reset controller part for this channel */
02161                 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
02162                      AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) | (0xc0 >> Channel));
02163                 AtapiStallExecution(1000);
02164                 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
02165                      AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) & ~(0xc0 >> Channel));
02166 
02167 
02168                 break; }
02169             case ATA_PROMISE_ID: {
02170                 break; }
02171             default:
02172                 if(ChipFlags & UNIATA_SATA) {
02173                     KdPrint2((PRINT_PREFIX "  SATA generic reset\n"));
02174                     UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
02175                 }
02176 default_reset:
02177                 KdPrint2((PRINT_PREFIX "  send reset\n"));
02178                 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
02179                                                                         IDE_DC_RESET_CONTROLLER );
02180                 KdPrint2((PRINT_PREFIX "  wait a little\n"));
02181                 AtapiStallExecution(10000);
02182                 // Disable interrupts
02183                 KdPrint2((PRINT_PREFIX "  disable intr\n"));
02184                 AtapiDisableInterrupts(deviceExtension, j);
02185                 AtapiStallExecution(100);
02186                 KdPrint2((PRINT_PREFIX "  re-enable intr\n"));
02187                 AtapiEnableInterrupts(deviceExtension, j);
02188                 KdPrint2((PRINT_PREFIX "  wait a little (2)\n"));
02189                 AtapiStallExecution(100000);
02190                 KdPrint2((PRINT_PREFIX "  done\n"));
02191 
02192                 break;
02193             } // end switch()
02194 
02195             //if(!(ChipFlags & UNIATA_SATA)) {}
02196             if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
02197                 // Reset DMA engine if active
02198                 KdPrint2((PRINT_PREFIX "  check DMA engine\n"));
02199                 dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
02200                 KdPrint2((PRINT_PREFIX "  DMA status %#x\n", dma_status));
02201                 if((ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
02202                    (dma_status & BM_STATUS_INTR)) {
02203                     AtapiDmaDone(HwDeviceExtension, 0, j, NULL);
02204                 }
02205             }
02206         } // ATA vs AHCI
02207 
02208         // all these shall be performed inside AtapiHwInitialize__() ?
02209 #if 1
02210         KdPrint2((PRINT_PREFIX "  process connected devices\n"));
02211         // Do special processing for ATAPI and IDE disk devices.
02212         for (i = 0; i < MaxLuns; i++) {
02213 
02214             // Check if device present.
02215             if (!(chan->lun[i]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
02216                 if(ChipFlags & UNIATA_AHCI) {
02217                     // everything is done in UniataAhciReset()
02218                     KdPrint2((PRINT_PREFIX "  device have gone\n"));
02219                     continue;
02220                 }
02221 #ifdef NAVO_TEST
02222                 continue;
02223 #else //NAVO_TEST
02224                 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
02225                 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
02226                     continue;
02227                 }
02228                 if(!CheckDevice(HwDeviceExtension, j, i, TRUE)) {
02229                     continue;
02230                 }
02231             } else {
02232                 if(ChipFlags & UNIATA_AHCI) {
02233                     // everything is done in UniataAhciReset()
02234                     KdPrint2((PRINT_PREFIX "  found some device\n"));
02235 
02236                     if(!IssueIdentify(HwDeviceExtension,
02237                                   i, j,
02238                              (chan->lun[i]->DeviceFlags & DFLAGS_ATAPI_DEVICE) ?
02239                                   IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY,
02240                                   FALSE)) {
02241                         KdPrint2((PRINT_PREFIX "  identify failed !\n"));
02242                         UniataForgetDevice(chan->lun[i]);
02243                     }
02244                     continue;
02245                 }
02246                 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
02247                     KdPrint2((PRINT_PREFIX "  device have gone\n"));
02248                     UniataForgetDevice(chan->lun[i]);
02249                 }
02250 #endif //NAVO_TEST
02251             }
02252 
02253             SelectDrive(chan, i);
02254             AtapiStallExecution(10);
02255             statusByte = WaitOnBusyLong(chan);
02256             statusByte = UniataIsIdle(deviceExtension, statusByte);
02257             if(statusByte == 0xff) {
02258                 KdPrint2((PRINT_PREFIX 
02259                            "no drive, status %#x\n",
02260                            statusByte));
02261                 UniataForgetDevice(chan->lun[i]);
02262             } else
02263             // Check for ATAPI disk.
02264             if (chan->lun[i]->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
02265                 // Issue soft reset and issue identify.
02266                 GetStatus(chan, statusByte);
02267                 KdPrint2((PRINT_PREFIX "AtapiResetController: Status before Atapi reset (%#x).\n",
02268                             statusByte));
02269 
02270                 AtapiDisableInterrupts(deviceExtension, j);
02271                 AtapiSoftReset(chan, i);
02272                 AtapiEnableInterrupts(deviceExtension, j);
02273 
02274                 GetStatus(chan, statusByte);
02275 
02276                 if(statusByte == IDE_STATUS_SUCCESS) {
02277 
02278                     IssueIdentify(HwDeviceExtension,
02279                                   i, j,
02280                                   IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
02281                 } else {
02282 
02283                     KdPrint2((PRINT_PREFIX 
02284                                "AtapiResetController: Status after soft reset %#x\n",
02285                                statusByte));
02286                 }
02287                 GetBaseStatus(chan, statusByte);
02288 
02289             } else {
02290                 // Issue identify and reinit after channel reset.
02291 
02292                 if (statusByte != IDE_STATUS_IDLE &&
02293                     statusByte != IDE_STATUS_SUCCESS &&
02294                     statusByte != IDE_STATUS_DRDY) {
02295 //                    result2 = FALSE;
02296                     KdPrint2((PRINT_PREFIX "AtapiResetController: IdeHardReset failed\n"));
02297                 } else
02298                 if(!IssueIdentify(HwDeviceExtension,
02299                                   i, j,
02300                                   IDE_COMMAND_IDENTIFY, FALSE)) {
02301 //                    result2 = FALSE;
02302                     KdPrint2((PRINT_PREFIX "AtapiResetController: IDE IssueIdentify failed\n"));
02303                 } else
02304                 // Set disk geometry parameters.
02305                 if (!SetDriveParameters(HwDeviceExtension, i, j)) {
02306                     KdPrint2((PRINT_PREFIX "AtapiResetController: SetDriveParameters failed\n"));
02307                 }
02308                 GetBaseStatus(chan, statusByte);
02309             }
02310             // force DMA mode reinit
02311             chan->lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
02312         }
02313 #endif //0
02314 
02315         // Enable interrupts, note, the we can have here recursive disable
02316         AtapiStallExecution(10);
02317         KdPrint2((PRINT_PREFIX "AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
02318             j,
02319             chan->DisableIntr));
02320         AtapiEnableInterrupts(deviceExtension, j);
02321 
02322         // Call the HwInitialize routine to setup multi-block.
02323         AtapiHwInitialize__(deviceExtension, j);
02324     } // for(channel)
02325     ScsiPortNotification(NextRequest, deviceExtension, NULL);
02326 
02327     return TRUE;
02328 
02329 } // end AtapiResetController__()
02330 
02331 
02332 /*++
02333 
02334 Routine Description:
02335     This routine maps ATAPI and IDE errors to specific SRB statuses.
02336 
02337 Arguments:
02338     HwDeviceExtension - HBA miniport driver's adapter data storage
02339     Srb - IO request packet
02340 
02341 Return Value:
02342     SRB status
02343 
02344 --*/
02345 ULONG
02346 NTAPI
02347 MapError(
02348     IN PVOID HwDeviceExtension,
02349     IN PSCSI_REQUEST_BLOCK Srb
02350     )
02351 {
02352     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
02353     ULONG lChannel = GET_CHANNEL(Srb);
02354     PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
02355 //    ULONG i;
02356     UCHAR errorByte;
02357     UCHAR srbStatus = SRB_STATUS_SUCCESS;
02358     UCHAR scsiStatus;
02359     ULONG DeviceNumber = GET_CDEV(Srb);
02360     PHW_LU_EXTENSION     LunExt = chan->lun[DeviceNumber];
02361 
02362     // Read the error register.
02363 
02364     errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
02365     KdPrint2((PRINT_PREFIX 
02366                "MapError: Error register is %#x\n",
02367                errorByte));
02368 
02369     if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
02370 
02371         switch (errorByte >> 4) {
02372         case SCSI_SENSE_NO_SENSE:
02373 
02374             KdPrint2((PRINT_PREFIX 
02375                        "ATAPI: No sense information\n"));
02376             scsiStatus = SCSISTAT_CHECK_CONDITION;
02377             srbStatus = SRB_STATUS_ERROR;
02378             break;
02379 
02380         case SCSI_SENSE_RECOVERED_ERROR:
02381 
02382             KdPrint2((PRINT_PREFIX 
02383                        "ATAPI: Recovered error\n"));
02384             scsiStatus = 0;
02385             srbStatus = SRB_STATUS_SUCCESS;
02386             break;
02387 
02388         case SCSI_SENSE_NOT_READY:
02389 
02390             KdPrint2((PRINT_PREFIX 
02391                        "ATAPI: Device not ready\n"));
02392             scsiStatus = SCSISTAT_CHECK_CONDITION;
02393             srbStatus = SRB_STATUS_ERROR;
02394             break;
02395 
02396         case SCSI_SENSE_MEDIUM_ERROR:
02397 
02398             KdPrint2((PRINT_PREFIX 
02399                        "ATAPI: Media error\n"));
02400             scsiStatus = SCSISTAT_CHECK_CONDITION;
02401             srbStatus = SRB_STATUS_ERROR;
02402             break;
02403 
02404         case SCSI_SENSE_HARDWARE_ERROR:
02405 
02406             KdPrint2((PRINT_PREFIX 
02407                        "ATAPI: Hardware error\n"));
02408             scsiStatus = SCSISTAT_CHECK_CONDITION;
02409             srbStatus = SRB_STATUS_ERROR;
02410             break;
02411 
02412         case SCSI_SENSE_ILLEGAL_REQUEST:
02413 
02414             KdPrint2((PRINT_PREFIX 
02415                        "ATAPI: Illegal request\n"));
02416             scsiStatus = SCSISTAT_CHECK_CONDITION;
02417             srbStatus = SRB_STATUS_ERROR;
02418             break;
02419 
02420         case SCSI_SENSE_UNIT_ATTENTION:
02421 
02422             KdPrint2((PRINT_PREFIX 
02423                        "ATAPI: Unit attention\n"));
02424             scsiStatus = SCSISTAT_CHECK_CONDITION;
02425             srbStatus = SRB_STATUS_ERROR;
02426             break;
02427 
02428         case SCSI_SENSE_DATA_PROTECT:
02429 
02430             KdPrint2((PRINT_PREFIX 
02431                        "ATAPI: Data protect\n"));
02432             scsiStatus = SCSISTAT_CHECK_CONDITION;
02433             srbStatus = SRB_STATUS_ERROR;
02434             break;
02435 
02436         case SCSI_SENSE_BLANK_CHECK:
02437 
02438             KdPrint2((PRINT_PREFIX 
02439                        "ATAPI: Blank check\n"));
02440             scsiStatus = SCSISTAT_CHECK_CONDITION;
02441             srbStatus = SRB_STATUS_ERROR;
02442             break;
02443 
02444         case SCSI_SENSE_ABORTED_COMMAND:
02445             KdPrint2((PRINT_PREFIX 
02446                         "Atapi: Command Aborted\n"));
02447             scsiStatus = SCSISTAT_CHECK_CONDITION;
02448             srbStatus = SRB_STATUS_ERROR;
02449             break;
02450 
02451         default:
02452 
02453             KdPrint2((PRINT_PREFIX 
02454                        "ATAPI: Invalid sense information\n"));
02455             scsiStatus = 0;
02456             srbStatus = SRB_STATUS_ERROR;
02457             break;
02458         }
02459 
02460     } else {
02461 
02462         scsiStatus = 0;
02463 
02464         // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
02465         chan->ReturningMediaStatus = errorByte;
02466 
02467         if (errorByte & IDE_ERROR_MEDIA_CHANGE_REQ) {
02468             KdPrint2((PRINT_PREFIX 
02469                        "IDE: Media change\n"));
02470             scsiStatus = SCSISTAT_CHECK_CONDITION;
02471             srbStatus = SRB_STATUS_ERROR;
02472 
02473             if (Srb->SenseInfoBuffer) {
02474 
02475                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
02476 
02477                 senseBuffer->ErrorCode = 0x70;
02478                 senseBuffer->Valid     = 1;
02479                 senseBuffer->AdditionalSenseLength = 0xb;
02480                 senseBuffer->SenseKey =  SCSI_SENSE_UNIT_ATTENTION;
02481                 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
02482                 senseBuffer->AdditionalSenseCodeQualifier = 0;
02483 
02484                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
02485             }
02486 
02487         } else if (errorByte & IDE_ERROR_COMMAND_ABORTED) {
02488             KdPrint2((PRINT_PREFIX 
02489                        "IDE: Command abort\n"));
02490             srbStatus = SRB_STATUS_ABORTED;
02491             scsiStatus = SCSISTAT_CHECK_CONDITION;
02492 
02493             if (Srb->SenseInfoBuffer) {
02494 
02495                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
02496 
02497                 senseBuffer->ErrorCode = 0x70;
02498                 senseBuffer->Valid     = 1;
02499                 senseBuffer->AdditionalSenseLength = 0xb;
02500                 senseBuffer->SenseKey =  SCSI_SENSE_ABORTED_COMMAND;
02501                 senseBuffer->AdditionalSenseCode = 0;
02502                 senseBuffer->AdditionalSenseCodeQualifier = 0;
02503 
02504                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
02505             }
02506 
02507             LunExt->ErrorCount++;
02508 
02509         } else if (errorByte & IDE_ERROR_END_OF_MEDIA) {
02510 
02511             KdPrint2((PRINT_PREFIX 
02512                        "IDE: End of media\n"));
02513             scsiStatus = SCSISTAT_CHECK_CONDITION;
02514             srbStatus = SRB_STATUS_ERROR;
02515 
02516             if (Srb->SenseInfoBuffer) {
02517 
02518                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
02519 
02520                 senseBuffer->ErrorCode = 0x70;
02521                 senseBuffer->Valid     = 1;
02522                 senseBuffer->AdditionalSenseLength = 0xb;
02523                 senseBuffer->SenseKey =  SCSI_SENSE_UNIT_ATTENTION;
02524                 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIA_STATE;
02525                 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_END_OF_MEDIUM;
02526                 senseBuffer->EndOfMedia = 1;
02527 
02528                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
02529             }
02530 
02531             if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
02532                 LunExt->ErrorCount++;
02533             }
02534 
02535         } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) {
02536 
02537             KdPrint2((PRINT_PREFIX 
02538                        "IDE: Illegal length\n"));
02539             srbStatus = SRB_STATUS_INVALID_REQUEST;
02540 
02541             if (Srb->SenseInfoBuffer) {
02542 
02543                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
02544 
02545                 senseBuffer->ErrorCode = 0x70;
02546                 senseBuffer->Valid     = 1;
02547                 senseBuffer->AdditionalSenseLength = 0xb;
02548                 senseBuffer->SenseKey =  SCSI_SENSE_ILLEGAL_REQUEST;
02549                 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_VALUE;
02550                 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_PARAM_INVALID_VALUE;
02551                 senseBuffer->IncorrectLength = 1;
02552 
02553                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
02554             }
02555 
02556         } else if (errorByte & IDE_ERROR_BAD_BLOCK) {
02557 
02558             KdPrint2((PRINT_PREFIX 
02559                        "IDE: Bad block\n"));
02560             srbStatus = SRB_STATUS_ERROR;
02561             scsiStatus = SCSISTAT_CHECK_CONDITION;
02562             if (Srb->SenseInfoBuffer) {
02563 
02564                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
02565 
02566                 senseBuffer->ErrorCode = 0x70;
02567                 senseBuffer->Valid     = 1;
02568                 senseBuffer->AdditionalSenseLength = 0xb;
02569                 senseBuffer->SenseKey =  SCSI_SENSE_MEDIUM_ERROR;
02570                 senseBuffer->AdditionalSenseCode = 0;
02571                 senseBuffer->AdditionalSenseCodeQualifier = 0;
02572 
02573                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
02574             }
02575 
02576         } else if (errorByte & IDE_ERROR_ID_NOT_FOUND) {
02577 
02578             KdPrint2((PRINT_PREFIX 
02579                        "IDE: Id not found\n"));
02580             srbStatus = SRB_STATUS_ERROR;
02581             scsiStatus = SCSISTAT_CHECK_CONDITION;
02582 
02583             if (Srb->SenseInfoBuffer) {
02584 
02585                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
02586 
02587                 senseBuffer->ErrorCode = 0x70;
02588                 senseBuffer->Valid     = 1;
02589                 senseBuffer->AdditionalSenseLength = 0xb;
02590                 senseBuffer->SenseKey =  SCSI_SENSE_MEDIUM_ERROR;
02591                 senseBuffer->AdditionalSenseCode = 0;
02592                 senseBuffer->AdditionalSenseCodeQualifier = 0;
02593 
02594                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
02595             }
02596 
02597             LunExt->ErrorCount++;
02598 
02599         } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) {
02600 
02601             KdPrint2((PRINT_PREFIX 
02602                        "IDE: Media change\n"));
02603             scsiStatus = SCSISTAT_CHECK_CONDITION;
02604             srbStatus = SRB_STATUS_ERROR;
02605 
02606             if (Srb->SenseInfoBuffer) {
02607 
02608                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
02609 
02610                 senseBuffer->ErrorCode = 0x70;
02611                 senseBuffer->Valid     = 1;
02612                 senseBuffer->AdditionalSenseLength = 0xb;
02613                 senseBuffer->SenseKey =  SCSI_SENSE_UNIT_ATTENTION;
02614                 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
02615                 senseBuffer->AdditionalSenseCodeQualifier = 0;
02616 
02617                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
02618             }
02619 
02620         } else if (errorByte & IDE_ERROR_DATA_ERROR) {
02621 
02622             KdPrint2((PRINT_PREFIX 
02623                    "IDE: Data error\n"));
02624             scsiStatus = SCSISTAT_CHECK_CONDITION;
02625             srbStatus = SRB_STATUS_ERROR;
02626 
02627             if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
02628                 LunExt->ErrorCount++;
02629             }
02630 
02631             // Build sense buffer
02632             if (Srb->SenseInfoBuffer) {
02633 
02634                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
02635 
02636                 senseBuffer->ErrorCode = 0x70;
02637                 senseBuffer->Valid     = 1;
02638                 senseBuffer->AdditionalSenseLength = 0xb;
02639                 senseBuffer->SenseKey =  SCSI_SENSE_MEDIUM_ERROR;
02640                 senseBuffer->AdditionalSenseCode = 0;
02641                 senseBuffer->AdditionalSenseCodeQualifier = 0;
02642 
02643                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
02644             }
02645         }
02646 
02647         if (LunExt->ErrorCount >= MAX_ERRORS) {
02648 //            deviceExtension->DWordIO = FALSE;
02649 
02650             KdPrint2((PRINT_PREFIX 
02651                         "MapError: ErrorCount >= MAX_ERRORS\n"));
02652 
02653             LunExt->DeviceFlags &= ~DFLAGS_DWORDIO_ENABLED;
02654             LunExt->MaximumBlockXfer = 0;
02655             BrutePoint();
02656 
02657             KdPrint2((PRINT_PREFIX 
02658                         "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
02659 
02660             // Log the error.
02661             KdPrint2((PRINT_PREFIX 
02662                         "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
02663                               HwDeviceExtension,
02664                               Srb,
02665                               Srb->PathId,
02666                               Srb->TargetId,
02667                               Srb->Lun,
02668                               SP_BAD_FW_WARNING,
02669                               4
02670                         ));
02671             ScsiPortLogError( HwDeviceExtension,
02672                               Srb,
02673                               Srb->PathId,
02674                               Srb->TargetId,
02675                               Srb->Lun,
02676                               SP_BAD_FW_WARNING,
02677                               4);
02678 
02679             // Reprogram to not use Multi-sector.
02680             UCHAR statusByte;
02681 
02682             if (LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT &&
02683                  !(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
02684 
02685                 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY);
02686 
02687                 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
02688                 // command was aborted.
02689                 if (statusByte & IDE_STATUS_ERROR) {
02690 
02691                     // Read the error register.
02692                     errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
02693 
02694                     KdPrint2((PRINT_PREFIX "MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
02695                                 statusByte,
02696                                 errorByte));
02697 
02698                     // Adjust the devExt. value, if necessary.
02699                     LunExt->MaximumBlockXfer = 0;
02700                     BrutePoint();
02701 
02702                 }
02703             }
02704         }
02705     }
02706 
02707     // Set SCSI status to indicate a check condition.
02708     Srb->ScsiStatus = scsiStatus;
02709 
02710     return srbStatus;
02711 
02712 } // end MapError()
02713 
02714 
02715 /*++
02716 
02717 Routine Description:
02718 
02719 Arguments:
02720     HwDeviceExtension - HBA miniport driver's adapter data storage
02721 
02722 Return Value:
02723     TRUE - if initialization successful.
02724     FALSE - if initialization unsuccessful.
02725 
02726 --*/
02727 BOOLEAN
02728 NTAPI
02729 AtapiHwInitialize(
02730     IN PVOID HwDeviceExtension
02731     )
02732 {
02733     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
02734     ULONG                numberChannels  = deviceExtension->NumberChannels;
02735     ULONG c;
02736 
02737     KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base)\n"));
02738 
02739     if(WinVer_WDM_Model) {
02740         AtapiResetController__(HwDeviceExtension, CHAN_NOT_SPECIFIED, RESET_COMPLETE_ALL);
02741     }
02742 
02743     /* do extra chipset specific setups */
02744     AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
02745 /*
02746     if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
02747         KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
02748         BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
02749     }
02750 */
02751     for (c = 0; c < numberChannels; c++) {
02752         AtapiHwInitialize__(deviceExtension, c);
02753     }
02754     KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base) done\n"));
02755     return TRUE;
02756 } // end AtapiHwInitialize()
02757 
02758 VOID
02759 NTAPI
02760 AtapiHwInitialize__(
02761     IN PHW_DEVICE_EXTENSION deviceExtension,
02762     IN ULONG lChannel
02763     )
02764 {
02765     ULONG i;
02766     UCHAR statusByte, errorByte;
02767     PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
02768     PHW_LU_EXTENSION     LunExt;
02769 //    ULONG tmp32;
02770     ULONG PreferedMode = 0xffffffff;
02771 
02772     AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
02773     FindDevices(deviceExtension, 0, lChannel);
02774 
02775     for (i = 0; i < chan->NumberLuns; i++) {
02776 
02777         KdPrint3((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel, i));
02778 
02779         LunExt = chan->lun[i];
02780         // skip empty slots
02781         if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
02782             continue;
02783         }
02784 
02785         AtapiDisableInterrupts(deviceExtension, lChannel);
02786         AtapiStallExecution(1);
02787 
02788         if (!(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
02789 
02790             KdPrint2((PRINT_PREFIX "AtapiHwInitialize: IDE branch\n"));
02791             // Enable media status notification
02792             IdeMediaStatus(TRUE,deviceExtension,lChannel,(UCHAR)i);
02793 
02794             // If supported, setup Multi-block transfers.
02795             statusByte = AtaCommand(deviceExtension, i, lChannel,
02796                                 IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
02797                                 LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
02798 
02799             // Check for errors. Reset the value to 0 (disable MultiBlock) if the
02800             // command was aborted.
02801             if (statusByte & IDE_STATUS_ERROR) {
02802 
02803                 // Read the error register.
02804                 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
02805 
02806                 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
02807                             statusByte,
02808                             errorByte));
02809 
02810                 statusByte = AtaCommand(deviceExtension, i, lChannel,
02811                                     IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
02812                                     LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
02813 
02814                 if (statusByte & IDE_STATUS_ERROR) {
02815                     // Read the error register.
02816                     errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
02817 
02818                     KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
02819                                 statusByte,
02820                                 errorByte));
02821                 }
02822                 // Adjust the devExt. value, if necessary.
02823                 LunExt->MaximumBlockXfer = 0;
02824 
02825             } else {
02826                 KdPrint2((PRINT_PREFIX 
02827                             "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
02828                             i,
02829                             LunExt->MaximumBlockXfer));
02830             }
02831 
02832             if(LunExt->IdentifyData.MajorRevision) {
02833             
02834                 if(LunExt->opt_ReadCacheEnable) {
02835                     KdPrint2((PRINT_PREFIX "  Try Enable Read Cache\n"));
02836                     // If supported, setup read/write cacheing
02837                     statusByte = AtaCommand(deviceExtension, i, lChannel,
02838                                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
02839                                         0, ATA_C_F_ENAB_RCACHE, ATA_WAIT_BASE_READY);
02840 
02841                     // Check for errors.
02842                     if (statusByte & IDE_STATUS_ERROR) {
02843                         KdPrint2((PRINT_PREFIX 
02844                                     "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
02845                                     i));
02846                         LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
02847                     } else {
02848                         LunExt->DeviceFlags |= DFLAGS_RCACHE_ENABLED;
02849                     }
02850                 } else {
02851                     KdPrint2((PRINT_PREFIX "  Disable Read Cache\n"));
02852                     statusByte = AtaCommand(deviceExtension, i, lChannel,
02853                                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
02854                                         0, ATA_C_F_DIS_RCACHE, ATA_WAIT_BASE_READY);
02855                     LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
02856                 }
02857                 if(LunExt->opt_WriteCacheEnable) {
02858                     KdPrint2((PRINT_PREFIX "  Try Enable Write Cache\n"));
02859                     // If supported & allowed, setup write cacheing
02860                     statusByte = AtaCommand(deviceExtension, i, lChannel,
02861                                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
02862                                         0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
02863                     // Check for errors.
02864                     if (statusByte & IDE_STATUS_ERROR) {
02865                         KdPrint2((PRINT_PREFIX 
02866                                     "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
02867                                     i));
02868                         LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
02869                     } else {
02870                         LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
02871                     }
02872                 } else {
02873                     KdPrint2((PRINT_PREFIX "  Disable Write Cache\n"));
02874                     statusByte = AtaCommand(deviceExtension, i, lChannel,
02875                                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
02876                                         0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
02877                     LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
02878                 }
02879             }
02880 
02881         } else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){
02882 
02883             ULONG j;
02884             BOOLEAN isSanyo = FALSE;
02885             CCHAR vendorId[26];
02886 
02887             KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n"));
02888 
02889             // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
02890             for (j = 0; j < 26; j += 2) {
02891 
02892                 // Build a buffer based on the identify data.
02893                 MOV_DW_SWP(vendorId[j], ((PUCHAR)LunExt->IdentifyData.ModelNumber)[j]);
02894             }
02895 
02896             if (!AtapiStringCmp (vendorId, "CD-ROM  CDR", 11)) {
02897 
02898                 // Inquiry string for older model had a '-', newer is '_'
02899                 if (vendorId[12] == 'C') {
02900 
02901                     // Torisan changer. Set the bit. This will be used in several places
02902                     // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
02903                     LunExt->DeviceFlags |= (DFLAGS_CHANGER_INITED | DFLAGS_SANYO_ATAPI_CHANGER);
02904                     LunExt->DiscsPresent = 3;
02905                     isSanyo = TRUE;
02906                 }
02907             }
02908         }
02909 
02910         PreferedMode = LunExt->opt_MaxTransferMode;
02911         if(PreferedMode == 0xffffffff) {
02912             KdPrint2((PRINT_PREFIX "MaxTransferMode (overriden): %#x\n", chan->MaxTransferMode));
02913             PreferedMode = chan->MaxTransferMode;
02914         }
02915 
02916         if(LunExt->opt_PreferedTransferMode != 0xffffffff) {
02917             KdPrint2((PRINT_PREFIX "PreferedTransferMode: %#x\n", PreferedMode));
02918             PreferedMode = min(LunExt->opt_PreferedTransferMode, PreferedMode);
02919         }
02920 
02921         KdPrint2((PRINT_PREFIX "  try mode %#x\n", PreferedMode));
02922         LunExt->OrigTransferMode =
02923         LunExt->LimitedTransferMode =
02924         LunExt->TransferMode =
02925             (CHAR)PreferedMode;
02926 
02927         AtapiDmaInit__(deviceExtension, LunExt);
02928 
02929         LunExt->OrigTransferMode =
02930         LunExt->LimitedTransferMode =
02931             LunExt->TransferMode;
02932         KdPrint2((PRINT_PREFIX "Using %#x mode\n", LunExt->TransferMode));
02933 
02934         // We need to get our device ready for action before
02935         // returning from this function
02936 
02937         // According to the atapi spec 2.5 or 2.6, an atapi device
02938         // clears its status BSY bit when it is ready for atapi commands.
02939         // However, some devices (Panasonic SQ-TC500N) are still
02940         // not ready even when the status BSY is clear.  They don't react
02941         // to atapi commands.
02942         //
02943         // Since there is really no other indication that tells us
02944         // the drive is really ready for action.  We are going to check BSY
02945         // is clear and then just wait for an arbitrary amount of time!
02946         //
02947         if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
02948             ULONG waitCount;
02949 
02950             // have to get out of the loop sometime!
02951             // 10000 * 100us = 1000,000us = 1000ms = 1s
02952             waitCount = 10000;
02953             GetStatus(chan, statusByte);
02954             while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
02955 
02956                 KdPrint2((PRINT_PREFIX "Wait for ATAPI (status %x\n)", statusByte));
02957                 // Wait for Busy to drop.
02958                 AtapiStallExecution(100);
02959                 GetStatus(chan, statusByte);
02960                 waitCount--;
02961             }
02962 
02963             // 5000 * 100us = 500,000us = 500ms = 0.5s
02964             waitCount = 5000;
02965             do {
02966                 AtapiStallExecution(100);
02967             } while (waitCount--);
02968         }
02969         GetBaseStatus(chan, statusByte);
02970         AtapiEnableInterrupts(deviceExtension, lChannel);
02971         AtapiStallExecution(10);
02972     }
02973 
02974     return;
02975 
02976 } // end AtapiHwInitialize()
02977 
02978 
02979 #ifndef UNIATA_CORE
02980 
02981 VOID
02982 NTAPI
02983 AtapiHwInitializeChanger(
02984     IN PVOID HwDeviceExtension,
02985     IN PSCSI_REQUEST_BLOCK Srb,
02986     IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus)
02987 {
02988     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
02989     ULONG lChannel = GET_CHANNEL(Srb);
02990     PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
02991     ULONG DeviceNumber = GET_CDEV(Srb);
02992     PHW_LU_EXTENSION     LunExt = chan->lun[DeviceNumber];
02993 
02994     if (MechanismStatus) {
02995         LunExt->DiscsPresent = MechanismStatus->NumberAvailableSlots;
02996         if (LunExt->DiscsPresent > 1) {
02997             LunExt->DeviceFlags |= DFLAGS_ATAPI_CHANGER;
02998         }
02999     }
03000     return;
03001 } // end AtapiHwInitializeChanger()
03002 
03003 
03004 /*++
03005 
03006 Routine Description:
03007     This routine will parse the string for a match on the keyword, then
03008     calculate the value for the keyword and return it to the caller.
03009 
03010 Arguments:
03011     String - The ASCII string to parse.
03012     KeyWord - The keyword for the value desired.
03013 
03014 Return Values:
03015     Zero if value not found
03016     Value converted from ASCII to binary.
03017 
03018 --*/
03019 ULONG
03020 NTAPI
03021 AtapiParseArgumentString(
03022     IN PCCH String,
03023     IN PCCH KeyWord
03024     )
03025 {
03026     PCCH cptr;
03027     PCCH kptr;
03028     ULONG value;
03029     ULONG stringLength = 0;
03030     ULONG keyWordLength = 0;
03031     ULONG index;
03032 
03033     if (!String) {
03034         return 0;
03035     }
03036     if (!KeyWord) {
03037         return 0;
03038     }
03039 
03040     // Calculate the string length and lower case all characters.
03041     cptr = String;
03042     while (*cptr++) {
03043         stringLength++;
03044     }
03045 
03046     // Calculate the keyword length.
03047     kptr = KeyWord;
03048     while (*kptr++) {
03049         keyWordLength++;
03050     }
03051 
03052     if (keyWordLength > stringLength) {
03053 
03054         // Can't possibly have a match.
03055         return 0;
03056     }
03057 
03058     // Now setup and start the compare.
03059     cptr = String;
03060 
03061 ContinueSearch:
03062 
03063     // The input string may start with white space.  Skip it.
03064     while (*cptr == ' ' || *cptr == '\t') {
03065         cptr++;
03066     }
03067 
03068     if (*cptr == '\0') {
03069         // end of string.
03070         return 0;
03071     }
03072 
03073     kptr = KeyWord;
03074     while ((*cptr == *kptr) ||
03075            (*cptr >= 'A' && *cptr <= 'Z' && *cptr + ('a' - 'A') == *kptr) ||
03076            (*cptr >= 'a' && *cptr <= 'z' && *cptr - ('a' - 'A') == *kptr)) {
03077         cptr++;
03078         kptr++;
03079 
03080         if (*cptr == '\0') {
03081             // end of string
03082             return 0;
03083         }
03084     }
03085 
03086     if (*kptr == '\0') {
03087 
03088         // May have a match backup and check for blank or equals.
03089         while (*cptr == ' ' || *cptr == '\t') {
03090             cptr++;
03091         }
03092 
03093         // Found a match.  Make sure there is an equals.
03094         if (*cptr != '=') {
03095 
03096             // Not a match so move to the next semicolon.
03097             while (*cptr) {
03098                 if (*cptr++ == ';') {
03099                     goto ContinueSearch;
03100                 }
03101             }
03102             return 0;
03103         }
03104         // Skip the equals sign.
03105         cptr++;
03106 
03107         // Skip white space.
03108         while ((*cptr == ' ') || (*cptr == '\t')) {
03109             cptr++;
03110         }
03111 
03112         if (*cptr == '\0') {
03113             // Early end of string, return not found
03114             return 0;
03115         }
03116 
03117         if (*cptr == ';') {
03118             // This isn't it either.
03119             cptr++;
03120             goto ContinueSearch;
03121         }
03122 
03123         value = 0;
03124         if ((*cptr == '0') && ((*(cptr + 1) == 'x') || (*(cptr + 1) == 'X'))) {
03125             // Value is in Hex.  Skip the "0x"
03126             cptr += 2;
03127             for (index = 0; *(cptr + index); index++) {
03128 
03129                 if (*(cptr + index) == ' ' ||
03130                     *(cptr + index) == '\t' ||
03131                     *(cptr + index) == ';') {
03132                      break;
03133                 }
03134 
03135                 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
03136                     value = (16 * value) + (*(cptr + index) - '0');
03137                 } else {
03138                     if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
03139                         value = (16 * value) + (*(cptr + index) - 'a' + 10);
03140                     } else if ((*(cptr + index) >= 'A') && (*(cptr + index) <= 'F')) {
03141                         value = (16 * value) + (*(cptr + index) - 'A' + 10);
03142                     } else {
03143                         // Syntax error, return not found.
03144                         return 0;
03145                     }
03146                 }
03147             }
03148         } else {
03149 
03150             // Value is in Decimal.
03151             for (index = 0; *(cptr + index); index++) {
03152 
03153                 if (*(cptr + index) == ' ' ||
03154                     *(cptr + index) == '\t' ||
03155                     *(cptr + index) == ';') {
03156                      break;
03157                 }
03158 
03159                 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
03160                     value = (10 * value) + (*(cptr + index) - '0');
03161                 } else {
03162 
03163                     // Syntax error return not found.
03164                     return 0;
03165                 }
03166             }
03167         }
03168 
03169         return value;
03170     } else {
03171 
03172         // Not a match check for ';' to continue search.
03173         while (*cptr) {
03174             if (*cptr++ == ';') {
03175                 goto ContinueSearch;
03176             }
03177         }
03178 
03179         return 0;
03180     }
03181 } // end AtapiParseArgumentString()_
03182 
03183 /*
03184     Timer callback
03185 */
03186 VOID
03187 NTAPI
03188 AtapiCallBack__(
03189     IN PVOID HwDeviceExtension,
03190     IN UCHAR lChannel
03191     )
03192 {
03193 
03194     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
03195     PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
03196     ULONG c, _c;
03197 
03198     PSCSI_REQUEST_BLOCK  srb = UniataGetCurRequest(chan);
03199     UCHAR statusByte;
03200 
03201     KdPrint2((PRINT_PREFIX "AtapiCallBack:\n"));
03202     // If the last command was DSC restrictive, see if it's set. If so, the device is
03203     // ready for a new request. Otherwise, reset the timer and come back to here later.
03204 
03205     // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
03206     // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
03207     // we shall have no problem with interrupt handler.
03208     if (!srb || chan->ExpectingInterrupt) {
03209         KdPrint2((PRINT_PREFIX "AtapiCallBack: Calling ISR directly due to BUSY\n"));
03210         chan->DpcState = DPC_STATE_TIMER;
03211         if(!AtapiInterrupt__(HwDeviceExtension, lChannel)) {
03212             InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
03213             KdPrint2((PRINT_PREFIX "AtapiCallBack: What's fucking this ???\n"));
03214         }
03215         goto ReturnCallback;
03216     }
03217 
03218 #ifdef DBG
03219     if (!IS_RDP((srb->Cdb[0]))) {
03220         KdPrint2((PRINT_PREFIX "AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb->Cdb[0]));
03221     }
03222 #endif
03223     if(!(chan->RDP)) {
03224         goto ReturnEnableIntr;
03225     }
03226     GetStatus(chan, statusByte);
03227     if (statusByte & IDE_STATUS_DSC) {
03228 
03229         UCHAR PathId   = srb->PathId;
03230         UCHAR TargetId = srb->TargetId;
03231         UCHAR Lun      = srb->Lun;
03232 
03233         KdPrint2((PRINT_PREFIX "AtapiCallBack: Found DSC for RDP - %#x\n", srb->Cdb[0]));
03234         AtapiDmaDBSync(chan, srb);
03235         UniataRemoveRequest(chan, srb);
03236         ScsiPortNotification(RequestComplete, deviceExtension, srb);
03237         // Clear current SRB.
03238         if(!deviceExtension->simplexOnly) {
03239             srb = UniataGetCurRequest(chan);
03240         } else {
03241             srb = NULL;
03242         }
03243         chan->RDP = FALSE;
03244 
03245         // Ask for next request.
03246         ScsiPortNotification(NextLuRequest,
03247                              deviceExtension, 
03248                              PathId,
03249                              TargetId,
03250                              Lun);
03251         ScsiPortNotification(NextRequest, deviceExtension, NULL);
03252 
03253         if(srb) {
03254             AtapiStartIo__(HwDeviceExtension, srb, FALSE);
03255         }
03256 
03257     } else {
03258         KdPrint2((PRINT_PREFIX "AtapiCallBack: Requesting another timer for Op %#x\n",
03259                     srb->Cdb[0]));
03260 
03261         AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
03262                              AtapiCallBack_X,
03263                              1000);
03264 
03265         goto ReturnCallback;
03266     }
03267 
03268 ReturnEnableIntr:
03269 
03270     if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
03271         KdPrint2((PRINT_PREFIX "AtapiCallBack: CallDisableInterrupts\n"));
03272         //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
03273 #ifdef UNIATA_USE_XXableInterrupts
03274         chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
03275         // must be called on DISPATCH_LEVEL
03276         ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
03277                              AtapiEnableInterrupts__);
03278 #else
03279         AtapiEnableInterrupts(HwDeviceExtension, lChannel);
03280         InterlockedExchange(&(chan->CheckIntr),
03281                                       CHECK_INTR_IDLE);
03282         // Will raise IRQL to DIRQL
03283         AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
03284                              AtapiEnableInterrupts__,
03285                              1);
03286         KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
03287 #endif // UNIATA_USE_XXableInterrupts
03288     } else {
03289         //ASSERT(!deviceExtension->simplexOnly);
03290     }
03291 
03292 ReturnCallback:
03293 
03294     // Check other channel
03295     // In simplex mode no interrupts must appear on other channels
03296     for(_c=0; _c<deviceExtension->NumberChannels-1; _c++) {
03297         c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
03298 
03299         chan = &(deviceExtension->chan[c]);
03300 
03301         if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
03302                                       CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
03303                                       CRNT_ILK_TYPE CHECK_INTR_DETECTED) == CHECK_INTR_DETECTED)
03304         {
03305             //ASSERT(!deviceExtension->simplexOnly);
03306             chan->DpcState = DPC_STATE_ISR;
03307             if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
03308                 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
03309             }
03310         }
03311     }
03312     KdPrint2((PRINT_PREFIX "AtapiCallBack: return\n"));
03313     return;
03314 
03315 } // end AtapiCallBack__()
03316 
03317 VOID
03318 NTAPI
03319 AtapiCallBack_X(
03320     IN PVOID HwDeviceExtension
03321     )
03322 {
03323     AtapiCallBack__(HwDeviceExtension, (UCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->ActiveDpcChan);
03324 }
03325 
03326 #endif //UNIATA_CORE
03327 
03328 /*++
03329 
03330 Routine Description:
03331 
03332     This is the interrupt service routine for ATAPI IDE miniport driver.
03333 
03334 Arguments:
03335 
03336     HwDeviceExtension - HBA miniport driver's adapter data storage
03337 
03338 Return Value:
03339 
03340     TRUE if expecting an interrupt.
03341 
03342 --*/
03343 BOOLEAN
03344 NTAPI
03345 AtapiInterrupt(
03346     IN PVOID HwDeviceExtension
03347     )
03348 {
03349     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
03350     ULONG c, _c;
03351     BOOLEAN status = FALSE;
03352     ULONG c_state;
03353     ULONG i_res = 0;
03354     ULONG pass;
03355     BOOLEAN checked[AHCI_MAX_PORT];
03356     ULONG hIS;
03357 
03358     KdPrint2((PRINT_PREFIX "Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
03359 
03360     if(deviceExtension->HwFlags & UNIATA_AHCI) {
03361         hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
03362         KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
03363         if(!hIS) {
03364             return FALSE;
03365         }
03366     }
03367 
03368     for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
03369         checked[_c] = FALSE;
03370     }
03371 
03372 //    fc = 
03373     for(pass=0; pass<2; pass++) {
03374         for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
03375 
03376             c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
03377 
03378             if(checked[c])
03379                 continue;
03380 
03381             // check non-empty and expecting interrupt channels first
03382             if(!pass && !deviceExtension->chan[c].ExpectingInterrupt)
03383                 continue;
03384 
03385             checked[c] = TRUE;
03386 
03387             KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
03388 
03389             if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
03390                 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): disabled INTR on ch %d\n", c));
03391                 continue;
03392             }
03393             // lock channel. Wait, while 2nd ISR checks interrupt on this channel
03394             do {
03395                 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): try lock\n"));
03396                 // c_state = deviceExtension->chan[c].CheckIntr;
03397                 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
03398                 //     deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
03399                 // }
03400                 c_state =
03401                     (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
03402                                               CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
03403                                               CRNT_ILK_TYPE CHECK_INTR_DETECTED);
03404                 if(c_state == CHECK_INTR_IDLE) {
03405                     // c_state = deviceExtension->chan[c].CheckIntr;
03406                     // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
03407                     //     deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
03408                     // }
03409                     c_state =
03410                         (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
03411                                                   CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
03412                                                   CRNT_ILK_TYPE CHECK_INTR_IDLE);
03413                 }
03414             } while(c_state == CHECK_INTR_CHECK);
03415             KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): locked\n"));
03416             // check if already serviced
03417             if(c_state == CHECK_INTR_ACTIVE) {
03418                 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
03419                 continue;
03420             }
03421 
03422             if((c_state == CHECK_INTR_DETECTED) ||
03423                (i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
03424 
03425                 if(i_res == INTERRUPT_REASON_UNEXPECTED) {
03426                     KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): Catch unexpected\n"));
03427                     InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
03428                     return TRUE;
03429                 }
03430                 // disable interrupts on other channel of legacy mode
03431                 // ISA-bridged onboard controller
03432                 if(deviceExtension->simplexOnly /*||
03433                    ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
03434                     AtapiDisableInterrupts(deviceExtension, !c);
03435                 }
03436 
03437                 deviceExtension->chan[c].DpcState = DPC_STATE_ISR;
03438                 if(AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
03439                     deviceExtension->LastInterruptedChannel = (UCHAR)c;
03440                     KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): return status TRUE\n"));
03441                     status = TRUE;
03442                 } else {
03443                     KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
03444                     InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
03445                 }
03446 
03447                 // re-enable interrupts on other channel
03448                 if(deviceExtension->simplexOnly /*||
03449                    ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
03450                     AtapiEnableInterrupts(deviceExtension, !c);
03451                 }
03452 
03453             } else {
03454                 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
03455                 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
03456             }
03457 
03458         }
03459     }
03460     KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): exit with status %#x\n", status));
03461     if(status) {
03462         deviceExtension->FirstChannelToCheck++;
03463         if(deviceExtension->FirstChannelToCheck >= deviceExtension->NumberChannels)
03464             deviceExtension->FirstChannelToCheck = 0;
03465     }
03466     return status;
03467 } // end AtapiInterrupt()
03468 
03469 //ULONG i2c = 0;
03470 #ifndef UNIATA_CORE
03471 
03472 BOOLEAN
03473 NTAPI
03474 AtapiInterrupt2(
03475     IN PKINTERRUPT Interrupt,
03476     IN PVOID Isr2HwDeviceExtension
03477     )
03478 {
03479 
03480     PISR2_DEVICE_EXTENSION Isr2DeviceExtension = (PISR2_DEVICE_EXTENSION)Isr2HwDeviceExtension;
03481     PHW_DEVICE_EXTENSION deviceExtension = Isr2DeviceExtension->HwDeviceExtension;
03482     ULONG c;
03483     BOOLEAN status = FALSE;
03484     ULONG c_count = 0;
03485     ULONG i_res;
03486     ULONG hIS;
03487 
03488     // we should never get here for ISA/MCA
03489     if(!BMList[deviceExtension->DevIndex].Isr2Enable) {
03490         KdPrint2((PRINT_PREFIX "AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension->DevIndex, deviceExtension->Channel));
03491         return FALSE;
03492     }
03493 
03494     if(deviceExtension->HwFlags & UNIATA_AHCI) {
03495         hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
03496         KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
03497         if(!hIS) {
03498             return FALSE;
03499         }
03500     }
03501 
03502     for(c=0; c<deviceExtension->NumberChannels; c++) {
03503         KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
03504 
03505         if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
03506             KdPrint2((PRINT_PREFIX "AtapiInterrupt2: disabled INTR\n"));
03507             continue;
03508         }
03509 
03510         if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
03511                                       CRNT_ILK_TYPE CHECK_INTR_CHECK,
03512                                       CRNT_ILK_TYPE CHECK_INTR_IDLE) != CHECK_INTR_IDLE)
03513         {
03514             KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
03515             // hunt on unexpected intr (Some devices generate double interrupts,
03516             // some controllers (at least CMD649) interrupt twice with small delay.
03517             // If interrupts are disabled, they queue interrupt and re-issue it later,
03518             // when we do not expect it.
03519             continue;
03520         }
03521 
03522         c_count++;
03523         if((i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
03524 
03525             KdPrint2((PRINT_PREFIX "AtapiInterrupt2: intr\n"));
03526             if(i_res == INTERRUPT_REASON_UNEXPECTED) {
03527                 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: Catch unexpected\n"));
03528                 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
03529                 return TRUE;
03530             }
03531 
03532             status = TRUE;
03533             InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_DETECTED);
03534         } else {
03535             InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
03536         }
03537     }
03538     KdPrint2((PRINT_PREFIX "AtapiInterrupt2: status %d, c_count %d\n", status, c_count));
03539     if(status && (c_count != deviceExtension->NumberChannels)) {
03540         // there is an active ISR/DPC for one channel, but
03541         // we have an interrupt from another one
03542         // Lets inform current ISR/DPC about new interrupt
03543         InterlockedExchange(&(deviceExtension->ReCheckIntr), CHECK_INTR_DETECTED);
03544     } else {
03545         status = FALSE;
03546     }
03547     KdPrint2((PRINT_PREFIX "AtapiInterrupt2: return %d\n", status));
03548     return status;
03549     
03550 } // end AtapiInterrupt2()
03551 
03552 RETTYPE_XXableInterrupts
03553 NTAPI
03554 AtapiInterruptDpc(
03555     IN PVOID HwDeviceExtension
03556     )
03557 {
03558     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
03559     ULONG c;
03560 
03561     for(c=0; c<deviceExtension->NumberChannels; c++) {
03562         KdPrint2((PRINT_PREFIX "AtapiInterruptDpc: %#x\n",c));
03563 
03564         if(!(deviceExtension->chan[c].ChannelCtrlFlags & CTRFLAGS_DPC_REQ)) {
03565 
03566             if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
03567                                           CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
03568                                           CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED)
03569             {
03570                 continue;
03571             }
03572                         
03573         } else {
03574             deviceExtension->chan[c].ChannelCtrlFlags &= ~CTRFLAGS_DPC_REQ;
03575         }
03576 /*
03577         if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
03578             AtapiDisableInterrupts(deviceExtension, lChannel);
03579         }
03580 */
03581         deviceExtension->chan[c].DpcState = DPC_STATE_DPC;
03582         if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
03583             InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
03584         }
03585     }
03586     return RETVAL_XXableInterrupts;
03587 } // end AtapiInterruptDpc()
03588 
03589 
03590 RETTYPE_XXableInterrupts
03591 NTAPI
03592 AtapiEnableInterrupts__(
03593     IN PVOID HwDeviceExtension
03594     )
03595 {
03596     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
03597     KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__():\n"));
03598     ULONG c;
03599     PHW_CHANNEL chan = NULL;
03600 
03601     for(c=0; c<deviceExtension->NumberChannels; c++) {
03602         KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__(2): %#x\n",c));
03603         chan = &(deviceExtension->chan[c]);
03604 
03605         if(chan->ChannelCtrlFlags & CTRFLAGS_ENABLE_INTR_REQ) {
03606             // enable intrs on requested channel
03607             chan->ChannelCtrlFlags &= ~CTRFLAGS_ENABLE_INTR_REQ;
03608             AtapiEnableInterrupts(HwDeviceExtension, c);
03609             InterlockedExchange(&(chan->CheckIntr),
03610                                           CHECK_INTR_IDLE);
03611 
03612             // check if current or other channel(s) interrupted
03613             //AtapiInterrupt(HwDeviceExtension);
03614 
03615             if(deviceExtension->simplexOnly) {
03616                 break;
03617             }
03618         } else {
03619             // check if other channel(s) interrupted
03620             // must do nothing in simplex mode
03621             if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
03622                                           CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
03623                                           CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) {
03624                 continue;
03625             }
03626             //ASSERT(!deviceExtension->simplexOnly);
03627             chan->DpcState = DPC_STATE_ISR;
03628             if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
03629                 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
03630             }
03631         }
03632     }
03633     // In simplex mode next command must be sent to device here
03634     if(deviceExtension->simplexOnly && chan) {
03635         PSCSI_REQUEST_BLOCK srb;
03636         chan = UniataGetNextChannel(chan);
03637         if(chan) {
03638             srb = UniataGetCurRequest(chan);
03639         } else {
03640             srb = NULL;
03641         }
03642         if(srb) {
03643             AtapiStartIo__(HwDeviceExtension, srb, FALSE);
03644         }
03645     }
03646 
03647     return RETVAL_XXableInterrupts;
03648 
03649 } // end AtapiEnableInterrupts__()
03650 
03651 #endif //UNIATA_CORE
03652 
03653 
03654 VOID
03655 NTAPI
03656 AtapiEnableInterrupts(
03657     IN PVOID HwDeviceExtension,
03658     IN ULONG c
03659     )
03660 {
03661     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
03662     PHW_CHANNEL chan;
03663     if(c >= deviceExtension->NumberChannels) {
03664         KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c));
03665         return;
03666     }
03667     chan = &(deviceExtension->chan[c]);
03668     KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr));
03669     if(!InterlockedDecrement(&chan->DisableIntr)) {
03670         if(deviceExtension->HwFlags & UNIATA_AHCI) {
03671             UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
03672         } else {
03673             AtapiWritePort1(chan, IDX_IO2_o_Control,
03674                                    IDE_DC_A_4BIT );
03675         }
03676         chan->ChannelCtrlFlags &= ~CTRFLAGS_INTR_DISABLED;
03677     } else {
03678         AtapiWritePort1(chan, IDX_IO2_o_Control,
03679                                IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
03680     }
03681     return;
03682 } // end AtapiEnableInterrupts()
03683 
03684 VOID
03685 NTAPI
03686 AtapiDisableInterrupts(
03687     IN PVOID HwDeviceExtension,
03688     IN ULONG c
03689     )
03690 {
03691     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
03692     PHW_CHANNEL chan;
03693     if(c >= deviceExtension->NumberChannels) {
03694         KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c));
03695         return;
03696     }
03697     chan = &(deviceExtension->chan[c]);
03698     KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: %d\n",c, chan->DisableIntr));
03699     // mark channel as busy
03700     if(InterlockedIncrement(&chan->DisableIntr)) {
03701         if(deviceExtension->HwFlags & UNIATA_AHCI) {
03702             UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE,
03703                 (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
03704                  ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
03705                  ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) |
03706                  ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB |
03707                  ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)
03708                 );
03709         } else {
03710             AtapiWritePort1(chan, IDX_IO2_o_Control,
03711                                    IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
03712         }
03713         chan->ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED;
03714     }
03715 
03716     return;
03717 } // end AtapiDisableInterrupts()
03718 
03719 
03720 /*
03721     Check hardware for interrupt state
03722  */
03723 BOOLEAN
03724 NTAPI
03725 AtapiCheckInterrupt__(
03726     IN PVOID HwDeviceExtension,
03727     IN UCHAR c // logical channel
03728     )
03729 {
03730     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
03731     PHW_CHANNEL chan = &(deviceExtension->chan[c]);
03732     PHW_LU_EXTENSION LunExt;
03733 
03734     ULONG VendorID  = deviceExtension->DevID & 0xffff;
03735     ULONG ChipType  = deviceExtension->HwFlags & CHIPTYPE_MASK;
03736 
03737     ULONG status;
03738     ULONG pr_status = 0;
03739     UCHAR dma_status = 0;
03740     UCHAR reg8 = 0;
03741     ULONG reg32 = 0;
03742     UCHAR statusByte;
03743     ULONG slotNumber = deviceExtension->slotNumber;
03744     ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
03745     ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
03746     UCHAR Channel;
03747     UCHAR lChannel;
03748     BOOLEAN DmaTransfer = FALSE;
03749     BOOLEAN OurInterrupt = FALSE;
03750 //    ULONG k;
03751     UCHAR interruptReason;
03752     BOOLEAN EarlyIntr = FALSE;
03753 
03754     KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__:\n"));
03755 
03756     lChannel = c;
03757     Channel = (UCHAR)(deviceExtension->Channel + lChannel);
03758 
03759     if((ChipFlags & UNIATA_AHCI) &&
03760         UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
03761         OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, -1);
03762         return OurInterrupt;
03763     }
03764 
03765     if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
03766         DmaTransfer = TRUE;
03767         KdPrint2((PRINT_PREFIX "  cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension->DevIndex,
03768             deviceExtension->Channel + c, c));
03769     } else {
03770         KdPrint2((PRINT_PREFIX "  cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension->DevIndex,
03771             deviceExtension->Channel + c, c));
03772         dma_status = GetDmaStatus(deviceExtension, lChannel);
03773         KdPrint2((PRINT_PREFIX "  DMA status %#x\n", dma_status));
03774     }
03775 
03776     // do controller-specific interrupt servicing staff
03777     if(deviceExtension->UnknownDev) {
03778         KdPrint2((PRINT_PREFIX "  UnknownDev\n"));
03779         goto check_unknown;
03780     }
03781 
03782     // Attention !
03783     // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
03784     // Such behavior was observed with Intel ICH-xxx chips
03785     // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
03786 
03787     switch(VendorID) {
03788 
03789     case ATA_PROMISE_ID: {
03790         switch(ChipType) {
03791         case PROLD:
03792         case PRNEW:
03793             status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1c);
03794             if (!DmaTransfer)
03795                 break;
03796             if (!(status & 
03797                   ((Channel) ? 0x00004000 : 0x00000400))) {
03798                 KdPrint2((PRINT_PREFIX "  Promise old/new unexpected\n"));
03799                 return INTERRUPT_REASON_IGNORE;
03800             }
03801             break;
03802         case PRTX:
03803             AtapiWritePort1(chan, IDX_BM_DeviceSpecific0, 0x0b);
03804             status = AtapiReadPort1(chan, IDX_BM_DeviceSpecific1);
03805             if (!DmaTransfer)
03806                 break;
03807             if(!(status & 0x20)) {
03808                 KdPrint2((PRINT_PREFIX "  Promise tx unexpected\n"));
03809                 return INTERRUPT_REASON_IGNORE;
03810             }
03811             break;
03812         case PRMIO:
03813             status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x0040);
03814             if(ChipFlags & PRSATA) {
03815                 pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c);
03816                 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c, pr_status & 0x000000ff);
03817             }
03818             if(pr_status & (0x11 << Channel)) {
03819                 // TODO: reset channel
03820                 KdPrint2((PRINT_PREFIX "  Promise mio unexpected + reset req\n"));
03821                 return INTERRUPT_REASON_IGNORE;
03822             }
03823             if(!(status & (0x01 << Channel))) {
03824                 KdPrint2((PRINT_PREFIX "  Promise mio unexpected\n"));
03825                 return INTERRUPT_REASON_IGNORE;
03826             }
03827             AtapiWritePort4(chan, IDX_BM_DeviceSpecific0, 0x00000001);
03828             break;
03829         }
03830         break; }
03831     case ATA_NVIDIA_ID: {
03832         if(!(ChipFlags & UNIATA_SATA))
03833             break;
03834 
03835         KdPrint2((PRINT_PREFIX "NVIDIA\n"));
03836 
03837         ULONG offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
03838         ULONG shift = Channel << ((ChipFlags & NVQ) ? 4 : 2);
03839 
03840         /* get and clear interrupt status */
03841         if(ChipFlags & NVQ) {
03842             pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
03843             AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0fUL << shift) | 0x00f000f0);
03844         } else {
03845             pr_status = AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
03846             AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0f << shift));
03847         }
03848         KdPrint2((PRINT_PREFIX "  pr_status %x\n", pr_status));
03849 
03850         /* check for and handle connect events */
03851         if(((pr_status & (0x0cUL << shift)) == (0x04UL << shift)) ) {
03852             UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0);
03853         }
03854         /* check for and handle disconnect events */
03855         if((pr_status & (0x08UL << shift)) &&
03856             !((pr_status & (0x04UL << shift) &&
03857             UniataSataReadPort4(chan, IDX_SATA_SStatus, 0))) ) {
03858             UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
03859         }
03860         /* do we have any device action ? */
03861         if(!(pr_status & (0x01UL << shift))) {
03862             KdPrint2((PRINT_PREFIX "  nVidia unexpected\n"));
03863             if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
03864                 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
03865             } else {
03866                 return INTERRUPT_REASON_IGNORE;
03867             }
03868         }
03869 
03870         break; }
03871     case ATA_ATI_ID:
03872         KdPrint2((PRINT_PREFIX "ATI\n"));
03873         if(ChipType == SIIMIO) {
03874             // fall to SiI
03875         } else {
03876             break;
03877         }
03878     case ATA_SILICON_IMAGE_ID:
03879 
03880         if(ChipType == SIIMIO) {
03881 
03882             reg32 = AtapiReadPort4(chan, IDX_BM_DeviceSpecific0);
03883             KdPrint2((PRINT_PREFIX "  Sii DS0 %x\n", reg32));
03884             if(reg32 == 0xffffffff) {
03885                 KdPrint2((PRINT_PREFIX "  Sii mio unexpected\n"));
03886                 return INTERRUPT_REASON_IGNORE;
03887             }
03888             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))) {
03889                 KdPrint2((PRINT_PREFIX "  Sii mio unexpected (2)\n"));
03890                 return INTERRUPT_REASON_IGNORE;
03891             }
03892 
03893             if(ChipFlags & UNIATA_SATA) {
03894                 if(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_IRQ)) {
03895 
03896                     /* SIEN doesn't mask SATA IRQs on some 3112s.  Those
03897                     * controllers continue to assert IRQ as long as
03898                     * SError bits are pending.  Clear SError immediately.
03899                     */
03900                     if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
03901                         OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
03902                     }
03903                 }
03904             }
03905 
03906             if (!DmaTransfer)
03907                 break;
03908             if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
03909                 KdPrint2((PRINT_PREFIX "  Sii mio unexpected (3)\n"));
03910                 return OurInterrupt;
03911             }
03912             AtapiWritePort1(chan, IDX_BM_Status, dma_status & ~BM_STATUS_ERR);
03913             goto skip_dma_stat_check;
03914 
03915         } else {
03916             if(!(deviceExtension->HwFlags & SIIINTR))
03917                 break;
03918             GetPciConfig1(0x71, reg8);
03919             KdPrint2((PRINT_PREFIX "  0x71 = %#x\n", reg8));
03920             if (!(reg8 &
03921                   (Channel ? 0x08 : 0x04))) {
03922                 return INTERRUPT_REASON_IGNORE;
03923             }
03924             if (!DmaTransfer) {
03925                 KdPrint2((PRINT_PREFIX "  cmd our\n"));
03926                 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
03927             }
03928             SetPciConfig1(0x71, (Channel ? 0x08 : 0x04));
03929         }
03930         break;
03931 
03932     case ATA_ACARD_ID:
03933         if (!DmaTransfer)
03934             break;
03935         //dma_status = GetDmaStatus(deviceExtension, lChannel);
03936         if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
03937             KdPrint2((PRINT_PREFIX "  Acard unexpected\n"));
03938             return INTERRUPT_REASON_IGNORE;
03939         }
03940         AtapiWritePort1(chan, IDX_BM_Status, dma_status | BM_STATUS_INTR);
03941         AtapiStallExecution(1);
03942         AtapiWritePort1(chan, IDX_BM_Command,
03943             AtapiReadPort1(chan, IDX_BM_Command) & ~BM_COMMAND_START_STOP);
03944         goto skip_dma_stat_check;
03945     case ATA_INTEL_ID:
03946         if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
03947             if(ChipFlags & UNIATA_AHCI) {
03948                 // Do nothing here
03949             } else
03950             if(ChipFlags & UNIATA_SATA) {
03951                 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
03952                     OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
03953                 }
03954                 if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
03955                     if(UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1)) {
03956                         OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
03957                     }
03958                 }
03959             }
03960         }
03961         break;
03962     default:
03963         if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
03964             if(ChipFlags & UNIATA_AHCI) {
03965                 // Do nothing here
03966             } else
03967             if(ChipFlags & UNIATA_SATA) {
03968                 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
03969                     OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
03970                 }
03971             }
03972         }
03973     }
03974 check_unknown:
03975     KdPrint2((PRINT_PREFIX "  perform generic check\n"));
03976     if (DmaTransfer) {
03977         if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
03978             KdPrint2((PRINT_PREFIX "  DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status));
03979             if(dma_status & BM_STATUS_ERR) {
03980                 KdPrint2((PRINT_PREFIX "  DmaTransfer + BM_STATUS_ERR -> our\n"));
03981                 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
03982             } else {
03983                 KdPrint2((PRINT_PREFIX "  getting status...\n"));
03984                 GetStatus(chan, statusByte);
03985                 KdPrint2((PRINT_PREFIX "  status %#x\n", statusByte));
03986                 if(statusByte & IDE_STATUS_ERROR) {
03987                     KdPrint2((PRINT_PREFIX "  IDE_STATUS_ERROR -> our\n", statusByte));
03988                     OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
03989                 } else {
03990                     return INTERRUPT_REASON_IGNORE;
03991                 }
03992             }
03993         }
03994     } else {
03995         if(dma_status & BM_STATUS_INTR) {
03996             // bullshit, we have DMA interrupt, but had never initiate DMA operation
03997             KdPrint2((PRINT_PREFIX "  clear unexpected DMA intr\n"));
03998             AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
03999             // catch it !
04000             OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
04001         }
04002     }
04003 skip_dma_stat_check:
04004     if(!(ChipFlags & UNIATA_SATA)) {
04005         AtapiStallExecution(1);
04006     }
04007 
04008     LunExt = chan->lun[chan->cur_cdev];
04009     /* if drive is busy it didn't interrupt */
04010     /* the exception is DCS + BSY state of ATAPI devices */
04011     KdPrint2((PRINT_PREFIX "  getting status...\n"));
04012     GetStatus(chan, statusByte);
04013     if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
04014         KdPrint3((PRINT_PREFIX "  ATAPI status %#x\n", statusByte));
04015     } else {
04016         KdPrint2((PRINT_PREFIX "  IDE status %#x\n", statusByte));
04017     }
04018     if (statusByte == 0xff) {
04019         // interrupt from empty controller ?
04020     } else 
04021     if (statusByte & IDE_STATUS_BUSY) {
04022         if(!chan->ExpectingInterrupt) {
04023             KdPrint3((PRINT_PREFIX "  unexpected intr + BUSY\n"));
04024             return OurInterrupt;
04025         }
04026 
04027         if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
04028             KdPrint2((PRINT_PREFIX "  ATAPI additional check\n"));
04029         } else {
04030             KdPrint2((PRINT_PREFIX "  expecting intr + BUSY (3), non ATAPI\n"));
04031             return INTERRUPT_REASON_IGNORE;
04032         }
04033         if((statusByte & ~IDE_STATUS_DRQ) != (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) {
04034             KdPrint3((PRINT_PREFIX "  unexpected status, seems it is not our\n"));
04035             return INTERRUPT_REASON_IGNORE;
04036         }
04037         if(!(LunExt->DeviceFlags & DFLAGS_INT_DRQ) && (statusByte & IDE_STATUS_DRQ)) {
04038             KdPrint3((PRINT_PREFIX "  unexpected DRQ, seems it is not our\n"));
04039             return INTERRUPT_REASON_IGNORE;
04040         }
04041 
04042         EarlyIntr = TRUE;
04043 
04044         if(dma_status & BM_STATUS_INTR) {
04045             KdPrint3((PRINT_PREFIX "  our interrupt with BSY set, try wait in ISR or post to DPC\n"));
04046             /* clear interrupt and get status */
04047             GetBaseStatus(chan, statusByte);
04048             KdPrint3((PRINT_PREFIX "  base status %#x (+BM_STATUS_INTR)\n", statusByte));
04049             return INTERRUPT_REASON_OUR;
04050         }
04051 
04052         if(g_WaitBusyInISR) {
04053             GetStatus(chan, statusByte);
04054             KdPrint2((PRINT_PREFIX "  status re-check %#x\n", statusByte));
04055             reg8 = AtapiReadPort1(chan, IDX_IO1_i_Error);
04056             KdPrint2((PRINT_PREFIX "  Error reg (%#x)\n", reg8));
04057             if (!(statusByte & IDE_STATUS_BUSY)) {
04058                 KdPrint2((PRINT_PREFIX "  expecting intr + cleared BUSY\n"));
04059             }
04060             if (statusByte & IDE_STATUS_BUSY) {
04061                 KdPrint2((PRINT_PREFIX "  still BUSY, seems it is not our\n"));
04062                 return INTERRUPT_REASON_IGNORE;
04063             }
04064         }
04065 
04066     }
04067 
04068     /* clear interrupt and get status */
04069     GetBaseStatus(chan, statusByte);
04070     KdPrint2((PRINT_PREFIX "  base status %#x\n", statusByte));
04071     if (statusByte == 0xff) {
04072         // interrupt from empty controller ?
04073     } else 
04074     if(!(statusByte & (IDE_STATUS_DRQ | IDE_STATUS_DRDY))) {
04075         KdPrint2((PRINT_PREFIX "  no DRQ/DRDY set\n"));
04076         return OurInterrupt;
04077     }
04078 
04079 #ifndef UNIATA_PIO_ONLY
04080     if(DmaTransfer) {
04081         if(!EarlyIntr || g_WaitBusyInISR) {
04082             dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
04083         } else {
04084             PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
04085             PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
04086 
04087             //ASSERT(AtaReq);
04088 
04089             KdPrint2((PRINT_PREFIX "  set REQ_STATE_EARLY_INTR.\n"));
04090             if(AtaReq) {
04091                 AtaReq->ReqState = REQ_STATE_EARLY_INTR;
04092             }
04093         }
04094     }
04095 #endif //
04096 
04097     if (!(chan->ExpectingInterrupt)) {
04098 
04099         KdPrint2((PRINT_PREFIX "  Unexpected interrupt.\n"));
04100 
04101         if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
04102             KdPrint2((PRINT_PREFIX "  ATAPI additional check\n"));
04103         } else {
04104             KdPrint2((PRINT_PREFIX "  OurInterrupt = %d\n", OurInterrupt));
04105             return OurInterrupt;
04106         }
04107         interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
04108         KdPrint3((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason));
04109         return OurInterrupt;
04110     }
04111     //ASSERT(!chan->queue_depth || chan->cur_req);
04112 
04113     KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__: exit with TRUE\n"));
04114     return INTERRUPT_REASON_OUR;
04115 
04116 } // end AtapiCheckInterrupt__()
04117 
04118 
04119 BOOLEAN
04120 NTAPI
04121 AtapiInterrupt__(
04122     IN PVOID HwDeviceExtension,
04123     IN UCHAR c
04124     )
04125 {
04126     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
04127     PHW_CHANNEL chan = &(deviceExtension->chan[c]);
04128     // Get current Srb
04129     PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
04130     PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
04131 
04132     ULONG wordCount = 0, wordsThisInterrupt = DEV_BSIZE/2;
04133     ULONG status = SRB_STATUS_SUCCESS;
04134     UCHAR dma_status = 0;
04135     ULONG i;
04136     ULONG k;
04137     UCHAR statusByte = 0,interruptReason;
04138 
04139     BOOLEAN atapiDev = FALSE;
04140 
04141     UCHAR Channel;
04142     UCHAR lChannel;
04143     UCHAR DeviceNumber;
04144     BOOLEAN DmaTransfer = FALSE;
04145     UCHAR error = 0;
04146     ULONG TimerValue = 1000;
04147 #ifdef UNIATA_USE_XXableInterrupts
04148     BOOLEAN InDpc = (KeGetCurrentIrql() == DISPATCH_LEVEL);
04149 #else
04150     BOOLEAN InDpc = (chan->DpcState != DPC_STATE_ISR);
04151 #endif // UNIATA_USE_XXableInterrupts
04152     BOOLEAN UseDpc = deviceExtension->UseDpc;
04153 //    BOOLEAN RestoreUseDpc = FALSE;
04154     BOOLEAN DataOverrun = FALSE;
04155     BOOLEAN NoStartIo = TRUE;
04156 
04157     KdPrint2((PRINT_PREFIX "AtapiInterrupt:\n"));
04158     if(InDpc) {
04159         KdPrint2((PRINT_PREFIX "  InDpc = TRUE\n"));
04160         //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
04161     }
04162 
04163     UCHAR PathId;
04164     UCHAR TargetId;
04165     UCHAR Lun;
04166     UCHAR OldReqState = REQ_STATE_NONE;
04167     //ULONG ldev;
04168     PHW_LU_EXTENSION LunExt;
04169 
04170     lChannel = c;
04171     Channel = (UCHAR)(deviceExtension->Channel + lChannel);
04172 
04173     KdPrint2((PRINT_PREFIX "  cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c));
04174 
04175     if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
04176        (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ) {
04177         DmaTransfer = TRUE;
04178         KdPrint2((PRINT_PREFIX "  DmaTransfer = TRUE\n"));
04179     }
04180 
04181     if (srb) {
04182         PathId   = srb->PathId;  
04183         TargetId = srb->TargetId;
04184         Lun      = srb->Lun;     
04185     } else {
04186         PathId = (UCHAR)c;
04187         TargetId =
04188         Lun      = 0;
04189         goto enqueue_next_req;
04190     }
04191 
04192     //ldev = GET_LDEV2(PathId, TargetId, Lun);
04193     DeviceNumber = (UCHAR)(TargetId);
04194     LunExt = chan->lun[DeviceNumber];
04195     atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
04196     KdPrint2((PRINT_PREFIX "  dev_type %s\n", atapiDev ? "ATAPI" : "IDE"));
04197 
04198     // check if we are in ISR DPC
04199     if(InDpc) {
04200         KdPrint2((PRINT_PREFIX "  InDpc -> CTRFLAGS_INTR_DISABLED\n"));
04201         goto ServiceInterrupt;
04202     }
04203 
04204     if (DmaTransfer) {
04205         dma_status = GetDmaStatus(deviceExtension, lChannel);
04206     }
04207 
04208     if (!(chan->ExpectingInterrupt)) {
04209 
04210         KdPrint2((PRINT_PREFIX "  Unexpected interrupt for this channel.\n"));
04211         return FALSE;
04212     }
04213 
04214     // change request state
04215     if(AtaReq) {
04216         OldReqState = AtaReq->ReqState;
04217         AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
04218         KdPrint2((PRINT_PREFIX "  OldReqState = %x\n", OldReqState));
04219     }
04220 
04221     // We don't want using DPC for fast operations, like
04222     // DMA completion, sending CDB, short ATAPI transfers, etc.
04223     // !!!! BUT !!!!
04224     // We MUST use DPC, because of interprocessor synchronization
04225     // on multiprocessor platforms
04226 
04227     if(DmaTransfer)
04228         goto ServiceInterrupt;
04229 
04230     switch(OldReqState) {
04231     case REQ_STATE_ATAPI_EXPECTING_CMD_INTR:
04232         KdPrint3((PRINT_PREFIX "  EXPECTING_CMD_INTR\n"));
04233     case REQ_STATE_ATAPI_EXPECTING_DATA_INTR:
04234     case REQ_STATE_DPC_WAIT_BUSY0:
04235     case REQ_STATE_DPC_WAIT_BUSY1:
04236         KdPrint2((PRINT_PREFIX "  continue service interrupt\n"));
04237         goto ServiceInterrupt;
04238     case REQ_STATE_ATAPI_DO_NOTHING_INTR:
04239         KdPrint2((PRINT_PREFIX "  do nothing on interrupt\n"));
04240         return TRUE;
04241     }
04242 
04243     if(!DmaTransfer && !atapiDev) {
04244         KdPrint2((PRINT_PREFIX "  service PIO HDD\n"));
04245         UseDpc = FALSE;
04246     }
04247 
04248 #ifndef UNIATA_CORE
04249 
04250     if(!UseDpc)
04251         goto ServiceInterrupt;
04252 
04253 #ifdef UNIATA_USE_XXableInterrupts
04254     if(InDpc) {
04255         KdPrint2((PRINT_PREFIX "  Unexpected InDpc\n"));
04256         ASSERT(FALSE);
04257         // shall never get here
04258         TimerValue = 1;
04259         goto CallTimerDpc;
04260     }
04261 
04262     KdPrint2((PRINT_PREFIX "  this is direct DPC call on DRQL\n"));
04263     if(AtaReq) {
04264         AtaReq->ReqState = REQ_STATE_DPC_INTR_REQ;
04265         KdPrint2((PRINT_PREFIX "  ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
04266     } else {
04267         KdPrint2((PRINT_PREFIX "  DPC without AtaReq!!!\n"));
04268     }
04269 #else
04270     KdPrint2((PRINT_PREFIX "call service interrupt\n"));
04271     goto ServiceInterrupt;
04272 #endif // UNIATA_USE_XXableInterrupts
04273 
04274 PostToDpc:
04275 
04276     // Attention !!!
04277     // AtapiInterruptDpc() is called on DISPATCH_LEVEL
04278     // We always get here when are called from timer callback, which is invoked on DRQL.
04279     // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
04280 
04281     KdPrint2((PRINT_PREFIX "AtapiInterrupt: start DPC init...\n"));
04282     // disable interrupts for this channel,
04283     // but avoid recursion and double-disable
04284     if(OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
04285         AtapiDisableInterrupts(deviceExtension, lChannel);
04286     }
04287     // go to ISR DPC
04288     chan->ChannelCtrlFlags |= CTRFLAGS_DPC_REQ;
04289 
04290 #ifdef UNIATA_USE_XXableInterrupts
04291     // Will lower IRQL to DISPATCH_LEVEL
04292     ScsiPortNotification(CallEnableInterrupts, HwDeviceExtension,
04293                          /*c ?*/ AtapiInterruptDpc/*_1 : AtapiInterruptDpc_0*/);
04294     KdPrint2((PRINT_PREFIX "AtapiInterrupt: DPC inited\n"));
04295 #else
04296     // Will raise IRQL to DIRQL
04297     AtapiQueueTimerDpc(HwDeviceExtension, c,
04298                          AtapiInterruptDpc,
04299                          TimerValue);
04300     KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
04301 #endif // UNIATA_USE_XXableInterrupts
04302     return TRUE;
04303 
04304 #ifndef UNIATA_CORE
04305 CallTimerDpc:
04306     AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
04307 CallTimerDpc2:
04308     // Will raise IRQL to DIRQL
04309     AtapiQueueTimerDpc(HwDeviceExtension, c,
04310                          AtapiCallBack_X,
04311                          TimerValue);
04312     return TRUE;
04313 #endif //UNIATA_CORE
04314 
04315 ServiceInterrupt:
04316 
04317     if(AtaReq && InDpc) {
04318         switch(AtaReq->ReqState) {
04319         case REQ_STATE_DPC_WAIT_DRQ0:
04320             goto PIO_wait_DRQ0;
04321         case REQ_STATE_DPC_WAIT_BUSY:
04322             goto PIO_wait_busy;
04323         case REQ_STATE_DPC_WAIT_DRQ:
04324             goto PIO_wait_DRQ;
04325         case REQ_STATE_DPC_WAIT_DRQ_ERR:
04326             goto continue_err;
04327         case REQ_STATE_DPC_WAIT_BUSY0:
04328         case REQ_STATE_DPC_WAIT_BUSY1:
04329             // continue normal execution
04330             break;
04331         }
04332     }
04333 #else
04334 ServiceInterrupt:
04335 #endif //UNIATA_CORE
04336 /*
04337     // make additional delay for old devices (if we are not in DPC)
04338     if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
04339              &&
04340        !InDpc &&
04341        !atapiDev &&
04342        !(deviceExtension->HwFlags & UNIATA_SATA)
04343        ) {
04344         KdPrint2((PRINT_PREFIX "  additional delay 10us for old devices\n"));
04345         AtapiStallExecution(10);
04346     }
04347 */
04348     /* clear interrupt and get status */
04349 
04350     if(deviceExtension->HwFlags & UNIATA_AHCI) {
04351         UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, srb);
04352         statusByte = (UCHAR)(AtaReq->ahci.in_status & 0xff);
04353     } else {
04354         GetBaseStatus(chan, statusByte);
04355     }
04356     if(atapiDev) {
04357         KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte));
04358     } else {
04359         KdPrint2((PRINT_PREFIX "AtapiInterrupt: Entered with status (%#x)\n", statusByte));
04360     }
04361 
04362     if(!UseDpc) {
04363         KdPrint2((PRINT_PREFIX "  operate like in DPC\n"));
04364         InDpc = TRUE;
04365     }
04366                                                                     
04367     if(deviceExtension->HwFlags & UNIATA_AHCI) {
04368         KdPrint3((PRINT_PREFIX "  AHCI branch\n"));
04369     } else
04370     if (!atapiDev) {
04371         // IDE
04372         if (statusByte & IDE_STATUS_BUSY) {
04373             if (deviceExtension->DriverMustPoll) {
04374                 // Crashdump is polling and we got caught with busy asserted.
04375                 // Just go away, and we will be polled again shortly.
04376                 KdPrint2((PRINT_PREFIX "  Hit BUSY while polling during crashdump.\n"));
04377                 goto ReturnEnableIntr;
04378             }
04379 try_dpc_wait:
04380             // Ensure BUSY is non-asserted.
04381             // make a very small idle before falling to DPC
04382             k = (InDpc && UseDpc) ? 1000 : 2;
04383 
04384             for (i = 0; i < k; i++) {
04385 
04386                 GetBaseStatus(chan, statusByte);
04387                 if (!(statusByte & IDE_STATUS_BUSY)) {
04388                     break;
04389                 }
04390                 AtapiStallExecution(10);
04391             }
04392 
04393             if (!InDpc && UseDpc && i == 2) {
04394 
04395                 KdPrint2((PRINT_PREFIX "  BUSY on entry. Status %#x, Base IO %#x\n", statusByte));
04396 
04397                 TimerValue = 50;
04398                 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
04399 
04400 #ifndef UNIATA_CORE
04401                 goto PostToDpc;
04402 #else //UNIATA_CORE
04403                 AtapiStallExecution(TimerValue);
04404                 goto ServiceInterrupt;
04405 #endif //UNIATA_CORE
04406             } else 
04407             if (InDpc && i == k) {
04408                 // reset the controller.
04409                 KdPrint2((PRINT_PREFIX 
04410                             "  Resetting due to BUSY on entry - %#x.\n",
04411                             statusByte));
04412                 goto IntrPrepareResetController;
04413             }
04414         }
04415     } else {
04416         // ATAPI
04417         if(!LunExt->IdentifyData.MajorRevision &&
04418             InDpc &&
04419             !atapiDev &&
04420             !(deviceExtension->HwFlags & UNIATA_SATA)
04421             ) {
04422             KdPrint2((PRINT_PREFIX "  additional delay 10us for old devices (2)\n"));
04423             AtapiStallExecution(10);
04424         }
04425         if (statusByte & IDE_STATUS_BUSY) {
04426         //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
04427             KdPrint3((PRINT_PREFIX "  BUSY on ATAPI device, waiting\n"));
04428             for(k=20; k; k--) {
04429                 GetStatus(chan, statusByte);
04430                 KdPrint3((PRINT_PREFIX "  status re-check %#x\n", statusByte));
04431                 KdPrint3((PRINT_PREFIX "  Error reg (%#x)\n",
04432                             AtapiReadPort1(chan, IDX_IO1_i_Error)));
04433                 if (!(statusByte & IDE_STATUS_BUSY)) {
04434                     KdPrint2((PRINT_PREFIX "  expecting intr + cleared BUSY\n"));
04435                     break;
04436                 }
04437                 if(k <= 18) {
04438                     KdPrint3((PRINT_PREFIX "  too long wait -> DPC\n"));
04439                     if(!InDpc) {
04440                         KdPrint2((PRINT_PREFIX "  too long wait: ISR -> DPC\n"));
04441                         TimerValue = 100;
04442                         AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
04443                     } else {
04444                         KdPrint2((PRINT_PREFIX "  too long wait: DPC -> DPC\n"));
04445                         TimerValue = 1000;
04446                         AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY1;
04447                     }
04448 #ifndef UNIATA_CORE
04449                     goto CallTimerDpc2;
04450 #else //UNIATA_CORE
04451                     AtapiStallExecution(TimerValue);
04452 #endif //UNIATA_CORE
04453                 }
04454 
04455                 AtapiStallExecution(10);
04456             }
04457             if (statusByte & IDE_STATUS_BUSY) {
04458                 KdPrint3((PRINT_PREFIX "  expecting intr + BUSY (2), try DPC wait\n"));
04459                 goto try_dpc_wait;
04460             }
04461         }
04462     }
04463 
04464     if(AtaReq && DmaTransfer && !(deviceExtension->HwFlags & UNIATA_AHCI)) {
04465         switch(OldReqState) {
04466         case REQ_STATE_EARLY_INTR:
04467         case REQ_STATE_DPC_WAIT_BUSY0:
04468 
04469             if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
04470                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DMA still active\n"));
04471                 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
04472             }
04473             break;
04474         }
04475     }
04476 
04477 //retry_check:
04478     // Check for error conditions.
04479     if ((statusByte & IDE_STATUS_ERROR) ||
04480         (dma_status & BM_STATUS_ERR)) {
04481 
04482         if(deviceExtension->HwFlags & UNIATA_AHCI) {
04483             error = (UCHAR)((AtaReq->ahci.in_status >> 8) && 0xff);
04484         } else {
04485             error = AtapiReadPort1(chan, IDX_IO1_i_Error);
04486         }
04487         KdPrint2((PRINT_PREFIX "AtapiInterrupt: Error %#x\n", error));
04488 /*
04489         if(error & IDE_STATUS_CORRECTED_ERROR) {
04490             KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
04491             statusByte &= ~IDE_STATUS_ERROR;
04492             goto retry_check;
04493         }
04494 */
04495         if(AtaReq) {
04496             KdPrint2((PRINT_PREFIX "  Bad Lba %#I64x\n", AtaReq->lba));
04497         } else {
04498             KdPrint2((PRINT_PREFIX "  Bad Lba unknown\n"));
04499         }
04500 
04501 
04502         if(!atapiDev) {
04503             KdPrint2((PRINT_PREFIX "  wait 100 ready after IDE error\n"));
04504             AtapiStallExecution(100);
04505         } else {
04506             KdPrint2((PRINT_PREFIX "  wait 10 ready after ATAPI error\n"));
04507             AtapiStallExecution(10);
04508         }
04509 continue_err:
04510 
04511         KdPrint3((PRINT_PREFIX "  Intr on DRQ %x\n",
04512             LunExt->DeviceFlags & DFLAGS_INT_DRQ));
04513 
04514         for (k = atapiDev ? 0 : 200; k; k--) {
04515             GetStatus(chan, statusByte);
04516             if (!(statusByte & IDE_STATUS_DRQ)) {
04517                 AtapiStallExecution(50);
04518             } else {
04519                 break;
04520             }
04521         }
04522 
04523         if (!atapiDev) {
04524             /* if this is a UDMA CRC error, reinject request */
04525 
04526             AtaReq->retry++;
04527             if(AtaReq->retry < MAX_RETRIES) {
04528 #ifdef IO_STATISTICS
04529                 chan->lun[DeviceNumber]->ModeErrorCount[AtaReq->retry]++;
04530 #endif //IO_STATISTICS
04531                 if(DmaTransfer /*&&
04532                    (error & IDE_ERROR_ICRC)*/) {
04533                     if(AtaReq->retry < MAX_RETRIES) {
04534 //fallback_pio:
04535                         AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
04536                         AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
04537 //                        LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
04538                         AtaReq->ReqState = REQ_STATE_QUEUED;
04539                         goto reenqueue_req;
04540                     }
04541                 } else {
04542                     if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
04543                         AtaReq->retry++;
04544                     }
04545                     KdPrint2((PRINT_PREFIX "Errors in PIO mode\n"));
04546                 }
04547             }
04548         } else {
04549             interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
04550             KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason));
04551 
04552             if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) &&
04553                ((error >> 4) == SCSI_SENSE_HARDWARE_ERROR)) {
04554                 if(AtaReq->retry < MAX_RETRIES) {
04555 //fallback_pio:
04556                     AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
04557                     AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
04558 //                        LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
04559                     AtaReq->ReqState = REQ_STATE_QUEUED;
04560                     goto reenqueue_req;
04561                 }
04562             } else {
04563                 if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
04564                     AtaReq->retry++;
04565                 }
04566                 KdPrint3((PRINT_PREFIX "Errors in PIO mode\n"));
04567             }
04568         }
04569 
04570         KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error\n"));
04571         if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
04572             // Fail this request.
04573             status = SRB_STATUS_ERROR;
04574             goto CompleteRequest;
04575         } else {
04576             KdPrint2((PRINT_PREFIX "  continue with SCSIOP_REQUEST_SENSE\n"));
04577         }
04578     } else
04579     if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE_LBA48) {
04580         KdPrint2((PRINT_PREFIX "DMA doesn't work right with LBA48\n"));
04581         deviceExtension->HbaCtrlFlags |= HBAFLAGS_DMA_DISABLED_LBA48;
04582     } else
04583     if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE) {
04584 #ifdef IO_STATISTICS
04585         KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n"));
04586         KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n",
04587               AtaReq->retry,
04588               chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry],
04589               chan->lun[DeviceNumber]->BlockIoCount
04590               ));
04591         chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry]++;
04592         if(chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
04593            (deviceExtension->HwFlags & UNIATA_NO80CHK)
04594            ) {
04595 #else
04596         if(deviceExtension->HwFlags & UNIATA_NO80CHK) {
04597 #endif //IO_STATISTICS
04598             KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", deviceExtension->lun[DeviceNumber].TransferMode));
04599             deviceExtension->lun[DeviceNumber].LimitedTransferMode =
04600                 deviceExtension->lun[DeviceNumber].TransferMode;
04601         }
04602     }
04603 #ifdef IO_STATISTICS
04604     if(AtaReq->bcount) {
04605         // we need stats for Read/Write operations
04606         chan->lun[DeviceNumber]->BlockIoCount++;
04607     }
04608     chan->lun[DeviceNumber]->IoCount++;
04609 #endif //IO_STATISTICS
04610 
04611 continue_PIO:
04612 
04613     // check reason for this interrupt.
04614     if (atapiDev) {
04615 
04616         KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI branch\n"));
04617         // ATAPI branch
04618 
04619         interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
04620         KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
04621         if(DmaTransfer) {
04622             wordsThisInterrupt = DEV_BSIZE/2*512;
04623         } else {
04624             wordsThisInterrupt = DEV_BSIZE/2;
04625         }
04626 
04627     } else {
04628 
04629         // ATA branch
04630 
04631         if(DmaTransfer) {
04632             // simulate DRQ for DMA transfers
04633             statusByte |= IDE_STATUS_DRQ;
04634         }
04635         if (statusByte & IDE_STATUS_DRQ) {
04636 
04637             if(DmaTransfer) {
04638                 wordsThisInterrupt = DEV_BSIZE/2*512;
04639             } else
04640             if (LunExt->MaximumBlockXfer) {
04641                 wordsThisInterrupt = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
04642             }
04643 
04644             if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
04645 
04646                 interruptReason =  0x2;
04647 
04648             } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
04649                 interruptReason = 0x0;
04650 
04651             } else {
04652                 status = SRB_STATUS_ERROR;
04653                 goto CompleteRequest;
04654             }
04655 
04656         } else if (statusByte & IDE_STATUS_BUSY) {
04657 
04658             //AtapiEnableInterrupts(deviceExtension, lChannel);
04659             KdPrint2((PRINT_PREFIX "AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
04660             return FALSE;
04661 
04662         } else {
04663 
04664             if (AtaReq->WordsLeft) {
04665 
04666                 // Funky behaviour seen with PCI IDE (not all, just one).
04667 PIO_wait_DRQ0:
04668                 // The ISR hits with DRQ low, but comes up later.
04669                 for (k = 0; k < 5000; k++) {
04670                     GetStatus(chan, statusByte);
04671                     if (statusByte & IDE_STATUS_DRQ) {
04672                         break;
04673                     }
04674                     if(!InDpc) {
04675                         // goto DPC
04676                         AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ0;
04677                         TimerValue = 100;
04678                         KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq0)\n"));
04679 #ifndef UNIATA_CORE
04680                         goto PostToDpc;
04681 #else //UNIATA_CORE
04682                         AtapiStallExecution(TimerValue);
04683                         goto ServiceInterrupt;
04684 #endif //UNIATA_CORE
04685                     }
04686                     AtapiStallExecution(100);
04687                 }
04688                 if (k == 5000) {
04689                     // reset the controller.
04690                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
04691                                 statusByte));
04692 IntrPrepareResetController:
04693                     AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_CURRENT);
04694                     goto ReturnEnableIntr;
04695 
04696                 } else {
04697                     interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? 0x2 : 0x0;
04698                 }
04699 
04700             } else {
04701                 // Command complete - verify, write, or the SMART enable/disable.
04702                 // Also get_media_status
04703                 interruptReason = 0x3;
04704             }
04705         }
04706     }
04707 
04708     KdPrint2((PRINT_PREFIX "AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason, statusByte));
04709     if(deviceExtension->HwFlags & UNIATA_AHCI) {
04710         KdPrint2((PRINT_PREFIX "  AHCI path\n"));
04711         goto ReturnEnableIntr;
04712     } else
04713     if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) {
04714         // Write the packet.
04715         KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
04716         // Send CDB to device.
04717         WriteBuffer(chan, (PUSHORT)srb->Cdb, 6, 0);
04718         AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
04719 
04720         if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
04721             KdPrint2((PRINT_PREFIX "AtapiInterrupt: AtapiDmaStart().\n"));
04722             AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, srb);
04723         }
04724 
04725         goto ReturnEnableIntr;
04726 
04727     } else if (interruptReason == 0x0 && (statusByte & IDE_STATUS_DRQ)) {
04728 
04729         // Write the data.
04730         if (atapiDev) {
04731 
04732             // Pick up bytes to transfer and convert to words.
04733             wordCount =
04734                 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
04735 
04736             wordCount |=
04737                 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
04738 
04739             // Covert bytes to words.
04740             wordCount >>= 1;
04741             KdPrint2((PRINT_PREFIX "AtapiInterrupt: get W wordCount %#x\n", wordCount));
04742 
04743             if (wordCount != AtaReq->WordsLeft) {
04744                 KdPrint2((PRINT_PREFIX 
04745                            "AtapiInterrupt: %d words requested; %d words xferred\n",
04746                            AtaReq->WordsLeft,
04747                            wordCount));
04748             }
04749 
04750             // Verify this makes sense.
04751             if (wordCount > AtaReq->WordsLeft) {
04752                 wordCount = AtaReq->WordsLeft;
04753                 KdPrint2((PRINT_PREFIX 
04754                            "AtapiInterrupt: Write underrun\n"));
04755                 DataOverrun = TRUE;
04756             }
04757 
04758         } else {
04759 
04760             // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
04761             if (AtaReq->WordsLeft < wordsThisInterrupt) {
04762                // Transfer only words requested.
04763                wordCount = AtaReq->WordsLeft;
04764             } else {
04765                // Transfer next block.
04766                wordCount = wordsThisInterrupt;
04767             }
04768         }
04769 
04770         if (DmaTransfer && (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
04771             //ASSERT(AtaReq->WordsLeft == wordCount);
04772             AtaReq->WordsLeft = 0;
04773             status = SRB_STATUS_SUCCESS;
04774             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
04775             goto CompleteRequest;
04776         }
04777         // Ensure that this is a write command.
04778         if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
04779 
04780            KdPrint2((PRINT_PREFIX 
04781                       "AtapiInterrupt: Write interrupt\n"));
04782 
04783            statusByte = WaitOnBusy(chan);
04784 
04785            if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) ) {
04786 
04787                WriteBuffer(chan,
04788                            AtaReq->DataBuffer,
04789                            wordCount,
04790                            UniataGetPioTiming(LunExt));
04791            } else {
04792 
04793                WriteBuffer2(chan,
04794                            (PULONG)(AtaReq->DataBuffer),
04795                            wordCount / 2,
04796                            UniataGetPioTiming(LunExt));
04797            }
04798         } else {
04799 
04800             KdPrint3((PRINT_PREFIX 
04801                         "AtapiInterrupt: Int reason %#x, but srb is for a write %#x.\n",
04802                         interruptReason,
04803                         srb));
04804 
04805             // Fail this request.
04806             status = SRB_STATUS_ERROR;
04807             goto CompleteRequest;
04808         }
04809 
04810         // Advance data buffer pointer and bytes left.
04811         AtaReq->DataBuffer += wordCount;
04812         AtaReq->WordsLeft -= wordCount;
04813 
04814         if (atapiDev) {
04815             AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
04816         }
04817 
04818         goto ReturnEnableIntr;
04819 
04820     } else if (interruptReason == 0x2 && (statusByte & IDE_STATUS_DRQ)) {
04821 
04822 
04823         if (atapiDev) {
04824 
04825             // Pick up bytes to transfer and convert to words.
04826             wordCount =
04827                 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow) |
04828                 (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8);
04829 
04830             // Covert bytes to words.
04831             wordCount /= 2;
04832             KdPrint2((PRINT_PREFIX "AtapiInterrupt: get R wordCount %#x\n", wordCount));
04833 
04834             if (wordCount != AtaReq->WordsLeft) {
04835                 KdPrint2((PRINT_PREFIX 
04836                            "AtapiInterrupt: %d words requested; %d words xferred\n",
04837                            AtaReq->WordsLeft,
04838                            wordCount));
04839             }
04840 
04841             // Verify this makes sense.
04842             if (wordCount > AtaReq->WordsLeft) {
04843                 wordCount = AtaReq->WordsLeft;
04844                 DataOverrun = TRUE;
04845             }
04846 
04847         } else {
04848 
04849             // Check if words left is at least 256.
04850             if (AtaReq->WordsLeft < wordsThisInterrupt) {
04851                // Transfer only words requested.
04852                wordCount = AtaReq->WordsLeft;
04853             } else {
04854                // Transfer next block.
04855                wordCount = wordsThisInterrupt;
04856             }
04857         }
04858 
04859         if (DmaTransfer && (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
04860             //ASSERT(AtaReq->WordsLeft == wordCount);
04861             AtaReq->WordsLeft = 0;
04862             status = SRB_STATUS_SUCCESS;
04863             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
04864             goto CompleteRequest;
04865         }
04866         // Ensure that this is a read command.
04867         if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
04868 
04869 /*           KdPrint2((
04870                       "AtapiInterrupt: Read interrupt\n"));*/
04871 
04872             statusByte = WaitOnBusy(chan);
04873 
04874             if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) ) {
04875                 KdPrint2((PRINT_PREFIX 
04876                            "IdeIntr: Read %#x words\n", wordCount));
04877 
04878                 ReadBuffer(chan,
04879                           AtaReq->DataBuffer,
04880                           wordCount,
04881                           UniataGetPioTiming(LunExt));
04882                 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)-1) ));
04883                 //KdDump(AtaReq->DataBuffer, wordCount*2);
04884                 if(srb && atapiDev && srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
04885                     KdDump(AtaReq->DataBuffer, wordCount*2);
04886                 }
04887 
04888                 GetStatus(chan, statusByte);
04889                 KdPrint2((PRINT_PREFIX "  status re-check %#x\n", statusByte));
04890 
04891                 if(DataOverrun) {
04892                     KdPrint2((PRINT_PREFIX "  DataOverrun\n"));
04893                     AtapiSuckPort2(chan);
04894                 }
04895 
04896             } else {
04897                 KdPrint2((PRINT_PREFIX 
04898                           "IdeIntr: Read %#x Dwords\n", wordCount/2));
04899 
04900                 ReadBuffer2(chan,
04901                            (PULONG)(AtaReq->DataBuffer),
04902                            wordCount / 2,
04903                            UniataGetPioTiming(LunExt));
04904             }
04905         } else {
04906 
04907             KdPrint3((PRINT_PREFIX 
04908                         "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
04909                         interruptReason,
04910                         srb));
04911 
04912             // Fail this request.
04913             status = SRB_STATUS_ERROR;
04914             goto CompleteRequest;
04915         }
04916 
04917         // Advance data buffer pointer and bytes left.
04918         AtaReq->DataBuffer += wordCount;
04919         AtaReq->WordsLeft -= wordCount;
04920 
04921         // Check for read command complete.
04922         if (AtaReq->WordsLeft == 0) {
04923 
04924             KdPrint2((PRINT_PREFIX "AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
04925             if (atapiDev) {
04926 
04927                 // Work around to make many atapi devices return correct sector size
04928                 // of 2048. Also certain devices will have sector count == 0x00, check
04929                 // for that also.
04930                 if ((srb->Cdb[0] == SCSIOP_READ_CAPACITY) &&
04931                     (LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM)) {
04932 
04933                     AtaReq->DataBuffer -= wordCount;
04934                     if (AtaReq->DataBuffer[0] == 0x00) {
04935 
04936                         *((ULONG *) &(AtaReq->DataBuffer[0])) = 0xFFFFFF7F;
04937 
04938                     }
04939 
04940                     *((ULONG *) &(AtaReq->DataBuffer[2])) = 0x00080000;
04941                     AtaReq->DataBuffer += wordCount;
04942                 }
04943             } else {
04944 
04945             /*
04946                 // Completion for IDE drives.
04947                 if (AtaReq->WordsLeft) {
04948                     status = SRB_STATUS_DATA_OVERRUN;
04949                 } else {
04950                     status = SRB_STATUS_SUCCESS;
04951                 }
04952 
04953                 goto CompleteRequest;
04954             */
04955                 status = SRB_STATUS_SUCCESS;
04956                 goto CompleteRequest;
04957 
04958             }
04959         } else {
04960             if (atapiDev) {
04961                 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
04962             }
04963         }
04964 
04965         goto ReturnEnableIntr;
04966 
04967     } else if (interruptReason == 0x3  && !(statusByte & IDE_STATUS_DRQ)) {
04968 
04969         KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n"));
04970         // Command complete.
04971         if(DmaTransfer) {
04972             KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
04973             AtaReq->WordsLeft = 0;
04974         }
04975         if (AtaReq->WordsLeft) {
04976             status = SRB_STATUS_DATA_OVERRUN;
04977         } else {
04978             status = SRB_STATUS_SUCCESS;
04979         }
04980 
04981 #ifdef UNIATA_DUMP_ATAPI
04982         if(srb &&
04983            srb->SrbFlags & SRB_FLAGS_DATA_IN) {
04984             UCHAR                   ScsiCommand;
04985             PCDB                    Cdb;
04986             PCHAR                   CdbData;
04987             PCHAR                   ModeSelectData;
04988             ULONG                   CdbDataLen;
04989             PSCSI_REQUEST_BLOCK     Srb = srb;
04990 
04991             Cdb = (PCDB)(Srb->Cdb);
04992             ScsiCommand = Cdb->CDB6.OperationCode;
04993             CdbData = (PCHAR)(Srb->DataBuffer);
04994             CdbDataLen = Srb->DataTransferLength;
04995 
04996             if(CdbDataLen > 0x1000) {
04997                 CdbDataLen = 0x1000;
04998             }
04999 
05000             KdPrint(("--\n"));
05001             KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
05002             KdPrint2(("P:T:D=%d:%d:%d\n",
05003                                       Srb->PathId,
05004                                       Srb->TargetId,
05005                                       Srb->Lun));
05006             KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand));
05007             KdDump(Cdb, 16);
05008 
05009             if(ScsiCommand == SCSIOP_MODE_SENSE) {
05010                 KdPrint(("ModeSense 6\n"));
05011                 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
05012                 ModeSelectData = CdbData+4;
05013                 KdDump(CdbData, CdbDataLen);
05014             } else
05015             if(ScsiCommand == SCSIOP_MODE_SENSE10) {
05016                 KdPrint(("ModeSense 10\n"));
05017                 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
05018                 ModeSelectData = CdbData+8;
05019                 KdDump(CdbData, CdbDataLen);
05020             } else {
05021                 if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
05022                     KdPrint(("Read buffer from device:\n"));
05023                     KdDump(CdbData, CdbDataLen);
05024                 }
05025             }
05026             KdPrint(("--\n"));
05027         }
05028 #endif //UNIATA_DUMP_ATAPI
05029 
05030 CompleteRequest:
05031 
05032         KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest\n"));
05033         // Check and see if we are processing our secret (mechanism status/request sense) srb
05034         if (AtaReq->OriginalSrb) {
05035 
05036             ULONG srbStatus;
05037 
05038             KdPrint2((PRINT_PREFIX "AtapiInterrupt: OriginalSrb != NULL\n"));
05039             if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
05040 
05041                 KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
05042                 if (status == SRB_STATUS_SUCCESS) {
05043                     // Bingo!!
05044                     AtapiHwInitializeChanger (HwDeviceExtension,
05045                                               srb,
05046                                               (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer);
05047 
05048                     // Get ready to issue the original srb
05049                     srb = AtaReq->Srb = AtaReq->OriginalSrb;
05050                     AtaReq->OriginalSrb = NULL;
05051 
05052                 } else {
05053                     // failed!  Get the sense key and maybe try again
05054                     srb = AtaReq->Srb = BuildRequestSenseSrb (
05055                                                           HwDeviceExtension,
05056                                                           AtaReq->OriginalSrb);
05057                 }
05058 /*
05059                 // do not enable interrupts in DPC, do not waste time, do it now!
05060                 if(UseDpc && chan->DisableIntr) {
05061                     AtapiEnableInterrupts(HwDeviceExtension, c);
05062                     UseDpc = FALSE;
05063                     RestoreUseDpc = TRUE;
05064                 }
05065 */
05066                 srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
05067 
05068                 KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
05069 
05070                 if (srbStatus == SRB_STATUS_PENDING) {
05071                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
05072                     goto ReturnEnableIntr;
05073                 }
05074 /*
05075                 if(RestoreUseDpc) {
05076                     // restore state on error
05077                     UseDpc = TRUE;
05078                     AtapiDisableInterrupts(HwDeviceExtension, c);
05079                 }
05080 */
05081 
05082             } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
05083 
05084                 PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer;
05085 
05086                 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI command status %#x\n", status));
05087                 if (status == SRB_STATUS_DATA_OVERRUN) {
05088                     // Check to see if we at least get mininum number of bytes
05089                     if ((srb->DataTransferLength - AtaReq->WordsLeft) >
05090                         (FIELD_OFFSET (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) {
05091                         status = SRB_STATUS_SUCCESS;
05092                     }
05093                 }
05094 
05095                 if (status == SRB_STATUS_SUCCESS) {
05096 #ifndef UNIATA_CORE
05097                     if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) &&
05098                         chan->MechStatusRetryCount) {
05099 
05100                         // The sense key doesn't say the last request is illegal, so try again
05101                         chan->MechStatusRetryCount--;
05102                         srb = AtaReq->Srb = BuildMechanismStatusSrb (
05103                                                               HwDeviceExtension,
05104                                                               AtaReq->OriginalSrb);
05105                     } else {
05106 
05107                         // last request was illegal.  No point trying again
05108                         AtapiHwInitializeChanger (HwDeviceExtension,
05109                                                   srb,
05110                                                   (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
05111 
05112                         // Get ready to issue the original srb
05113                         srb = AtaReq->Srb = AtaReq->OriginalSrb;
05114                         AtaReq->OriginalSrb = NULL;
05115                     }
05116 #endif //UNIATA_CORE
05117 /*
05118                     // do not enable interrupts in DPC, do not waste time, do it now!
05119                     if(UseDpc && chan->DisableIntr) {
05120                         AtapiEnableInterrupts(HwDeviceExtension, c);
05121                         UseDpc = FALSE;
05122                         RestoreUseDpc = TRUE;
05123                     }
05124 */
05125                     srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
05126 
05127                     KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan->ExpectingInterrupt));
05128 
05129                     if (srbStatus == SRB_STATUS_PENDING) {
05130                         KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
05131                         goto ReturnEnableIntr;
05132                     }
05133 /*
05134                     if(RestoreUseDpc) {
05135                         // restore state on error
05136                         UseDpc = TRUE;
05137                         AtapiDisableInterrupts(HwDeviceExtension, c);
05138                     }
05139 */
05140                 }
05141             }
05142 
05143             // If we get here, it means AtapiSendCommand() has failed
05144             // Can't recover.  Pretend the original srb has failed and complete it.
05145 
05146             KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. complete OriginalSrb\n"));
05147 
05148             if (AtaReq->OriginalSrb) {
05149                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
05150                 AtapiHwInitializeChanger (HwDeviceExtension,
05151                                           srb,
05152                                           (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
05153                 srb = AtaReq->Srb = AtaReq->OriginalSrb;
05154                 AtaReq->OriginalSrb = NULL;
05155             }
05156 
05157             KdPrint2((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan->ExpectingInterrupt));
05158 
05159             // fake an error and read no data
05160             status = SRB_STATUS_ERROR;
05161             srb->ScsiStatus = 0;
05162             AtaReq->DataBuffer = (PUSHORT)(srb->DataBuffer);
05163             AtaReq->WordsLeft = srb->DataTransferLength;
05164             chan->RDP = FALSE;
05165 
05166         } else if (status == SRB_STATUS_ERROR) {
05167 
05168             // Map error to specific SRB status and handle request sense.
05169             KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. Begin mapping...\n"));
05170             status = MapError(deviceExtension,
05171                               srb);
05172 
05173             chan->RDP = FALSE;
05174 
05175         } else if(!DmaTransfer) {
05176 
05177             KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion\n"));
05178             // Command complete.
05179 PIO_wait_busy:
05180             KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion, wait BUSY\n"));
05181             // Wait for busy to drop.
05182             for (i = 0; i < 5*30; i++) {
05183                 GetStatus(chan, statusByte);
05184                 if (!(statusByte & IDE_STATUS_BUSY)) {
05185                     break;
05186                 }
05187                 if(!InDpc) {
05188                     // goto DPC
05189                     AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY;
05190                     TimerValue = 200;
05191                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (busy)\n"));
05192 #ifndef UNIATA_CORE
05193                     goto PostToDpc;
05194 #else //UNIATA_CORE
05195                     AtapiStallExecution(TimerValue);
05196                     goto ServiceInterrupt;
05197 #endif //UNIATA_CORE
05198                 }
05199                 AtapiStallExecution(100);
05200             }
05201 
05202             if (i == 5*30) {
05203 
05204                 // reset the controller.
05205                 KdPrint2((PRINT_PREFIX 
05206                             "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
05207                             statusByte));
05208                 goto IntrPrepareResetController;
05209             }
05210             // Check to see if DRQ is still up.
05211             if(statusByte & IDE_STATUS_DRQ) {
05212                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DRQ...\n"));
05213                 if(srb) {
05214                     if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
05215                         KdPrint2((PRINT_PREFIX "srb %x data in\n", srb));
05216                     } else {
05217                         KdPrint2((PRINT_PREFIX "srb %x data out\n", srb));
05218                     }
05219                 } else {
05220                     KdPrint2((PRINT_PREFIX "srb NULL\n"));
05221                 }
05222                 if(AtaReq) {
05223                     KdPrint2((PRINT_PREFIX "AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq, AtaReq->WordsLeft));
05224                 } else {
05225                     KdPrint2((PRINT_PREFIX "AtaReq NULL\n"));
05226                 }
05227                 if(AtaReq && AtaReq->WordsLeft /*&&
05228                    !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
05229                     KdPrint2((PRINT_PREFIX "DRQ+AtaReq->WordsLeft -> next portion\n"));
05230                     goto continue_PIO;
05231                 }
05232             }
05233             //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
05234             //if ((statusByte & IDE_STATUS_DRQ)) {}
05235             if((statusByte & IDE_STATUS_DRQ) &&
05236                (LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED)) ) {
05237 
05238 PIO_wait_DRQ:
05239                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO_wait_DRQ\n"));
05240                 for (i = 0; i < 200; i++) {
05241                     GetStatus(chan, statusByte);
05242                     if (!(statusByte & IDE_STATUS_DRQ)) {
05243                         break;
05244                     }
05245                     if(!InDpc) {
05246                         // goto DPC
05247                         KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq)\n"));
05248                         AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ;
05249                         TimerValue = 100;
05250 #ifndef UNIATA_CORE
05251                         goto PostToDpc;
05252 #else //UNIATA_CORE
05253                         AtapiStallExecution(TimerValue);
05254                         goto ServiceInterrupt;
05255 #endif //UNIATA_CORE
05256                     }
05257                     AtapiStallExecution(100);
05258                 }
05259 
05260                 if (i == 200) {
05261                     // reset the controller.
05262                     KdPrint2((PRINT_PREFIX   "AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
05263                                 statusByte));
05264                     goto IntrPrepareResetController;
05265                 }
05266             }
05267             if(atapiDev) {
05268                 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
05269                      AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)(-1)), srb->DataTransferLength ));
05270                 //KdDump(srb->DataBuffer, srb->DataTransferLength);
05271             }
05272             if(!AtapiDmaPioSync(HwDeviceExtension, srb, (PUCHAR)(srb->DataBuffer), srb->DataTransferLength)) {
05273                 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
05274             }
05275         }
05276 
05277         // Clear interrupt expecting flag.
05278         chan->ExpectingInterrupt = FALSE;
05279         InterlockedExchange(&(chan->CheckIntr),
05280                                       CHECK_INTR_IDLE);
05281 
05282         // Sanity check that there is a current request.
05283         if(srb != NULL) {
05284             // Set status in SRB.
05285             srb->SrbStatus = (UCHAR)status;
05286 
05287             // Check for underflow.
05288             if(AtaReq->WordsLeft) {
05289 
05290                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq->WordsLeft));
05291                 // Subtract out residual words and update if filemark hit,
05292                 // setmark hit , end of data, end of media...
05293                 if (!(LunExt->DeviceFlags & DFLAGS_TAPE_DEVICE)) {
05294                     if (status == SRB_STATUS_DATA_OVERRUN) {
05295                         srb->DataTransferLength -= AtaReq->WordsLeft*2;
05296                     } else {
05297                         srb->DataTransferLength = 0;
05298                     }
05299                 } else {
05300                     srb->DataTransferLength -= AtaReq->WordsLeft*2;
05301                 }
05302             }
05303             if(status == SRB_STATUS_SUCCESS) {
05304                 AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
05305                 if(!atapiDev &&
05306                    AtaReq->WordsTransfered*2 < AtaReq->TransferLength) {
05307                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
05308                          AtaReq->WordsTransfered*2, AtaReq->TransferLength));
05309                     AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
05310                     AtaReq->ReqState = REQ_STATE_PREPARE_TO_NEXT;
05311                     goto reenqueue_req;
05312                 } else {
05313                     KdPrint2((PRINT_PREFIX "   Transfered %x, full size %x\n",
05314                         AtaReq->WordsTransfered*2, AtaReq->TransferLength));
05315                 }
05316             }
05317 
05318             if (srb->Function != SRB_FUNCTION_IO_CONTROL) {
05319 
05320 CompleteRDP:
05321                 // Indicate command complete.
05322                 if (!(chan->RDP)) {
05323                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete\n"));
05324 IntrCompleteReq:
05325 
05326                     if (status == SRB_STATUS_SUCCESS &&
05327                         srb->SenseInfoBuffer &&
05328                         srb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
05329 
05330                         PSENSE_DATA  senseBuffer = (PSENSE_DATA)srb->SenseInfoBuffer;
05331 
05332                         KdPrint2((PRINT_PREFIX "AtapiInterrupt: set AutoSense\n"));
05333                         senseBuffer->ErrorCode = 0;
05334                         senseBuffer->Valid     = 1;
05335                         senseBuffer->AdditionalSenseLength = 0xb;
05336                         senseBuffer->SenseKey =  0;
05337                         senseBuffer->AdditionalSenseCode = 0;
05338                         senseBuffer->AdditionalSenseCodeQualifier = 0;
05339 
05340                         srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
05341                     }
05342                     AtapiDmaDBSync(chan, srb);
05343                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove srb %#x, status %x\n", srb, status));
05344                     UniataRemoveRequest(chan, srb);
05345                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete, srb %#x\n", srb));
05346                     ScsiPortNotification(RequestComplete,
05347                                          deviceExtension,
05348                                          srb);
05349                 }
05350             } else {
05351 
05352                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n"));
05353                 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
05354 
05355                 if (status != SRB_STATUS_SUCCESS) {
05356                     error = AtapiReadPort1(chan, IDX_IO1_i_Error);
05357                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error));
05358                 }
05359 
05360                 // Build the SMART status block depending upon the completion status.
05361                 cmdOutParameters->cBufferSize = wordCount;
05362                 cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
05363                 cmdOutParameters->DriverStatus.bIDEError = error;
05364 
05365                 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
05366                 // data buffer.
05367                 if (chan->SmartCommand == RETURN_SMART_STATUS) {
05368                     cmdOutParameters->bBuffer[0] = RETURN_SMART_STATUS;
05369                     cmdOutParameters->bBuffer[1] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason);
05370                     cmdOutParameters->bBuffer[2] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Unused1);
05371                     cmdOutParameters->bBuffer[3] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
05372                     cmdOutParameters->bBuffer[4] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh);
05373                     cmdOutParameters->bBuffer[5] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_DriveSelect);
05374                     cmdOutParameters->bBuffer[6] = SMART_CMD;
05375                     cmdOutParameters->cBufferSize = 8;
05376                 }
05377 
05378                 // Indicate command complete.
05379                 goto IntrCompleteReq;
05380             }
05381 
05382         } else {
05383 
05384             KdPrint2((PRINT_PREFIX "AtapiInterrupt: No SRB!\n"));
05385         }
05386 
05387         if (chan->RDP) {
05388             // Check DSC
05389             for (i = 0; i < 5; i++) {
05390                 GetStatus(chan, statusByte);
05391                 if(!(statusByte & IDE_STATUS_BUSY)) {
05392                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: RDP + cleared BUSY\n"));
05393                     chan->RDP = FALSE;
05394                     goto CompleteRDP;
05395                 } else
05396                 if (statusByte & IDE_STATUS_DSC) {
05397                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: Clear RDP\n"));
05398                     chan->RDP = FALSE;
05399                     goto CompleteRDP;
05400                 } 
05401                 AtapiStallExecution(50);
05402             }
05403         }
05404         // RDP can be cleared since previous check
05405         if (chan->RDP) {
05406             KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestTimerCall 2000\n"));
05407 
05408             TimerValue = 2000;
05409 #ifndef UNIATA_CORE
05410             goto CallTimerDpc;
05411 #else //UNIATA_CORE
05412             AtapiStallExecution(TimerValue);
05413             goto ServiceInterrupt;
05414 #endif //UNIATA_CORE
05415         }
05416 
05417 //            ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
05418 enqueue_next_req:
05419         // Get next request
05420         srb = UniataGetCurRequest(chan);
05421 
05422 reenqueue_req:
05423 
05424 #ifndef UNIATA_CORE
05425         KdPrint2((PRINT_PREFIX "AtapiInterrupt: NextRequest, srb=%#x\n",srb));
05426         if(!srb) {
05427             ScsiPortNotification(NextRequest,
05428                                  deviceExtension,
05429                                  NULL);
05430         } else {
05431             ScsiPortNotification(NextLuRequest,
05432                                  deviceExtension, 
05433                                  PathId,
05434                                  TargetId,
05435                                  Lun);
05436             // in simplex mode next command must NOT be sent here
05437             if(!deviceExtension->simplexOnly) {
05438                 AtapiStartIo__(HwDeviceExtension, srb, FALSE);
05439             }
05440         }
05441         // Try to get SRB fron any non-empty queue (later)
05442         if(deviceExtension->simplexOnly) {
05443             NoStartIo = FALSE;
05444         }
05445 #endif //UNIATA_CORE
05446 
05447         goto ReturnEnableIntr;
05448 
05449     } else {
05450 
05451         // Unexpected int. Catch it
05452         KdPrint2((PRINT_PREFIX "AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
05453                     interruptReason,
05454                     statusByte));
05455 
05456     }
05457 
05458 ReturnEnableIntr:
05459 
05460     KdPrint2((PRINT_PREFIX "AtapiInterrupt: ReturnEnableIntr\n",srb));
05461     if(UseDpc) {
05462         if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
05463             KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
05464 #ifdef UNIATA_USE_XXableInterrupts
05465             //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
05466             chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
05467             // must be called on DISPATCH_LEVEL
05468             ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
05469                                  AtapiEnableInterrupts__);
05470 #else
05471             AtapiEnableInterrupts(HwDeviceExtension, c);
05472             InterlockedExchange(&(chan->CheckIntr),
05473                                           CHECK_INTR_IDLE);
05474             // Will raise IRQL to DIRQL
05475 #ifndef UNIATA_CORE
05476             AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
05477                                  AtapiEnableInterrupts__,
05478                                  1);
05479 #endif // UNIATA_CORE
05480             KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
05481 #endif // UNIATA_USE_XXableInterrupts
05482         }
05483     }
05484 
05485     InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
05486     // in simplex mode next command must be sent here if
05487     // DPC is not used
05488     KdPrint2((PRINT_PREFIX "AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc, NoStartIo));
05489 
05490 #ifndef UNIATA_CORE
05491     if(!UseDpc && /*deviceExtension->simplexOnly &&*/ !NoStartIo) {
05492         chan = UniataGetNextChannel(chan);
05493         if(chan) {
05494             srb = UniataGetCurRequest(chan);
05495         } else {
05496             srb = NULL;
05497         }
05498         KdPrint2((PRINT_PREFIX "AtapiInterrupt: run srb %x\n", srb));
05499         if(srb) {
05500             AtapiStartIo__(HwDeviceExtension, srb, FALSE);
05501         }
05502     }
05503 #endif //UNIATA_CORE
05504     return TRUE;
05505 
05506 } // end AtapiInterrupt__()
05507 
05508 #ifndef UNIATA_CORE
05509 
05510 /*++
05511 
05512 Routine Description:
05513 
05514     This routine handles SMART enable, disable, read attributes and threshold commands.
05515 
05516 Arguments:
05517 
05518     HwDeviceExtension - HBA miniport driver's adapter data storage
05519     Srb - IO request packet
05520 
05521 Return Value:
05522 
05523     SRB status
05524 
05525 --*/
05526 ULONG
05527 NTAPI
05528 IdeSendSmartCommand(
05529     IN PVOID HwDeviceExtension,
05530     IN PSCSI_REQUEST_BLOCK Srb
05531     )
05532 {
05533     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
05534     ULONG                c               = GET_CHANNEL(Srb);
05535     PHW_CHANNEL          chan            = &(deviceExtension->chan[c]);
05536     PATA_REQ             AtaReq          = (PATA_REQ)(Srb->SrbExtension);
05537     PSENDCMDOUTPARAMS    cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
05538     SENDCMDINPARAMS      cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
05539     PIDEREGS             regs            = &cmdInParameters.irDriveRegs;
05540 //    ULONG                i;
05541     UCHAR                statusByte,targetId;
05542 
05543 
05544     if (regs->bCommandReg != SMART_CMD) {
05545         KdPrint2((PRINT_PREFIX 
05546                     "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
05547         return SRB_STATUS_INVALID_REQUEST;
05548     }
05549 
05550     targetId = cmdInParameters.bDriveNumber;
05551 
05552     //TODO optimize this check
05553     if ((!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) ||
05554          (deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
05555 
05556         return SRB_STATUS_SELECTION_TIMEOUT;
05557     }
05558 
05559     chan->SmartCommand = regs->bFeaturesReg;
05560 
05561     // Determine which of the commands to carry out.
05562     switch(regs->bFeaturesReg) {
05563     case READ_ATTRIBUTES:
05564     case READ_THRESHOLDS:
05565 
05566         statusByte = WaitOnBusy(chan);
05567 
05568         if (statusByte & IDE_STATUS_BUSY) {
05569             KdPrint2((PRINT_PREFIX 
05570                         "IdeSendSmartCommand: Returning BUSY status\n"));
05571             return SRB_STATUS_BUSY;
05572         }
05573 
05574         // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
05575         RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1);
05576 
05577         // Set data buffer pointer and words left.
05578         AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
05579         AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2;
05580 
05581         statusByte = AtaCommand(deviceExtension, targetId & 0x1, c,
05582                    regs->bCommandReg,
05583                    (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
05584                    0,
05585                    regs->bSectorNumberReg,
05586                    regs->bSectorCountReg,
05587                    regs->bFeaturesReg,
05588                    ATA_IMMEDIATE);
05589 
05590         if(!(statusByte & IDE_STATUS_ERROR)) {
05591             // Wait for interrupt.
05592             return SRB_STATUS_PENDING;
05593         }
05594         return SRB_STATUS_ERROR;
05595 
05596     case ENABLE_SMART:
05597     case DISABLE_SMART:
05598     case RETURN_SMART_STATUS:
05599     case ENABLE_DISABLE_AUTOSAVE:
05600     case EXECUTE_OFFLINE_DIAGS:
05601     case SAVE_ATTRIBUTE_VALUES:
05602 
05603         statusByte = WaitOnBusy(chan);
05604 
05605         if (statusByte & IDE_STATUS_BUSY) {
05606             KdPrint2((PRINT_PREFIX 
05607                         "IdeSendSmartCommand: Returning BUSY status\n"));
05608             return SRB_STATUS_BUSY;
05609         }
05610 
05611         // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
05612         RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) - 1);
05613 
05614         // Set data buffer pointer and indicate no data transfer.
05615         AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
05616         AtaReq->WordsLeft = 0;
05617 
05618         statusByte = AtaCommand(deviceExtension, targetId & 0x1, c,
05619                    regs->bCommandReg,
05620                    (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
05621                    0,
05622                    regs->bSectorNumberReg,
05623                    regs->bSectorCountReg,
05624                    regs->bFeaturesReg,
05625                    ATA_IMMEDIATE);
05626 
05627         if(!(statusByte & IDE_STATUS_ERROR)) {
05628             // Wait for interrupt.
05629             return SRB_STATUS_PENDING;
05630         }
05631         return SRB_STATUS_ERROR;
05632     } // end switch(regs->bFeaturesReg)
05633 
05634     return SRB_STATUS_INVALID_REQUEST;
05635 
05636 } // end IdeSendSmartCommand()
05637 
05638 #endif //UNIATA_CORE
05639 
05640 ULONGLONG
05641 NTAPI
05642 UniAtaCalculateLBARegs(
05643     PHW_LU_EXTENSION     LunExt,
05644     ULONG                startingSector,
05645     PULONG               max_bcount
05646     )
05647 {
05648     UCHAR                drvSelect,sectorNumber;
05649     USHORT               cylinder;
05650     ULONG                tmp;
05651 
05652     if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
05653         if(LunExt->LimitedTransferMode >= ATA_DMA) {
05654             if(LunExt->DeviceExtension) {
05655                 (*max_bcount) = LunExt->DeviceExtension->MaximumDmaTransferLength / DEV_BSIZE;
05656             }
05657         }
05658         return startingSector;
05659     }
05660     tmp = LunExt->IdentifyData.SectorsPerTrack *
05661                        LunExt->IdentifyData.NumberOfHeads;
05662     if(!tmp) {
05663         KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: 0-sized\n"));
05664         cylinder     = 0;
05665         drvSelect    = 0;
05666         sectorNumber = 1;
05667         (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack;
05668     } else {
05669         cylinder =    (USHORT)(startingSector / tmp);
05670         drvSelect =   (UCHAR)((startingSector % tmp) / LunExt->IdentifyData.SectorsPerTrack); 
05671         sectorNumber = (UCHAR)(startingSector % LunExt->IdentifyData.SectorsPerTrack) + 1;
05672         (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack - sectorNumber + 1;
05673         KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
05674             cylinder, drvSelect, sectorNumber, (*max_bcount)));
05675     }
05676         (*max_bcount) = 0;
05677 
05678     return (ULONG)(sectorNumber&0xff) | (((ULONG)cylinder&0xffff)<<8) | (((ULONG)drvSelect&0xf)<<24);
05679 } // end UniAtaCalculateLBARegs()
05680 
05681 ULONGLONG
05682 NTAPI
05683 UniAtaCalculateLBARegsBack(
05684     PHW_LU_EXTENSION     LunExt,
05685     ULONGLONG            lba
05686     )
05687 {
05688     ULONG                drvSelect,sectorNumber;
05689     ULONG                cylinder;
05690     ULONG                tmp;
05691 
05692     if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
05693         return lba;
05694     }
05695     tmp = LunExt->IdentifyData.SectorsPerTrack *
05696                        LunExt->IdentifyData.NumberOfHeads;
05697 
05698     cylinder     = (USHORT)((lba >> 8) & 0xffff);
05699     drvSelect    = (UCHAR)((lba >> 24) & 0xf);
05700     sectorNumber = (UCHAR)(lba & 0xff);
05701 
05702     lba = sectorNumber-1 +
05703           (drvSelect*LunExt->IdentifyData.SectorsPerTrack) +
05704           (cylinder*tmp);
05705 
05706     return lba;
05707 } // end UniAtaCalculateLBARegsBack()
05708 
05709 
05710 /*++
05711 
05712 Routine Description:
05713 
05714     This routine handles IDE read and writes.
05715 
05716 Arguments:
05717 
05718     HwDeviceExtension - HBA miniport driver's adapter data storage
05719     Srb - IO request packet
05720 
05721 Return Value:
05722 
05723     SRB status
05724 
05725 --*/
05726 ULONG
05727 NTAPI
05728 IdeReadWrite(
05729     IN PVOID HwDeviceExtension,
05730     IN PSCSI_REQUEST_BLOCK Srb,
05731     IN ULONG CmdAction
05732     )
05733 {
05734     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
05735     UCHAR                lChannel = GET_CHANNEL(Srb);
05736     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
05737     PHW_LU_EXTENSION     LunExt;
05738     PATA_REQ             AtaReq = (PATA_REQ)(Srb->SrbExtension);
05739     //ULONG                ldev = GET_LDEV(Srb);
05740     UCHAR                DeviceNumber = GET_CDEV(Srb);;
05741     ULONG                startingSector;
05742     ULONG                max_bcount;
05743     ULONG                wordCount = 0;
05744     UCHAR                statusByte,statusByte2;
05745     UCHAR                cmd;
05746     ULONGLONG            lba;
05747     BOOLEAN              use_dma = FALSE;
05748     ULONG                fis_size;
05749 
05750     AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
05751     LunExt = chan->lun[DeviceNumber];
05752 
05753     if((CmdAction & CMD_ACTION_PREPARE) &&
05754        (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
05755 
05756         if(LunExt->opt_ReadOnly && 
05757            (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) {
05758             if(LunExt->opt_ReadOnly == 1) {
05759                 KdPrint2((PRINT_PREFIX "Abort WRITE (Soft R/O)\n"));
05760                 return SRB_STATUS_ERROR;
05761             } else {
05762                 KdPrint2((PRINT_PREFIX "Ignore WRITE (Soft R/O)\n"));
05763                 return SRB_STATUS_SUCCESS;
05764             }
05765         }
05766 
05767         // Set data buffer pointer and words left.
05768         AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
05769 
05770         if(AtaReq->WordsTransfered) {
05771             AtaReq->DataBuffer = ((PUSHORT)(Srb->DataBuffer)) + AtaReq->WordsTransfered;
05772             startingSector = (ULONG)(UniAtaCalculateLBARegsBack(LunExt, AtaReq->lba)) /* latest lba */ + AtaReq->bcount /* previous bcount */;
05773             AtaReq->bcount = (AtaReq->TransferLength - AtaReq->WordsTransfered*2 + DEV_BSIZE-1) / DEV_BSIZE;
05774             KdPrint2((PRINT_PREFIX "IdeReadWrite (Chained REQ): Starting sector %#x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
05775                        startingSector,
05776                        AtaReq->TransferLength/2,
05777                        AtaReq->WordsTransfered,
05778                        AtaReq->bcount));
05779         } else {
05780             AtaReq->DataBuffer = (PUSHORT)(Srb->DataBuffer);
05781             AtaReq->TransferLength = Srb->DataTransferLength;
05782             // Set up 1st block.
05783             MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
05784             MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
05785             KdPrint2((PRINT_PREFIX "IdeReadWrite (Orig REQ): Starting sector %#x, OrigWordsRequested %#x, DevSize %#x\n",
05786                        startingSector,
05787                        AtaReq->TransferLength/2,
05788                        AtaReq->bcount));
05789         }
05790         lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
05791 
05792         if(max_bcount) {
05793             AtaReq->bcount = min(AtaReq->bcount, max_bcount);
05794         }
05795         AtaReq->WordsLeft = min(AtaReq->TransferLength - AtaReq->WordsTransfered*2,
05796                                 AtaReq->bcount * DEV_BSIZE) / 2;
05797 
05798         KdPrint2((PRINT_PREFIX "IdeReadWrite (REQ): Starting sector is %#x, Number of WORDS %#x, DevSize %#x\n",
05799                    startingSector,
05800                    AtaReq->WordsLeft,
05801                    AtaReq->bcount));
05802 
05803         AtaReq->lba = lba;
05804 
05805         // assume best case here
05806         // we cannot reinit Dma until previous request is completed
05807         if ((LunExt->LimitedTransferMode >= ATA_DMA)) {
05808             use_dma = TRUE;
05809             // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
05810             if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
05811                           (PUCHAR)(AtaReq->DataBuffer),
05812                           AtaReq->bcount * DEV_BSIZE)) {
05813                 use_dma = FALSE;
05814             }
05815         }
05816 
05817         if(use_dma && (deviceExtension->HwFlags & UNIATA_AHCI)) {
05818             UniataAhciSetupCmdPtr(AtaReq);
05819             KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
05820             RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
05821 
05822             fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
05823                    &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
05824                     (AtaReq->Flags & REQ_FLAG_READ) ? IDE_COMMAND_READ_DMA : /*IDE_COMMAND_WRITE_DMA*/ IDE_COMMAND_READ_DMA,
05825                     lba,
05826                      (USHORT)(AtaReq->bcount),
05827                     0,
05828                     ATA_IMMEDIATE
05829                     );
05830 
05831             if(!fis_size) {
05832                 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
05833                 return SRB_STATUS_ERROR;
05834             }
05835 
05836             AtaReq->ahci.io_cmd_flags = (USHORT)(((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) |
05837                                      /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/
05838                                      (fis_size / sizeof(ULONG)) |
05839                                      (DeviceNumber << 12));
05840             KdPrint2((PRINT_PREFIX "IdeReadWrite ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
05841         }
05842 
05843         AtaReq->ReqState = REQ_STATE_READY_TO_TRANSFER;
05844 
05845     } else { // exec_only
05846         KdPrint2((PRINT_PREFIX "IdeReadWrite (ExecOnly): \n"));
05847         lba = AtaReq->lba;
05848 
05849         if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
05850             use_dma = TRUE;
05851         }
05852     }
05853     if(!(CmdAction & CMD_ACTION_EXEC)) {
05854 
05855         return SRB_STATUS_PENDING;
05856     }
05857 
05858     // if this is queued request, reinit DMA and check
05859     // if DMA mode is still available
05860     AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
05861     if (/*EnableDma &&*/
05862         (LunExt->TransferMode >= ATA_DMA)) {
05863         use_dma = TRUE;
05864     } else {
05865         AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
05866         use_dma = FALSE;
05867     }
05868 
05869     // Check if write request.
05870     if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
05871 
05872         // Prepare read command.
05873         if(use_dma) {
05874             cmd = IDE_COMMAND_READ_DMA;
05875         } else
05876         if(LunExt->MaximumBlockXfer) {
05877             cmd = IDE_COMMAND_READ_MULTIPLE;
05878         } else {
05879             cmd = IDE_COMMAND_READ;
05880         }
05881     } else {
05882 
05883         // Prepare write command.
05884         if (use_dma) {
05885             wordCount = AtaReq->bcount*DEV_BSIZE/2;
05886             cmd = IDE_COMMAND_WRITE_DMA;
05887         } else
05888         if (LunExt->MaximumBlockXfer) {
05889             wordCount = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
05890 
05891             if (AtaReq->WordsLeft < wordCount) {
05892                // Transfer only words requested.
05893                wordCount = AtaReq->WordsLeft;
05894             }
05895             cmd = IDE_COMMAND_WRITE_MULTIPLE;
05896 
05897         } else {
05898             wordCount = DEV_BSIZE/2;
05899             cmd = IDE_COMMAND_WRITE;
05900         }
05901     }
05902 
05903     // Send IO command.
05904     KdPrint2((PRINT_PREFIX "IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba, ((Srb->DataTransferLength + 0x1FF) / 0x200),
05905                                                            ((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE)));
05906     if(use_dma) {
05907         chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
05908     } else {
05909         chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
05910     }
05911 
05912     if(use_dma && (deviceExtension->HwFlags & UNIATA_AHCI)) {
05913         //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
05914         UniataAhciBeginTransaction(HwDeviceExtension, DeviceNumber, lChannel, Srb);
05915         return SRB_STATUS_PENDING;
05916     }
05917 
05918     if ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) ||
05919         use_dma) {
05920         statusByte2 = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
05921                      cmd, lba,
05922                      (USHORT)(AtaReq->bcount),
05923 //                     (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
05924                      0, ATA_IMMEDIATE);
05925         if(statusByte2 != 0xff) {
05926             GetStatus(chan, statusByte2);
05927         }
05928         if(statusByte2 & IDE_STATUS_ERROR) {
05929             statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
05930             KdPrint2((PRINT_PREFIX "IdeReadWrite: status %#x, error %#x\n", statusByte2, statusByte));
05931             return SRB_STATUS_ERROR;
05932         }
05933         if(use_dma) {
05934             AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
05935         }
05936         return SRB_STATUS_PENDING;
05937     }
05938 
05939     statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
05940                  cmd, lba,
05941                  (USHORT)(AtaReq->bcount),
05942 //                 (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
05943                  0, ATA_WAIT_INTR);
05944 
05945     if (!(statusByte & IDE_STATUS_DRQ) ||
05946         statusByte == 0xff) {
05947 
05948         if(statusByte == 0xff) {
05949             KdPrint2((PRINT_PREFIX 
05950                        "IdeReadWrite: error sending command (%#x)\n",
05951                        statusByte));
05952         } else {
05953             KdPrint2((PRINT_PREFIX 
05954                        "IdeReadWrite: DRQ never asserted (%#x)\n",
05955                        statusByte));
05956         }
05957 
05958         AtaReq->WordsLeft = 0;
05959 
05960         // Clear interrupt expecting flag.
05961         chan->ExpectingInterrupt = FALSE;
05962         InterlockedExchange(&(chan->CheckIntr),
05963                                       CHECK_INTR_IDLE);
05964 
05965         // Clear current SRB.
05966         UniataRemoveRequest(chan, Srb);
05967 
05968         return (statusByte == 0xff) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT;
05969     }
05970 
05971     chan->ExpectingInterrupt = TRUE;
05972     InterlockedExchange(&(chan->CheckIntr),
05973                                   CHECK_INTR_IDLE);
05974 
05975     // Write next DEV_BSIZE/2*N words.
05976     if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED)) {
05977         KdPrint2((PRINT_PREFIX 
05978                    "IdeReadWrite: Write %#x words\n", wordCount));
05979 
05980         WriteBuffer(chan,
05981                   AtaReq->DataBuffer,
05982                   wordCount,
05983                   UniataGetPioTiming(LunExt));
05984 
05985     } else {
05986 
05987         KdPrint2((PRINT_PREFIX 
05988                    "IdeReadWrite: Write %#x Dwords\n", wordCount/2));
05989 
05990         WriteBuffer2(chan,
05991                    (PULONG)(AtaReq->DataBuffer),
05992                    wordCount / 2,
05993                    UniataGetPioTiming(LunExt));
05994     }
05995 
05996     // Adjust buffer address and words left count.
05997     AtaReq->WordsLeft -= wordCount;
05998     AtaReq->DataBuffer += wordCount;
05999 
06000     // Wait for interrupt.
06001     return SRB_STATUS_PENDING;
06002 
06003 } // end IdeReadWrite()
06004 
06005 #ifndef UNIATA_CORE
06006 
06007 /*++
06008 
06009 Routine Description:
06010     This routine handles IDE Verify.
06011 
06012 Arguments:
06013     HwDeviceExtension - HBA miniport driver's adapter data storage
06014     Srb - IO request packet
06015     `
06016 Return Value:
06017     SRB status
06018 
06019 --*/
06020 ULONG
06021 NTAPI
06022 IdeVerify(
06023     IN PVOID HwDeviceExtension,
06024     IN PSCSI_REQUEST_BLOCK Srb
06025     )
06026 {
06027     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
06028     UCHAR                lChannel = GET_CHANNEL(Srb);
06029     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
06030     PATA_REQ             AtaReq = (PATA_REQ)(Srb->SrbExtension);
06031     PHW_LU_EXTENSION     LunExt;
06032     //ULONG                ldev = GET_LDEV(Srb);
06033     ULONG                DeviceNumber = GET_CDEV(Srb);
06034     UCHAR                statusByte;
06035     ULONG                startingSector;
06036     ULONG                max_bcount;
06037     ULONG                sectors;
06038     ULONG                endSector;
06039     USHORT               sectorCount;
06040     ULONGLONG            lba;
06041 
06042     LunExt = chan->lun[DeviceNumber];
06043     // Drive has these number sectors.
06044     if(!(sectors = (ULONG)(LunExt->NumOfSectors))) {
06045         sectors = LunExt->IdentifyData.SectorsPerTrack *
06046                   LunExt->IdentifyData.NumberOfHeads *
06047                   LunExt->IdentifyData.NumberOfCylinders;
06048     }
06049 
06050     KdPrint2((PRINT_PREFIX 
06051                 "IdeVerify: Total sectors %#x\n",
06052                 sectors));
06053 
06054     // Get starting sector number from CDB.
06055     MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
06056     MOV_DW_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
06057 
06058     KdPrint2((PRINT_PREFIX 
06059                 "IdeVerify: Starting sector %#x. Number of blocks %#x\n",
06060                 startingSector,
06061                 sectorCount));
06062 
06063     endSector = startingSector + sectorCount;
06064 
06065     KdPrint2((PRINT_PREFIX 
06066                 "IdeVerify: Ending sector %#x\n",
06067                 endSector));
06068 
06069     if (endSector > sectors) {
06070 
06071         // Too big, round down.
06072         KdPrint2((PRINT_PREFIX 
06073                     "IdeVerify: Truncating request to %#x blocks\n",
06074                     sectors - startingSector - 1));
06075 
06076         sectorCount = (USHORT)(sectors - startingSector - 1);
06077 
06078     } else {
06079 
06080         // Set up sector count register. Round up to next block.
06081         if (sectorCount > 0xFF) {
06082             sectorCount = (USHORT)0xFF;
06083         }
06084     }
06085 
06086     // Set data buffer pointer and words left.
06087     AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
06088     AtaReq->WordsLeft = Srb->DataTransferLength / 2;
06089 
06090     // Indicate expecting an interrupt.
06091     InterlockedExchange(&(chan->CheckIntr),
06092                                   CHECK_INTR_IDLE);
06093 
06094     lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
06095 
06096     statusByte = AtaCommand48(deviceExtension, LunExt->Lun, GET_CHANNEL(Srb),
06097                  IDE_COMMAND_VERIFY, lba,
06098                  sectorCount,
06099                  0, ATA_IMMEDIATE);
06100 
06101     if(!(statusByte & IDE_STATUS_ERROR)) {
06102         // Wait for interrupt.
06103         return SRB_STATUS_PENDING;
06104     }
06105     return SRB_STATUS_ERROR;
06106 
06107 } // end IdeVerify()
06108 
06109 #endif //UNIATA_CORE
06110 
06111 /*++
06112 
06113 Routine Description:
06114     Send ATAPI packet command to device.
06115 
06116 Arguments:
06117     HwDeviceExtension - HBA miniport driver's adapter data storage
06118     Srb - IO request packet
06119 
06120 Return Value:
06121 
06122 --*/
06123 ULONG
06124 NTAPI
06125 AtapiSendCommand(
06126     IN PVOID HwDeviceExtension,
06127     IN PSCSI_REQUEST_BLOCK Srb,
06128     IN ULONG CmdAction
06129     )
06130 {
06131     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
06132     UCHAR                lChannel = GET_CHANNEL(Srb);
06133     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
06134     PATA_REQ             AtaReq = (PATA_REQ)(Srb->SrbExtension);
06135     PHW_LU_EXTENSION     LunExt;
06136     //ULONG                ldev = GET_LDEV(Srb);
06137     ULONG                DeviceNumber = GET_CDEV(Srb);
06138     ULONG i;
06139     ULONG flags;
06140     UCHAR statusByte,byteCountLow,byteCountHigh;
06141     BOOLEAN use_dma = FALSE;
06142     BOOLEAN dma_reinited = FALSE;
06143     BOOLEAN retried = FALSE;
06144     ULONG                fis_size;
06145 
06146     LunExt = chan->lun[DeviceNumber];
06147 
06148     KdPrint3((PRINT_PREFIX "AtapiSendCommand: req state %#x, Action %x\n", AtaReq->ReqState, CmdAction));
06149     if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
06150         AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
06151 
06152 #ifdef UNIATA_DUMP_ATAPI
06153     if(CmdAction & CMD_ACTION_PREPARE) {
06154         UCHAR                   ScsiCommand;
06155         PCDB                    Cdb;
06156         PCHAR                   CdbData;
06157         PCHAR                   ModeSelectData;
06158         ULONG                   CdbDataLen;
06159 
06160         Cdb = (PCDB)(Srb->Cdb);
06161         ScsiCommand = Cdb->CDB6.OperationCode;
06162         CdbData = (PCHAR)(Srb->DataBuffer);
06163         CdbDataLen = Srb->DataTransferLength;
06164 
06165         if(CdbDataLen > 0x1000) {
06166             CdbDataLen = 0x1000;
06167         }
06168 
06169         KdPrint(("--\n"));
06170         KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
06171         KdPrint2(("P:T:D=%d:%d:%d\n",
06172                                   Srb->PathId,
06173                                   Srb->TargetId,
06174                                   Srb->Lun));
06175         KdPrint(("SCSI Command %2.2x\n", ScsiCommand));
06176         KdDump(Cdb, 16);
06177 
06178         if(ScsiCommand == SCSIOP_WRITE_CD) {
06179             KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
06180                      Cdb->WRITE_CD.LBA[0],
06181                      Cdb->WRITE_CD.LBA[1],
06182                      Cdb->WRITE_CD.LBA[2],
06183                      Cdb->WRITE_CD.LBA[3]
06184                      ));
06185         } else
06186         if(ScsiCommand == SCSIOP_WRITE12) {
06187             KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
06188                      Cdb->CDB12READWRITE.LBA[0],
06189                      Cdb->CDB12READWRITE.LBA[1],
06190                      Cdb->CDB12READWRITE.LBA[2],
06191                      Cdb->CDB12READWRITE.LBA[3]
06192                      ));
06193         } else
06194         if(ScsiCommand == SCSIOP_MODE_SELECT) {
06195             KdPrint(("ModeSelect 6\n"));
06196             PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
06197             ModeSelectData = CdbData+4;
06198             KdDump(CdbData, CdbDataLen);
06199         } else
06200         if(ScsiCommand == SCSIOP_MODE_SELECT10) {
06201             KdPrint(("ModeSelect 10\n"));
06202             PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
06203             ModeSelectData = CdbData+8;
06204             KdDump(CdbData, CdbDataLen);
06205         } else {
06206             if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
06207                 KdPrint(("Send buffer to device:\n"));
06208                 KdDump(CdbData, CdbDataLen);
06209             }
06210         }
06211         KdPrint(("--\n"));
06212     }
06213 #endif //UNIATA_DUMP_ATAPI
06214 
06215 
06216     if(CmdAction == CMD_ACTION_PREPARE) {
06217         KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE\n"));
06218         switch (Srb->Cdb[0]) {
06219         case SCSIOP_READ:
06220         case SCSIOP_WRITE:
06221         case SCSIOP_READ12:
06222         case SCSIOP_WRITE12:
06223             // all right
06224             break;
06225         default:
06226             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY\n"));
06227             return SRB_STATUS_BUSY;
06228         }
06229         //
06230         if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
06231             !AtaReq->OriginalSrb) {
06232             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
06233             return SRB_STATUS_BUSY;
06234         }
06235     }
06236 
06237     if((CmdAction & CMD_ACTION_PREPARE) &&
06238        (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
06239 
06240         KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x\n", Srb->Cdb[0]));
06241         // Set data buffer pointer and words left.
06242         AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
06243         AtaReq->WordsLeft = Srb->DataTransferLength / 2;
06244         AtaReq->TransferLength = Srb->DataTransferLength;
06245         AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
06246 
06247         // check if reorderable
06248         switch(Srb->Cdb[0]) {
06249         case SCSIOP_READ12:
06250         case SCSIOP_WRITE12:
06251 
06252             MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
06253             goto GetLba;
06254 
06255         case SCSIOP_READ:
06256         case SCSIOP_WRITE:
06257 
06258             MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
06259 GetLba:
06260             MOV_DD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB10.LBA);
06261 
06262             AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
06263             AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
06264             AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE || Srb->Cdb[0] == SCSIOP_WRITE12) ?
06265                               REQ_FLAG_WRITE : REQ_FLAG_READ;
06266             break;
06267         }
06268 
06269         // check if DMA read/write
06270         if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
06271             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
06272         } else
06273         if(AtaReq->TransferLength) {
06274             // try use DMA
06275             switch(Srb->Cdb[0]) {
06276             case SCSIOP_WRITE:
06277             case SCSIOP_WRITE12:
06278                 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO)
06279                     break;
06280                 /* FALLTHROUGH */
06281             case SCSIOP_READ:
06282             case SCSIOP_READ12:
06283 
06284                 if(deviceExtension->opt_AtapiDmaReadWrite) {
06285 call_dma_setup:
06286                     if(AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
06287                                   (PUCHAR)(AtaReq->DataBuffer),
06288                                   Srb->DataTransferLength
06289                                   /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
06290                                   )) {
06291                         KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
06292                         use_dma = TRUE;
06293                     }
06294                 }
06295                 break;
06296             case SCSIOP_READ_CD:
06297                 if(deviceExtension->opt_AtapiDmaRawRead)
06298                     goto call_dma_setup;
06299                 break;
06300             default:
06301 
06302                 if(deviceExtension->opt_AtapiDmaControlCmd) {
06303                     if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
06304                         // read operation
06305                         use_dma = TRUE;
06306                     } else {
06307                         // write operation
06308                         if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) {
06309                             KdPrint2((PRINT_PREFIX "dma RO\n"));
06310                             use_dma = FALSE;
06311                         } else {
06312                             use_dma = TRUE;
06313                         }
06314                     }
06315                 }
06316                 break;
06317             }
06318             // try setup DMA
06319             if(use_dma) {
06320                 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
06321                               (PUCHAR)(AtaReq->DataBuffer),
06322                               Srb->DataTransferLength)) {
06323                     KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma\n"));
06324                     use_dma = FALSE;
06325                 } else {
06326                     KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
06327                 }
06328             }
06329         } else {
06330             KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer, no DMA setup\n"));
06331         }
06332 
06333 
06334         if(deviceExtension->HwFlags & UNIATA_AHCI) {
06335             UniataAhciSetupCmdPtr(AtaReq);
06336             KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
06337             RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
06338             RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, 16);
06339 
06340             fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
06341                    &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
06342                     IDE_COMMAND_ATAPI_PACKET /* command */,
06343                     0 /* lba */,
06344                     (Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength),
06345                     use_dma ? ATA_F_DMA : 0/* feature */,
06346                     ATA_IMMEDIATE /* flags */
06347                     );
06348 
06349             if(!fis_size) {
06350                 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
06351                 return SRB_STATUS_ERROR;
06352             }
06353 
06354             AtaReq->ahci.io_cmd_flags = (USHORT)(((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) |
06355                                      /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/
06356                                      (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) |
06357                                      (fis_size / sizeof(ULONG)) |
06358                                      (DeviceNumber << 12));
06359             KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
06360         }
06361     
06362     } else {
06363         if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
06364             // if this is queued request, reinit DMA and check
06365             // if DMA mode is still available
06366             KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()  (1)\n"));
06367             AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
06368             if (/*EnableDma &&*/
06369                 (LunExt->TransferMode >= ATA_DMA)) {
06370                 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (2)\n"));
06371                 use_dma = TRUE;
06372             } else {
06373                 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
06374                 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma (2)\n"));
06375                 use_dma = FALSE;
06376             }
06377             dma_reinited = TRUE;
06378         }
06379     }
06380 
06381     if(!(CmdAction & CMD_ACTION_EXEC)) {
06382         KdPrint2((PRINT_PREFIX "AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
06383         return SRB_STATUS_PENDING;
06384     }
06385     KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
06386     if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
06387         KdPrint2((PRINT_PREFIX "  REQ_FLAG_DMA_OPERATION\n"));
06388     }
06389 
06390     if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
06391         KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
06392         use_dma = FALSE;
06393         AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
06394         //AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
06395     } if(AtaReq->TransferLength) {
06396         if(!dma_reinited) {
06397             KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()\n"));
06398             AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
06399             if (/*EnableDma &&*/
06400                 (LunExt->TransferMode >= ATA_DMA)) {
06401                 use_dma = TRUE;
06402             } else {
06403                 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
06404                 use_dma = FALSE;
06405             }
06406         }
06407     } else {
06408         KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer\n"));
06409         use_dma = FALSE;
06410         AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
06411         if(!deviceExtension->opt_AtapiDmaZeroTransfer) {
06412             KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
06413             AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
06414         }
06415     }
06416     KdPrint2((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
06417     if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
06418         KdPrint2((PRINT_PREFIX "  REQ_FLAG_DMA_OPERATION\n"));
06419     }
06420     
06421     KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_EXEC\n"));
06422 
06423 #ifndef UNIATA_CORE
06424     // We need to know how many platters our atapi cd-rom device might have.
06425     // Before anyone tries to send a srb to our target for the first time,
06426     // we must "secretly" send down a separate mechanism status srb in order to
06427     // initialize our device extension changer data.  That's how we know how
06428     // many platters our target has.
06429 
06430     if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
06431         !AtaReq->OriginalSrb) {
06432 
06433         ULONG srbStatus;
06434 
06435         KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n"));
06436         // Set this flag now. If the device hangs on the mech. status
06437         // command, we will not have the chance to set it.
06438         LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
06439 
06440         chan->MechStatusRetryCount = 3;
06441         AtaReq->OriginalSrb = Srb;
06442         AtaReq->Srb = BuildMechanismStatusSrb (
06443                                         HwDeviceExtension,
06444                                         Srb);
06445 
06446         KdPrint3((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n"));
06447         srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
06448         if (srbStatus == SRB_STATUS_PENDING) {
06449             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
06450             return srbStatus;
06451         } else {
06452             AtaReq->Srb = AtaReq->OriginalSrb;
06453             AtaReq->OriginalSrb = NULL;
06454             KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiHwInitializeChanger()\n"));
06455             AtapiHwInitializeChanger (HwDeviceExtension, Srb,
06456                                       (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
06457             // fall out
06458         }
06459     }
06460 #endif //UNIATA_CORE
06461 
06462     KdPrint3((PRINT_PREFIX "AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
06463                Srb->Cdb[0], Srb->TargetId, Srb->Lun));
06464     
06465     // Make sure command is to ATAPI device.
06466     flags = LunExt->DeviceFlags;
06467     if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
06468         if((Srb->Lun) > (LunExt->DiscsPresent - 1)) {
06469 
06470             // Indicate no device found at this address.
06471             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
06472             return SRB_STATUS_SELECTION_TIMEOUT;
06473         }
06474     } else if(Srb->Lun > 0) {
06475         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
06476         return SRB_STATUS_SELECTION_TIMEOUT;
06477     }
06478 
06479     if(!(flags & DFLAGS_ATAPI_DEVICE)) {
06480         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
06481         return SRB_STATUS_SELECTION_TIMEOUT;
06482     }
06483 retry:
06484     if(deviceExtension->HwFlags & UNIATA_AHCI) {
06485         KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n"));
06486         if(use_dma) {
06487             chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
06488         } else {
06489             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
06490         }
06491         UniataAhciBeginTransaction(HwDeviceExtension, DeviceNumber, lChannel, Srb);
06492         return SRB_STATUS_PENDING;
06493     }
06494 
06495     // Select device 0 or 1.
06496     SelectDrive(chan, DeviceNumber);
06497 
06498     // Verify that controller is ready for next command.
06499     GetStatus(chan, statusByte);
06500     KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte));
06501 
06502     if(statusByte == 0xff) {
06503         KdPrint2((PRINT_PREFIX "AtapiSendCommand: bad status 0xff on entry\n"));
06504         goto make_reset;
06505     }
06506     if(statusByte & IDE_STATUS_BUSY) {
06507         if(statusByte & IDE_STATUS_DSC) {
06508             KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte));
06509         } else {
06510             KdPrint2((PRINT_PREFIX "AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte));
06511             // We have to make reset here, since we are expecting device to be available
06512             //return SRB_STATUS_BUSY; // this cause queue freeze
06513             goto make_reset;
06514         }
06515     }
06516     if(statusByte & IDE_STATUS_ERROR) {
06517         if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
06518 
06519             KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on entry: (%#x)\n", statusByte));
06520             // Read the error reg. to clear it and fail this request.
06521             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
06522             return MapError(deviceExtension, Srb);
06523         } else {
06524             KdPrint2((PRINT_PREFIX "  continue with SCSIOP_REQUEST_SENSE\n", statusByte));
06525         }
06526     }
06527     // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
06528     // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
06529     if((!(statusByte & IDE_STATUS_DSC)) &&
06530           (flags & (DFLAGS_TAPE_DEVICE | DFLAGS_ATAPI_DEVICE)) && chan->RDP) {
06531 
06532         AtapiStallExecution(200);
06533         KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte));
06534         AtaReq->ReqState = REQ_STATE_QUEUED;
06535         return SRB_STATUS_PENDING;
06536     }
06537 
06538     if(IS_RDP(Srb->Cdb[0])) {
06539         chan->RDP = TRUE;
06540         KdPrint2((PRINT_PREFIX "AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb->Cdb[0]));
06541     } else {
06542         chan->RDP = FALSE;
06543     }
06544     if(statusByte & IDE_STATUS_DRQ) {
06545 
06546         KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
06547                     statusByte));
06548         // Try to drain the data that one preliminary device thinks that it has
06549         // to transfer. Hopefully this random assertion of DRQ will not be present
06550         // in production devices.
06551         for (i = 0; i < 0x10000; i++) {
06552             GetStatus(chan, statusByte);
06553             if(statusByte & IDE_STATUS_DRQ) {
06554                 AtapiReadPort2(chan, IDX_IO1_i_Data);
06555             } else {
06556                 break;
06557             }
06558         }
06559 
06560         if (i == 0x10000) {
06561 make_reset:
06562             KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
06563 
06564             AtapiDisableInterrupts(deviceExtension, lChannel);
06565 
06566             AtapiSoftReset(chan, DeviceNumber);
06567 
06568             KdPrint2((PRINT_PREFIX "AtapiSendCommand: Issued soft reset to Atapi device. \n"));
06569             // Re-initialize Atapi device.
06570             CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), DeviceNumber, TRUE);
06571 /*
06572             IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
06573                           IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
06574 */
06575             // Inform the port driver that the bus has been reset.
06576             ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
06577             // Clean up device extension fields that AtapiStartIo won't.
06578             chan->ExpectingInterrupt = FALSE;
06579             chan->RDP = FALSE;
06580             InterlockedExchange(&(deviceExtension->chan[GET_CHANNEL(Srb)].CheckIntr),
06581                                           CHECK_INTR_IDLE);
06582 
06583             AtapiEnableInterrupts(deviceExtension, lChannel);
06584 /*
06585             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
06586             return SRB_STATUS_BUS_RESET;
06587 */
06588             if(!retried) {
06589                 KdPrint3((PRINT_PREFIX "AtapiSendCommand: retry after reset.\n"));
06590                 retried = TRUE;
06591                 goto retry;
06592             }
06593             KdPrint3((PRINT_PREFIX "AtapiSendCommand: selection timeout.\n"));
06594             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
06595             return SRB_STATUS_SELECTION_TIMEOUT;
06596         }
06597     }
06598 
06599     if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
06600         // As the cdrom driver sets the LUN field in the cdb, it must be removed.
06601         Srb->Cdb[1] &= ~0xE0;
06602         if((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) {
06603             // Torisan changer. TUR's are overloaded to be platter switches.
06604             Srb->Cdb[7] = Srb->Lun;
06605         }
06606     }
06607 
06608     // SETUP DMA !!!!!
06609 
06610     if(use_dma) {
06611         chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
06612     } else {
06613         chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
06614     }
06615 
06616     statusByte = WaitOnBusy(chan);
06617     KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n",
06618                statusByte));
06619 
06620     AtapiWritePort1(chan, IDX_IO1_o_Feature,
06621                             use_dma ? ATA_F_DMA : 0);
06622 
06623     // Write transfer byte count to registers.
06624     byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
06625     byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
06626 
06627     if (Srb->DataTransferLength >= 0x10000) {
06628         byteCountLow = byteCountHigh = 0xFF;
06629     }
06630 
06631     AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow);
06632     AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh);
06633 
06634     if (flags & DFLAGS_INT_DRQ) {
06635 
06636         // This device interrupts when ready to receive the packet.
06637 
06638         KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
06639                    statusByte));
06640 
06641         chan->ExpectingInterrupt = TRUE;
06642         AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR;
06643         InterlockedExchange(&(chan->CheckIntr),
06644                                       CHECK_INTR_IDLE);
06645 
06646         // Write ATAPI packet command.
06647         AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
06648 
06649         KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
06650         return SRB_STATUS_PENDING;
06651 
06652     }
06653 
06654     // This device quickly sets DRQ when ready to receive the packet.
06655 
06656     KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
06657                statusByte));
06658 
06659     chan->ExpectingInterrupt = TRUE;
06660     AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR;
06661     InterlockedExchange(&(chan->CheckIntr),
06662                                   CHECK_INTR_IDLE);
06663 
06664     if(g_opt_AtapiSendDisableIntr) {
06665         AtapiDisableInterrupts(deviceExtension, lChannel);
06666     }
06667 
06668     // Write ATAPI packet command.
06669     AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
06670 
06671     // Wait for DRQ.
06672     WaitOnBusy(chan);
06673     statusByte = WaitForDrq(chan);
06674 
06675     // Need to read status register and clear interrupt (if any)
06676     GetBaseStatus(chan, statusByte);
06677 
06678     if (!(statusByte & IDE_STATUS_DRQ)) {
06679 
06680         if(g_opt_AtapiSendDisableIntr) {
06681             AtapiEnableInterrupts(deviceExtension, lChannel);
06682         }
06683         KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte));
06684         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
06685         return SRB_STATUS_ERROR;
06686     }
06687 
06688     GetStatus(chan, statusByte);
06689     KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
06690 
06691     // Send CDB to device.
06692     statusByte = WaitOnBaseBusy(chan);
06693 
06694     // Indicate expecting an interrupt and wait for it.
06695     chan->ExpectingInterrupt = TRUE;
06696     InterlockedExchange(&(chan->CheckIntr),
06697                                   CHECK_INTR_IDLE);
06698     AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
06699 
06700     GetBaseStatus(chan, statusByte);
06701 
06702     if(g_opt_AtapiSendDisableIntr) {
06703         AtapiEnableInterrupts(deviceExtension, lChannel);
06704     }
06705 
06706     WriteBuffer(chan,
06707                 (PUSHORT)Srb->Cdb,
06708                 6,
06709                 0);
06710 
06711     if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
06712         AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
06713     }
06714 
06715     KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt));
06716 
06717     KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
06718     return SRB_STATUS_PENDING;
06719 
06720 } // end AtapiSendCommand()
06721 
06722 
06723 #ifndef UNIATA_CORE
06724 
06725 /*++
06726 
06727 Routine Description:
06728     Program ATA registers for IDE disk transfer.
06729 
06730 Arguments:
06731     HwDeviceExtension - ATAPI driver storage.
06732     Srb - System request block.
06733 
06734 Return Value:
06735     SRB status (pending if all goes well).
06736 
06737 --*/
06738 
06739 #ifdef _DEBUG
06740 ULONG check_point = 0;
06741 #define SetCheckPoint(cp)  { check_point = (cp) ; }
06742 #else
06743 #define SetCheckPoint(cp)
06744 #endif
06745 
06746 ULONG
06747 NTAPI
06748 IdeSendCommand(
06749     IN PVOID HwDeviceExtension,
06750     IN PSCSI_REQUEST_BLOCK Srb,
06751     IN ULONG CmdAction
06752     )
06753 {
06754     SetCheckPoint(1);
06755     KdPrint2((PRINT_PREFIX "** Ide: Command: entryway\n"));
06756     SetCheckPoint(2);
06757 
06758     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
06759     SetCheckPoint(3);
06760     UCHAR                lChannel;
06761     PHW_CHANNEL          chan;
06762     PCDB cdb;
06763 
06764     SetCheckPoint(4);
06765 
06766     UCHAR statusByte,errorByte;
06767     ULONG status;
06768     ULONG i;
06769     PMODE_PARAMETER_HEADER   modeData;
06770     //ULONG ldev;
06771     ULONG DeviceNumber;
06772     PATA_REQ AtaReq;
06773     SetCheckPoint(5);
06774     //ULONG __ebp__ = 0;
06775 
06776     SetCheckPoint(0x20);
06777     KdPrint2((PRINT_PREFIX "** Ide: Command:\n\n"));
06778 /*    __asm {
06779         mov eax,ebp
06780         mov __ebp__, eax
06781     }*/
06782     /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
06783         __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
06784     KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
06785         (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
06786     KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
06787         Srb));
06788     KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
06789         Srb->SrbExtension));
06790     KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
06791         Srb->TargetId));*/
06792 
06793     SetCheckPoint(0x30);
06794     AtaReq = (PATA_REQ)(Srb->SrbExtension);
06795 
06796     KdPrint2((PRINT_PREFIX "** Ide: Command &AtaReq %#x\n",
06797         &AtaReq));
06798     KdPrint2((PRINT_PREFIX "** Ide: Command AtaReq %#x\n",
06799         AtaReq));
06800     KdPrint2((PRINT_PREFIX "** --- **\n"));
06801 
06802     lChannel = GET_CHANNEL(Srb);
06803     chan = &(deviceExtension->chan[lChannel]);
06804     //ldev = GET_LDEV(Srb);
06805     DeviceNumber = GET_CDEV(Srb);
06806 
06807     SetCheckPoint(0x40);
06808     if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
06809         AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
06810 
06811     if(CmdAction == CMD_ACTION_PREPARE) {
06812         switch (Srb->Cdb[0]) {
06813 #ifdef NAVO_TEST
06814         case SCSIOP_INQUIRY: // now it requires device access
06815 #endif //NAVO_TEST
06816         case SCSIOP_READ_CAPACITY:
06817         case SCSIOP_READ:
06818         case SCSIOP_WRITE:
06819         case SCSIOP_REQUEST_SENSE:
06820             // all right
06821             KdPrint2((PRINT_PREFIX "** Ide: Command continue prep\n"));
06822             SetCheckPoint(50);
06823             break;
06824         default:
06825             SetCheckPoint(0);
06826             KdPrint2((PRINT_PREFIX "** Ide: Command break prep\n"));
06827             return SRB_STATUS_BUSY;
06828         }
06829     }
06830 
06831     SetCheckPoint(0x100 | Srb->Cdb[0]);
06832     switch (Srb->Cdb[0]) {
06833     case SCSIOP_INQUIRY:
06834 
06835         KdPrint2((PRINT_PREFIX 
06836                    "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
06837                    Srb->PathId, Srb->Lun, Srb->TargetId));
06838         // Filter out all TIDs but 0 and 1 since this is an IDE interface
06839         // which support up to two devices.
06840         if ((Srb->Lun != 0) ||
06841             (Srb->PathId >= deviceExtension->NumberChannels) ||
06842             (Srb->TargetId > deviceExtension->NumberLuns)) {
06843 
06844             KdPrint2((PRINT_PREFIX 
06845                        "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
06846             // Indicate no device found at this address.
06847             status = SRB_STATUS_SELECTION_TIMEOUT;
06848             break;
06849 
06850         } else {
06851 
06852             KdPrint2((PRINT_PREFIX 
06853                        "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
06854             PINQUIRYDATA    inquiryData  = (PINQUIRYDATA)(Srb->DataBuffer);
06855             PIDENTIFY_DATA2 identifyData = &(chan->lun[DeviceNumber]->IdentifyData);
06856 
06857             if (!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
06858                 
06859                 if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
06860                     KdPrint2((PRINT_PREFIX 
06861                                "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
06862                     // Indicate no device found at this address.
06863 #ifndef NAVO_TEST
06864                     status = SRB_STATUS_SELECTION_TIMEOUT;
06865                     break;
06866                 }
06867             } else {
06868                 if(!UniataAnybodyHome(HwDeviceExtension, lChannel, DeviceNumber)) {
06869                     KdPrint2((PRINT_PREFIX 
06870                                "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
06871                     // Indicate no device found at this address.
06872                     UniataForgetDevice(chan->lun[DeviceNumber]);
06873 #endif //NAVO_TEST
06874                     status = SRB_STATUS_SELECTION_TIMEOUT;
06875                     break;
06876                 }
06877             }
06878 
06879             // Zero INQUIRY data structure.
06880             RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
06881 
06882             // Standard IDE interface only supports disks.
06883             inquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
06884 
06885             // Set the removable bit, if applicable.
06886             if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
06887                 KdPrint2((PRINT_PREFIX 
06888                            "RemovableMedia\n"));
06889                 inquiryData->RemovableMedia = 1;
06890             }
06891             // Set the Relative Addressing (LBA) bit, if applicable.
06892             if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) {
06893                 inquiryData->RelativeAddressing = 1;
06894                 KdPrint2((PRINT_PREFIX 
06895                            "RelativeAddressing\n"));
06896             }
06897             // Set the CommandQueue bit
06898             inquiryData->CommandQueue = 1;
06899 
06900             // Fill in vendor identification fields.
06901             for (i = 0; i < 24; i += 2) {
06902                 MOV_DW_SWP(inquiryData->VendorId[i], ((PUCHAR)identifyData->ModelNumber)[i]);
06903             }
06904 /*
06905             // Initialize unused portion of product id.
06906             for (i = 0; i < 4; i++) {
06907                 inquiryData->ProductId[12+i] = ' ';
06908             }
06909 */
06910             // Move firmware revision from IDENTIFY data to
06911             // product revision in INQUIRY data.
06912             for (i = 0; i < 4; i += 2) {
06913                 MOV_DW_SWP(inquiryData->ProductRevisionLevel[i], ((PUCHAR)identifyData->FirmwareRevision)[i]);
06914             }
06915 
06916             status = SRB_STATUS_SUCCESS;
06917         }
06918 
06919         break;
06920 
06921     case SCSIOP_MODE_SENSE:
06922 
06923         KdPrint2((PRINT_PREFIX 
06924                    "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
06925                    Srb->PathId, Srb->Lun, Srb->TargetId));
06926         // This is used to determine if the media is write-protected.
06927         // Since IDE does not support mode sense then we will modify just the portion we need
06928         // so the higher level driver can determine if media is protected.
06929         if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
06930 
06931             SelectDrive(chan, DeviceNumber);
06932             AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
06933             statusByte = WaitOnBusy(chan);
06934 
06935             if (!(statusByte & IDE_STATUS_ERROR)){
06936 
06937                 // no error occured return success, media is not protected
06938                 chan->ExpectingInterrupt = FALSE;
06939                 InterlockedExchange(&(chan->CheckIntr),
06940                                               CHECK_INTR_IDLE);
06941                 status = SRB_STATUS_SUCCESS;
06942 
06943             } else {
06944 
06945                 // error occured, handle it locally, clear interrupt
06946                 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
06947 
06948                 GetBaseStatus(chan, statusByte);
06949                 chan->ExpectingInterrupt = FALSE;
06950                 InterlockedExchange(&(chan->CheckIntr),
06951                                               CHECK_INTR_IDLE);
06952                 status = SRB_STATUS_SUCCESS;
06953 
06954                 if (errorByte & IDE_ERROR_DATA_ERROR) {
06955 
06956                     //media is write-protected, set bit in mode sense buffer
06957                     modeData = (PMODE_PARAMETER_HEADER)Srb->DataBuffer;
06958 
06959                     Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER);
06960                     modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
06961                 }
06962             }
06963             status = SRB_STATUS_SUCCESS;
06964         } else {
06965             status = SRB_STATUS_INVALID_REQUEST;
06966         }
06967         break;
06968 
06969     case SCSIOP_TEST_UNIT_READY:
06970 
06971         KdPrint2((PRINT_PREFIX 
06972                    "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
06973                    Srb->PathId, Srb->Lun, Srb->TargetId));
06974         if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
06975 
06976             // Select device 0 or 1.
06977             SelectDrive(chan, DeviceNumber);
06978             AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
06979 
06980             // Wait for busy. If media has not changed, return success
06981             statusByte = WaitOnBusy(chan);
06982 
06983             if (!(statusByte & IDE_STATUS_ERROR)){
06984                 chan->ExpectingInterrupt = FALSE;
06985                 InterlockedExchange(&(chan->CheckIntr),
06986                                               CHECK_INTR_IDLE);
06987                 status = SRB_STATUS_SUCCESS;
06988             } else {
06989                 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
06990                 if (errorByte == IDE_ERROR_DATA_ERROR){
06991 
06992                     // Special case: If current media is write-protected,
06993                     // the 0xDA command will always fail since the write-protect bit
06994                     // is sticky,so we can ignore this error
06995                     GetBaseStatus(chan, statusByte);
06996                     chan->ExpectingInterrupt = FALSE;
06997                     InterlockedExchange(&(chan->CheckIntr),
06998                                                   CHECK_INTR_IDLE);
06999                     status = SRB_STATUS_SUCCESS;
07000 
07001                 } else {
07002 
07003                     // Request sense buffer to be build
07004                     chan->ExpectingInterrupt = TRUE;
07005                     InterlockedExchange(&(chan->CheckIntr),
07006                                                   CHECK_INTR_IDLE);
07007                     status = SRB_STATUS_PENDING;
07008                }
07009             }
07010         } else {
07011             status = SRB_STATUS_SUCCESS;
07012         }
07013 
07014         break;
07015 
07016     case SCSIOP_READ_CAPACITY:
07017 
07018         KdPrint2((PRINT_PREFIX 
07019                    "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
07020                    Srb->PathId, Srb->Lun, Srb->TargetId));
07021         // Claim 512 byte blocks (big-endian).
07022         //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
07023         i = DEV_BSIZE;
07024         MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i );
07025 
07026         // Calculate last sector.
07027         if(!(i = (ULONG)chan->lun[DeviceNumber]->NumOfSectors)) {
07028             i = chan->lun[DeviceNumber]->IdentifyData.SectorsPerTrack *
07029                 chan->lun[DeviceNumber]->IdentifyData.NumberOfHeads *
07030                 chan->lun[DeviceNumber]->IdentifyData.NumberOfCylinders;
07031         }
07032         i--;
07033 
07034         //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
07035         //    (((PUCHAR)&i)[0] << 24) |  (((PUCHAR)&i)[1] << 16) |
07036         //    (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
07037 
07038         MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress, i );
07039 
07040         KdPrint2((PRINT_PREFIX 
07041                    "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
07042                    Srb->TargetId,
07043                    chan->lun[DeviceNumber]->IdentifyData.SectorsPerTrack,
07044                    chan->lun[DeviceNumber]->IdentifyData.NumberOfHeads,
07045                    chan->lun[DeviceNumber]->IdentifyData.NumberOfCylinders));
07046 
07047 
07048         status = SRB_STATUS_SUCCESS;
07049         break;
07050 
07051     case SCSIOP_VERIFY:
07052 
07053         KdPrint2((PRINT_PREFIX 
07054                    "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
07055                    Srb->PathId, Srb->Lun, Srb->TargetId));
07056         status = IdeVerify(HwDeviceExtension,Srb);
07057 
07058         break;
07059 
07060     case SCSIOP_READ:
07061     case SCSIOP_WRITE:
07062 
07063         KdPrint2((PRINT_PREFIX 
07064                    "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
07065                    (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ",
07066                    Srb->PathId, Srb->Lun, Srb->TargetId));
07067         AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
07068         AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE) ? REQ_FLAG_WRITE : REQ_FLAG_READ;
07069         status = IdeReadWrite(HwDeviceExtension,
07070                               Srb, CmdAction);
07071         break;
07072 
07073     case SCSIOP_START_STOP_UNIT:
07074 
07075         KdPrint2((PRINT_PREFIX 
07076                    "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
07077                    Srb->PathId, Srb->Lun, Srb->TargetId));
07078         //Determine what type of operation we should perform
07079         cdb = (PCDB)Srb->Cdb;
07080 
07081         if (cdb->START_STOP.LoadEject == 1){
07082 
07083             statusByte = WaitOnBaseBusy(chan);
07084             // Eject media,
07085             // first select device 0 or 1.
07086             SelectDrive(chan, DeviceNumber);
07087             AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
07088         }
07089         status = SRB_STATUS_SUCCESS;
07090         break;
07091 
07092     case SCSIOP_MEDIUM_REMOVAL:
07093 
07094        cdb = (PCDB)Srb->Cdb;
07095 
07096        statusByte = WaitOnBaseBusy(chan);
07097 
07098        SelectDrive(chan, DeviceNumber);
07099        if (cdb->MEDIA_REMOVAL.Prevent == TRUE) {
07100            AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
07101        } else {
07102            AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
07103        }
07104        status = SRB_STATUS_SUCCESS;
07105        break;
07106 
07107     // Note: I don't implement this, because NTFS driver too often issues this command
07108     // It causes awful performance degrade. However, if somebody wants, I will implement
07109     // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
07110 
07111 #if 0
07112     case SCSIOP_FLUSH_BUFFER:
07113     case SCSIOP_SYNCHRONIZE_CACHE:
07114 
07115         SelectDrive(chan, DeviceNumber);
07116         AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_FLUSH_CACHE);
07117         status = SRB_STATUS_SUCCESS;
07118 //        status = SRB_STATUS_PENDING;
07119         statusByte = WaitOnBusy(chan);
07120         break;
07121 #endif
07122 
07123     case SCSIOP_REQUEST_SENSE:
07124         // this function makes sense buffers to report the results
07125         // of the original GET_MEDIA_STATUS command
07126 
07127         KdPrint2((PRINT_PREFIX 
07128                    "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
07129                    Srb->PathId, Srb->Lun, Srb->TargetId));
07130         if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
07131             status = IdeBuildSenseBuffer(HwDeviceExtension,Srb);
07132             break;
07133         }
07134         status = SRB_STATUS_INVALID_REQUEST;
07135         break;
07136 
07137     // ATA_PASSTHORUGH
07138     case SCSIOP_ATA_PASSTHROUGH:
07139     {
07140         PIDEREGS_EX regs;
07141         BOOLEAN use_dma = FALSE;
07142         ULONG to_lim;
07143         
07144         regs = (PIDEREGS_EX) &(Srb->Cdb[2]);
07145 
07146         lChannel = Srb->TargetId >> 1;
07147 
07148         regs->bDriveHeadReg &= 0x0f;
07149         regs->bDriveHeadReg |= (UCHAR) (((Srb->TargetId & 0x1) << 4) | 0xA0);
07150 
07151         if((regs->bOpFlags & 1) == 0) {      // execute ATA command
07152 
07153             KdPrint2((PRINT_PREFIX 
07154                        "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
07155                        Srb->PathId, Srb->Lun, Srb->TargetId));
07156 
07157 
07158             AtapiDisableInterrupts(deviceExtension, lChannel);
07159 
07160             if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) {
07161                 if((chan->lun[Srb->TargetId & 0x1]->LimitedTransferMode >= ATA_DMA)) {
07162                     use_dma = TRUE;
07163                     // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
07164                     if(!AtapiDmaSetup(HwDeviceExtension, Srb->TargetId & 0x1, lChannel, Srb,
07165                                   (PUCHAR)(Srb->DataBuffer),
07166                                   ((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) {
07167                         use_dma = FALSE;
07168                     }
07169                 }
07170             }
07171 
07172             AtapiWritePort1(chan, IDX_IO1_o_DriveSelect,  regs->bDriveHeadReg);
07173             AtapiStallExecution(10);
07174 
07175             if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {      // execute ATA command
07176                 AtapiWritePort1(chan, IDX_IO1_o_Feature,      regs->bFeaturesReg);
07177                 AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   regs->bSectorCountReg);
07178                 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  regs->bSectorNumberReg);
07179                 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  regs->bCylLowReg);
07180                 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
07181             } else {
07182                 AtapiWritePort1(chan, IDX_IO1_o_Feature,      regs->bFeaturesRegH);
07183                 AtapiWritePort1(chan, IDX_IO1_o_Feature,      regs->bFeaturesReg);
07184                 AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   regs->bSectorCountRegH);
07185                 AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   regs->bSectorCountReg);
07186                 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  regs->bSectorNumberRegH);
07187                 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  regs->bSectorNumberReg);
07188                 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  regs->bCylLowRegH);
07189                 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  regs->bCylLowReg);
07190                 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighRegH);
07191                 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
07192             }
07193             AtapiWritePort1(chan, IDX_IO1_o_Command,      regs->bCommandReg);
07194             
07195             if(use_dma) {
07196                 GetBaseStatus(chan, statusByte);
07197                 if(statusByte & IDE_STATUS_ERROR) {
07198                     goto passthrough_err;
07199                 }
07200                 AtapiDmaStart(HwDeviceExtension, (Srb->TargetId & 0x1), lChannel, Srb);
07201             }
07202 
07203             ScsiPortStallExecution(1);                  // wait for busy to be set
07204 
07205             if(regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) {
07206                 to_lim = Srb->TimeOutValue;
07207             } else {
07208                 if(Srb->TimeOutValue <= 2) {
07209                     to_lim = Srb->TimeOutValue*900;
07210                 } else {
07211                     to_lim = (Srb->TimeOutValue*999) - 500;
07212                 }
07213             }
07214             for(i=0; i<to_lim;i+=2) {      // 2 msec from WaitOnBaseBusy()
07215                 statusByte = WaitOnBaseBusy(chan);      // wait for busy to be clear, up to 2 msec
07216                 GetBaseStatus(chan, statusByte);
07217                 if(statusByte & IDE_STATUS_ERROR) {
07218                     break;
07219                 }
07220                 if(!(statusByte & IDE_STATUS_BUSY)) {
07221                     break;
07222                 }
07223             }
07224             if(i >= to_lim) {
07225                 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
07226                 //}
07227                 AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_NONE);
07228                 goto passthrough_err;
07229             }
07230 
07231             if(use_dma) {
07232                 AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel);
07233             }
07234             AtapiDmaDone(deviceExtension, (Srb->TargetId & 0x1), lChannel, NULL);
07235             GetBaseStatus(chan, statusByte);
07236 
07237             if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
07238                 AtapiSuckPort2(chan);
07239 passthrough_err:
07240                 if (Srb->SenseInfoBuffer) {
07241 
07242                     PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
07243 
07244                     senseBuffer->ErrorCode = 0x70;
07245                     senseBuffer->Valid     = 1;
07246                     senseBuffer->AdditionalSenseLength = 0xb;
07247                     senseBuffer->SenseKey =  SCSI_SENSE_ABORTED_COMMAND;
07248                     senseBuffer->AdditionalSenseCode = 0;
07249                     senseBuffer->AdditionalSenseCodeQualifier = 0;
07250 
07251                     Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
07252                     Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
07253                 }
07254                 status = SRB_STATUS_ERROR;
07255             } else {
07256 
07257                 if(!use_dma) {
07258                     if (statusByte & IDE_STATUS_DRQ) {
07259                         if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
07260                             ReadBuffer(chan,
07261                                        (PUSHORT) Srb->DataBuffer,
07262                                        Srb->DataTransferLength / 2,
07263                                        0);
07264                         } else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
07265                             WriteBuffer(chan,
07266                                         (PUSHORT) Srb->DataBuffer,
07267                                         Srb->DataTransferLength / 2,
07268                                         0);
07269                         }
07270                     }
07271                 }
07272                 status = SRB_STATUS_SUCCESS;
07273             }
07274 
07275             AtapiEnableInterrupts(deviceExtension, lChannel);
07276 
07277         } else { // read task register
07278 
07279             regs = (PIDEREGS_EX) Srb->DataBuffer;
07280 
07281             regs->bDriveHeadReg    = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
07282 
07283             if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {      // execute ATA command
07284                 regs->bFeaturesReg     = AtapiReadPort1(chan, IDX_IO1_i_Error);
07285                 regs->bSectorCountReg  = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
07286                 regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
07287                 regs->bCylLowReg       = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
07288                 regs->bCylHighReg      = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
07289             } else {
07290                 regs->bFeaturesReg     = AtapiReadPort1(chan, IDX_IO1_i_Error);
07291                 regs->bFeaturesRegH    = AtapiReadPort1(chan, IDX_IO1_i_Error);
07292                 regs->bSectorCountReg  = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
07293                 regs->bSectorCountRegH = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
07294                 regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
07295                 regs->bSectorNumberRegH= AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
07296                 regs->bCylLowReg       = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
07297                 regs->bCylLowRegH      = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
07298                 regs->bCylHighReg      = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
07299                 regs->bCylHighRegH     = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
07300             }
07301             regs->bCommandReg      = AtapiReadPort1(chan, IDX_IO1_i_Status);
07302             status = SRB_STATUS_SUCCESS;
07303         }
07304         break;
07305     }
07306 
07307     default:
07308 
07309         KdPrint2((PRINT_PREFIX 
07310                    "IdeSendCommand: Unsupported command %#x\n",
07311                    Srb->Cdb[0]));
07312 
07313         status = SRB_STATUS_INVALID_REQUEST;
07314 
07315     } // end switch
07316 
07317     if(status == SRB_STATUS_PENDING) {
07318         KdPrint2((PRINT_PREFIX "IdeSendCommand: SRB_STATUS_PENDING\n"));
07319         if(CmdAction & CMD_ACTION_EXEC) {
07320             KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
07321             AtaReq->ReqState = REQ_STATE_EXPECTING_INTR;
07322         }
07323     } else {
07324         KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
07325         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
07326     }
07327 
07328     return status;
07329 
07330 } // end IdeSendCommand()
07331 
07332 
07333 /*++
07334 
07335 Routine Description:
07336     Enables disables media status notification
07337 
07338 Arguments:
07339     HwDeviceExtension - ATAPI driver storage.
07340 
07341 --*/
07342 VOID
07343 NTAPI
07344 IdeMediaStatus(
07345     BOOLEAN EnableMSN,
07346     IN PVOID HwDeviceExtension,
07347     IN ULONG lChannel,
07348     IN ULONG DeviceNumber
07349     )
07350 {
07351     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
07352     PHW_CHANNEL          chan;
07353     UCHAR statusByte,errorByte;
07354 
07355     chan = &(deviceExtension->chan[lChannel]);
07356 
07357     if (EnableMSN == TRUE){
07358 
07359         // If supported enable Media Status Notification support
07360         if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE)) {
07361 
07362             // enable
07363             statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
07364                                 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
07365                                 0, ATA_C_F_ENAB_MEDIASTAT, ATA_WAIT_BASE_READY);
07366 
07367             if (statusByte & IDE_STATUS_ERROR) {
07368                 // Read the error register.
07369                 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
07370 
07371                 KdPrint2((PRINT_PREFIX 
07372                             "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
07373                              statusByte,
07374                              errorByte));
07375             } else {
07376                 chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_MEDIA_STATUS_ENABLED;
07377                 KdPrint2((PRINT_PREFIX "IdeMediaStatus: Media Status Notification Supported\n"));
07378                 chan->ReturningMediaStatus = 0;
07379 
07380             }
07381 
07382         }
07383     } else { // end if EnableMSN == TRUE
07384 
07385         // disable if previously enabled
07386         if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)) {
07387 
07388             statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
07389                                 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
07390                                 0, ATA_C_F_DIS_MEDIASTAT, ATA_WAIT_BASE_READY);
07391             chan->lun[DeviceNumber]->DeviceFlags &= ~DFLAGS_MEDIA_STATUS_ENABLED;
07392         }
07393 
07394 
07395     }
07396 
07397 
07398 } // end IdeMediaStatus()
07399 
07400 
07401 /*++
07402 
07403 Routine Description:
07404 
07405     Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
07406     command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
07407 Arguments:
07408 
07409     HwDeviceExtension - ATAPI driver storage.
07410     Srb - System request block.
07411 
07412 Return Value:
07413 
07414     SRB status (ALWAYS SUCCESS).
07415 
07416 --*/
07417 ULONG
07418 NTAPI
07419 IdeBuildSenseBuffer(
07420     IN PVOID HwDeviceExtension,
07421     IN PSCSI_REQUEST_BLOCK Srb
07422     )
07423 {
07424     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
07425 //    ULONG status;
07426     PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->DataBuffer;
07427     UCHAR ReturningMediaStatus = deviceExtension->chan[GET_CHANNEL(Srb)].ReturningMediaStatus;
07428 
07429     if (senseBuffer){
07430 
07431         if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE) {
07432 
07433             senseBuffer->ErrorCode = 0x70;
07434             senseBuffer->Valid     = 1;
07435             senseBuffer->AdditionalSenseLength = 0xb;
07436             senseBuffer->SenseKey =  SCSI_SENSE_UNIT_ATTENTION;
07437             senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
07438             senseBuffer->AdditionalSenseCodeQualifier = 0;
07439         } else if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE_REQ) {
07440 
07441             senseBuffer->ErrorCode = 0x70;
07442             senseBuffer->Valid     = 1;
07443             senseBuffer->AdditionalSenseLength = 0xb;
07444             senseBuffer->SenseKey =  SCSI_SENSE_UNIT_ATTENTION;
07445             senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
07446             senseBuffer->AdditionalSenseCodeQualifier = 0;
07447         } else if(ReturningMediaStatus & IDE_ERROR_END_OF_MEDIA) {
07448 
07449             senseBuffer->ErrorCode = 0x70;
07450             senseBuffer->Valid     = 1;
07451             senseBuffer->AdditionalSenseLength = 0xb;
07452             senseBuffer->SenseKey =  SCSI_SENSE_NOT_READY;
07453             senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
07454             senseBuffer->AdditionalSenseCodeQualifier = 0;
07455         } else if(ReturningMediaStatus & IDE_ERROR_DATA_ERROR) {
07456 
07457             senseBuffer->ErrorCode = 0x70;
07458             senseBuffer->Valid     = 1;
07459             senseBuffer->AdditionalSenseLength = 0xb;
07460             senseBuffer->SenseKey =  SCSI_SENSE_DATA_PROTECT;
07461             senseBuffer->AdditionalSenseCode = 0;
07462             senseBuffer->AdditionalSenseCodeQualifier = 0;
07463         }
07464         return SRB_STATUS_SUCCESS;
07465     }
07466     return SRB_STATUS_ERROR;
07467 
07468 }// End of IdeBuildSenseBuffer
07469 
07470 VOID
07471 NTAPI
07472 UniataUserDeviceReset(
07473     PHW_DEVICE_EXTENSION deviceExtension,
07474     PHW_LU_EXTENSION LunExt,
07475     ULONG PathId
07476     )
07477 {
07478     ULONG i;
07479     AtapiDisableInterrupts(deviceExtension, PathId);
07480     if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
07481         KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n"));
07482         AtapiSoftReset(&(deviceExtension->chan[PathId]), LunExt->Lun);
07483     } else {
07484         KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
07485         AtapiResetController__(deviceExtension, PathId, RESET_COMPLETE_NONE);
07486         for(i=0; i<deviceExtension->NumberLuns; i++) {
07487             deviceExtension->chan[PathId].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
07488         }
07489     }
07490     LunExt->DeviceFlags |= DFLAGS_REINIT_DMA;  // force PIO/DMA reinit
07491     AtapiEnableInterrupts(deviceExtension, PathId);
07492     return;
07493 } // end UniataUserDeviceReset()
07494 
07495 BOOLEAN
07496 NTAPI
07497 UniataNeedQueueing(
07498     PHW_DEVICE_EXTENSION deviceExtension,
07499     PHW_CHANNEL          chan,
07500     BOOLEAN              TopLevel
07501     )
07502 {
07503     BOOLEAN PostReq = FALSE;
07504     if(TopLevel) {
07505         KdPrint3((PRINT_PREFIX "UniataNeedQueueing: TopLevel, qd=%x\n", chan->queue_depth));
07506         if(chan->queue_depth > 0) {
07507 #if 0
07508             if(atapiDev &&
07509                ((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY)/* ||
07510                 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
07511                 KdPrint2((PRINT_PREFIX "spec: SCSIOP_TEST_UNIT_READY\n"));
07512                 //PostReq = FALSE;
07513                 status = SRB_STATUS_BUSY;
07514                 goto skip_exec;
07515             } else {
07516                 PostReq = TRUE;
07517             }
07518 #else
07519             PostReq = TRUE;
07520 #endif
07521         } else
07522         if(deviceExtension->simplexOnly && deviceExtension->queue_depth > 0) {
07523             PostReq = TRUE;
07524         }
07525     } else {
07526         KdPrint3((PRINT_PREFIX "UniataNeedQueueing: qd=%x\n", chan->queue_depth));
07527     }
07528     return PostReq;
07529 } // end UniataNeedQueueing()
07530 
07531 /*++
07532 
07533 Routine Description:
07534 
07535     This routine is called from the SCSI port driver synchronized
07536     with the kernel to start an IO request.
07537 
07538 Arguments:
07539 
07540     HwDeviceExtension - HBA miniport driver's adapter data storage
07541     Srb - IO request packet
07542 
07543 Return Value:
07544 
07545     TRUE
07546 
07547 --*/
07548 BOOLEAN
07549 NTAPI
07550 AtapiStartIo(
07551     IN PVOID HwDeviceExtension,
07552     IN PSCSI_REQUEST_BLOCK Srb
07553     )
07554 {
07555     return AtapiStartIo__(HwDeviceExtension, Srb, TRUE);
07556 } // end AtapiStartIo()
07557 
07558 BOOLEAN
07559 NTAPI
07560 AtapiStartIo__(
07561     IN PVOID HwDeviceExtension,
07562     IN PSCSI_REQUEST_BLOCK Srb,
07563     IN BOOLEAN TopLevel
07564     )
07565 {
07566     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
07567     UCHAR                lChannel;
07568     PHW_CHANNEL          chan;
07569     PHW_LU_EXTENSION     LunExt;
07570     ULONG status;
07571     //ULONG ldev;
07572     ULONG DeviceNumber;
07573     UCHAR PathId;
07574     UCHAR TargetId;
07575     UCHAR Lun;
07576     PATA_REQ AtaReq;
07577     PSCSI_REQUEST_BLOCK tmpSrb;
07578     BOOLEAN PostReq = FALSE;
07579     BOOLEAN atapiDev;
07580     BOOLEAN commPort = FALSE;
07581 
07582     // deviceExtension->Isr2DevObj must always be NULL for non-PCI
07583     if(deviceExtension->Isr2DevObj && !BMList[deviceExtension->DevIndex].Isr2Enable) {
07584         KdPrint2((PRINT_PREFIX "Isr2Enable -> 1\n"));
07585         BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
07586     }
07587 //    deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
07588 
07589 /*                KeBugCheckEx(0xc000000e,
07590                              (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
07591                              Srb->Function, 
07592                              TopLevel, 0x80000001);
07593 */
07594     if(TopLevel && Srb && Srb->SrbExtension) {
07595         KdPrint2((PRINT_PREFIX "TopLevel\n"));
07596         RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
07597     }
07598 
07599     do {
07600 
07601         lChannel = GET_CHANNEL(Srb);
07602         //ldev = GET_LDEV(Srb);
07603         chan = NULL;
07604         LunExt = NULL;
07605         DeviceNumber = GET_CDEV(Srb);
07606 
07607         //ASSERT(deviceExtension);
07608         //ASSERT(chan);
07609 
07610         KdPrint2((PRINT_PREFIX 
07611                    "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
07612                    Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId));
07613         KdPrint2((PRINT_PREFIX "   VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
07614 
07615         if(lChannel == deviceExtension->NumberChannels &&
07616            !Srb->Lun && !Srb->TargetId &&
07617            ((Srb->Function == SRB_FUNCTION_IO_CONTROL) ||
07618             (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Cdb[0] == SCSIOP_INQUIRY))
07619            ) {
07620             KdPrint2((PRINT_PREFIX 
07621                        "AtapiStartIo: Communication port\n"));
07622             if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
07623 
07624                 PINQUIRYDATA    inquiryData  = (PINQUIRYDATA)(Srb->DataBuffer);
07625 
07626                 KdPrint2((PRINT_PREFIX 
07627                            "  INQUIRY\n"));
07628                 // Zero INQUIRY data structure.
07629                 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
07630 
07631                 inquiryData->DeviceType = COMMUNICATION_DEVICE;
07632 
07633                 // Fill in vendor identification fields.
07634                 RtlCopyMemory(&inquiryData->VendorId, &uniata_comm_name, 28);
07635 
07636                 status = SRB_STATUS_SUCCESS;
07637                 goto complete_req;
07638             }
07639             commPort = TRUE;
07640             /* Pass IOCTL request down */
07641         } else
07642         if(lChannel >= deviceExtension->NumberChannels ||
07643            Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
07644            Srb->Lun) {
07645 
07646            if(lChannel >= deviceExtension->NumberChannels) {
07647                chan = NULL;
07648            }
07649 
07650 reject_srb:
07651             //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
07652                 KdPrint3((PRINT_PREFIX 
07653                            "AtapiStartIo: SRB rejected\n"));
07654                 // Indicate no device found at this address.
07655                 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
07656                 status = SRB_STATUS_SELECTION_TIMEOUT;
07657                 goto complete_req;
07658             //}
07659         }
07660 
07661         if(!commPort) {
07662             chan = &(deviceExtension->chan[lChannel]);
07663             LunExt = chan->lun[DeviceNumber];
07664             if(!LunExt) {
07665                 goto reject_srb;
07666             }
07667             atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
07668         } else {
07669             atapiDev = FALSE;
07670         }
07671 
07672 #ifdef _DEBUG
07673         if(!commPort && !LunExt) {
07674 #if 0
07675             PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
07676                 deviceExtension,
07677                 chan, DeviceNumber,
07678                 deviceExtension->NumberChannels);
07679             PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
07680                 lChannel, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]);
07681             PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
07682                        Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId);
07683 #endif //0
07684 /*
07685             int i;
07686             for(i=0; i<1000; i++) {
07687                 AtapiStallExecution(3*1000);
07688             }
07689 */
07690             goto reject_srb;
07691         }
07692 #endif //_DEBUG
07693 
07694         // Determine which function.
07695         switch (Srb->Function) {
07696 
07697         case SRB_FUNCTION_EXECUTE_SCSI:
07698 
07699             if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
07700                 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
07701                     // let passthrough go
07702                 } else
07703                 if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
07704                     // let INQUIRY go
07705                 } else {
07706 
07707                 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
07708                     KdPrint2((PRINT_PREFIX 
07709                                "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
07710                     // Indicate no device found at this address.
07711                     KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
07712                     status = SRB_STATUS_SELECTION_TIMEOUT;
07713                     break;
07714                 //}
07715                 }
07716             }
07717 /*
07718             __try {
07719                 if(Srb->DataTransferLength) {
07720                     UCHAR a;
07721                     a = ((PUCHAR)(Srb->DataBuffer))[0];
07722                     g_foo += a;
07723                 }
07724             } __except(EXCEPTION_EXECUTE_HANDLER) {
07725                 KdPrint3((PRINT_PREFIX 
07726                            "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
07727                 // Indicate no device found at this address.
07728                 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
07729                 status = SRB_STATUS_ERROR;
07730                 KdPrint2((PRINT_PREFIX "  *** Exception...\n"));
07731                 ASSERT(FALSE);
07732                 break;
07733             }
07734 */
07735             PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
07736 
07737             if(PostReq) {
07738 
07739                 KdPrint3((PRINT_PREFIX "Non-empty queue\n"));
07740                 if (atapiDev &&
07741                     (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
07742                     KdPrint3((PRINT_PREFIX "Try ATAPI prepare\n"));
07743 
07744                     status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
07745                 } else {
07746                     KdPrint2((PRINT_PREFIX "Try IDE prepare\n"));
07747                     status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
07748                 }
07749                 /*KeBugCheckEx(0xc000000e,
07750                              (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
07751                              Srb->Function, 
07752                              status, 0x80000001);*/
07753                 if(status == SRB_STATUS_BUSY)
07754                     status = SRB_STATUS_PENDING;
07755                 // Insert requests AFTER they have been initialized on
07756                 // CMD_ACTION_PREPARE stage
07757                 // we should not check TopLevel here (it is always TRUE)
07758                 //ASSERT(chan->lun[GET_CDEV(Srb)]);
07759                 UniataQueueRequest(chan, Srb);
07760 
07761                 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
07762 
07763             } else {
07764                 // Send command to device.
07765                 KdPrint2((PRINT_PREFIX "Send to device\n"));
07766                 if(TopLevel) {
07767                     KdPrint2((PRINT_PREFIX "TopLevel (2), srb %#x\n", Srb));
07768                     AtaReq = (PATA_REQ)(Srb->SrbExtension);
07769                     KdPrint2((PRINT_PREFIX "TopLevel (3), AtaReq %#x\n", AtaReq));
07770                     //ASSERT(!AtaReq->Flags);
07771                     //ASSERT(chan->lun[GET_CDEV(Srb)]);
07772                     UniataQueueRequest(chan, Srb);
07773 //                    AtaReq = (PATA_REQ)(Srb->SrbExtension);
07774                     //ASSERT(!AtaReq->Flags);
07775                     AtaReq->ReqState = REQ_STATE_QUEUED;
07776                     //ASSERT(!AtaReq->Flags);
07777                 }
07778 
07779 #ifndef NAVO_TEST
07780                 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
07781                     if(!LunExt) {
07782                         goto reject_srb;
07783                     }
07784                     if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
07785                         if(UniataAnybodyHome(deviceExtension, chan->lChannel, DeviceNumber)) {
07786                             if(!CheckDevice(HwDeviceExtension, chan->lChannel, DeviceNumber, TRUE)) {
07787                                 goto reject_srb;
07788                             }
07789                         }
07790                         if(!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
07791                             goto reject_srb;
07792                         }
07793                     } else
07794                     if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
07795                         // allow
07796                     } else {
07797                         goto reject_srb;
07798                     }
07799                 }
07800 #endif //NAVO_TEST
07801 
07802                 if(atapiDev &&
07803                    (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
07804                     KdPrint3((PRINT_PREFIX "Try ATAPI send\n"));
07805                     status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
07806                 } else {
07807                     KdPrint2((PRINT_PREFIX "Try IDE send\n"));
07808 /*                    {
07809                         ULONG __ebp__ = 0;
07810                         ULONG __esp__ = 0;
07811 
07812                         KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
07813                         __asm {
07814                             mov eax,ebp
07815                             mov __ebp__, eax
07816                             mov eax,esp
07817                             mov __esp__, eax
07818                         }
07819                         KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
07820                     }*/
07821                     status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
07822                 }
07823 /*                KeBugCheckEx(0xc000000e,
07824                              (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
07825                              Srb->Function, 
07826                              status, 0x80000002);*/
07827 
07828             }
07829 //skip_exec:
07830             TopLevel = FALSE;
07831 
07832             break;
07833 
07834         case SRB_FUNCTION_ABORT_COMMAND:
07835 
07836             tmpSrb = ScsiPortGetSrb(HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun,
07837                                Srb->QueueTag);
07838             // Verify that SRB to abort is still outstanding.
07839             if((tmpSrb != Srb->NextSrb) ||
07840                !chan->queue_depth) {
07841 
07842                 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB to abort already completed\n"));
07843 
07844                 // Complete abort SRB.
07845                 status = SRB_STATUS_ABORT_FAILED;
07846                 break;
07847             }
07848 
07849             AtaReq = (PATA_REQ)(tmpSrb->SrbExtension);
07850             if(AtaReq->ReqState > REQ_STATE_READY_TO_TRANSFER) {
07851                 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_CURRENT)) {
07852                       KdPrint2((PRINT_PREFIX "AtapiStartIo: Abort command failed\n"));
07853                     // Log reset failure.
07854                     KdPrint3((PRINT_PREFIX 
07855                                 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
07856                                       HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
07857                                 ));
07858                     ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
07859                     status = SRB_STATUS_ERROR;
07860 
07861                 } else {
07862                     status = SRB_STATUS_SUCCESS;
07863                 }
07864             } else {
07865                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove aborted srb %#x\n", tmpSrb));
07866                 if (tmpSrb->SenseInfoBuffer &&
07867                     tmpSrb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
07868 
07869                     PSENSE_DATA  senseBuffer = (PSENSE_DATA)tmpSrb->SenseInfoBuffer;
07870 
07871                     senseBuffer->ErrorCode = 0;
07872                     senseBuffer->Valid     = 1;
07873                     senseBuffer->AdditionalSenseLength = 0xb;
07874                     senseBuffer->SenseKey =  SCSI_SENSE_ABORTED_COMMAND;
07875                     senseBuffer->AdditionalSenseCode = 0;
07876                     senseBuffer->AdditionalSenseCodeQualifier = 0;
07877 
07878                     tmpSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
07879                 }
07880                 AtapiDmaDBSync(chan, tmpSrb);
07881                 UniataRemoveRequest(chan, tmpSrb);
07882                 // Indicate command complete.
07883                 ScsiPortNotification(RequestComplete,
07884                                      deviceExtension,
07885                                      tmpSrb);
07886                 status = SRB_STATUS_SUCCESS;
07887             }
07888             break;
07889 
07890             // Abort function indicates that a request timed out.
07891             // Call reset routine. Card will only be reset if
07892             // status indicates something is wrong.
07893             // Fall through to reset code.
07894 
07895         case SRB_FUNCTION_RESET_DEVICE:
07896         case SRB_FUNCTION_RESET_LOGICAL_UNIT:
07897 
07898             // Reset single device.
07899             // For now we support only Lun=0
07900 
07901             // Note: reset is immediate command, it cannot be queued since it is usually used to
07902             // revert not- responding device to operational state
07903             KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device request received\n"));
07904             UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
07905             status = SRB_STATUS_SUCCESS;
07906             break;
07907 
07908         case SRB_FUNCTION_RESET_BUS:
07909 do_bus_reset:
07910             // Reset Atapi and SCSI bus.
07911 
07912             // Note: reset is immediate command, it cannot be queued since it is usually used to
07913             // revert not- responding device to operational state
07914             KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus request received\n"));
07915             if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_ALL)) {
07916                   KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus failed\n"));
07917                 // Log reset failure.
07918                 KdPrint3((PRINT_PREFIX 
07919                             "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
07920                                   HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
07921                             ));
07922                 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
07923                 status = SRB_STATUS_ERROR;
07924 
07925             } else {
07926                 status = SRB_STATUS_SUCCESS;
07927             }
07928 
07929             break;
07930 
07931         case SRB_FUNCTION_SHUTDOWN:
07932 
07933             KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown\n"));
07934             if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
07935                 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - no such device\n"));
07936             } else
07937             if(atapiDev) {
07938                 // FLUSH ATAPI device - do nothing
07939                 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - ATAPI device\n"));
07940             } else {
07941                 // FLUSH IDE/ATA device
07942                 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - IDE device\n"));
07943                 AtapiDisableInterrupts(deviceExtension, lChannel);
07944                 status = AtaCommand(deviceExtension, DeviceNumber, GET_CHANNEL(Srb),
07945                            IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_IDLE);
07946                 // If supported & allowed, reset write cacheing
07947                 if(LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) {
07948 
07949                     // Disable write cache
07950                     status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
07951                                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
07952                                         0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
07953                     // Check for errors.
07954                     if (status & IDE_STATUS_ERROR) {
07955                         KdPrint2((PRINT_PREFIX 
07956                                     "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
07957                                     DeviceNumber));
07958                     }
07959                     LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
07960 
07961                     // Re-enable write cache
07962                     status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
07963                                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
07964                                         0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
07965                     // Check for errors.
07966                     if (status & IDE_STATUS_ERROR) {
07967                         KdPrint2((PRINT_PREFIX 
07968                                     "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
07969                                     DeviceNumber));
07970                         LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
07971                     } else {
07972                         LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
07973                     }
07974                 }
07975 
07976                 AtapiEnableInterrupts(deviceExtension, lChannel);
07977             }
07978             status = SRB_STATUS_SUCCESS;
07979 
07980             break;
07981 
07982         case SRB_FUNCTION_FLUSH:
07983 
07984             KdPrint2((PRINT_PREFIX "AtapiStartIo: Flush (do nothing)\n"));
07985             status = SRB_STATUS_SUCCESS;
07986             break;
07987 
07988     /*    case SRB_FUNCTION_SHUTDOWN:
07989         case SRB_FUNCTION_FLUSH:
07990 
07991             // Flush device's cache.
07992             KdPrint2((PRINT_PREFIX "AtapiStartIo: Device flush received\n"));
07993 
07994             if (chan->CurrentSrb) {
07995 
07996                 KdPrint2((PRINT_PREFIX "AtapiStartIo (SRB_FUNCTION_FLUSH): Already have a request!\n"));
07997                 Srb->SrbStatus = SRB_STATUS_BUSY;
07998                 ScsiPortNotification(RequestComplete,
07999                                      deviceExtension,
08000                                      Srb);
08001                 return FALSE;
08002             }
08003 
08004             if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
08005                 status = SRB_STATUS_SUCCESS;
08006             } else {
08007                 status = AtaCommand(deviceExtension, GET_CDEV(Srb), GET_CHANNEL(Srb),
08008                            IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR);
08009                 if (status & IDE_STATUS_DRQ) {
08010                     status = SRB_STATUS_SUCCESS;
08011                 } else {
08012                     status = SRB_STATUS_SELECTION_TIMEOUT;
08013                 }
08014             }
08015             break;*/
08016 
08017         case SRB_FUNCTION_IO_CONTROL: {
08018 
08019             ULONG len;
08020 
08021             KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
08022 
08023             len = Srb->DataTransferLength;
08024 
08025             if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
08026 
08027                 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
08028                 case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
08029 
08030                     PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
08031                     UCHAR deviceNumber;
08032 
08033                     KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
08034 
08035                     // Version and revision per SMART 1.03
08036 
08037                     versionParameters->bVersion = 1;
08038                     versionParameters->bRevision = 1;
08039                     versionParameters->bReserved = 0;
08040 
08041                     // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
08042                     versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
08043 
08044                     // This is done because of how the IOCTL_SCSI_MINIPORT
08045                     // determines 'targetid's'. Disk.sys places the real target id value
08046                     // in the DeviceMap field. Once we do some parameter checking, the value passed
08047                     // back to the application will be determined.
08048 
08049                     deviceNumber = versionParameters->bIDEDeviceMap;
08050 
08051                     if(commPort) {
08052                         KdPrint2((PRINT_PREFIX 
08053                                    "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
08054                         // Indicate no device found at this address.
08055                         KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
08056                         status = SRB_STATUS_SELECTION_TIMEOUT;
08057                         break;
08058                     }
08059 
08060                     if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) ||
08061                         atapiDev) {
08062 
08063                         status = SRB_STATUS_SELECTION_TIMEOUT;
08064                         break;
08065                     }
08066 
08067                     // NOTE: This will only set the bit
08068                     // corresponding to this drive's target id.
08069                     // The bit mask is as follows:
08070                     //
08071                     //     -Sec Pri
08072                     //     S M S M
08073                     //     3 2 1 0
08074 
08075                     if (deviceExtension->NumberChannels == 1) {
08076                         if (chan->PrimaryAddress) {
08077                             deviceNumber = 1 << DeviceNumber;
08078                         } else {
08079                             deviceNumber = 4 << DeviceNumber;
08080                         }
08081                     } else {
08082                         deviceNumber = (1 << DeviceNumber) << lChannel;
08083                     }
08084 
08085                     versionParameters->bIDEDeviceMap = deviceNumber;
08086 
08087                     status = SRB_STATUS_SUCCESS;
08088                     break;
08089                 }
08090 
08091                 case IOCTL_SCSI_MINIPORT_IDENTIFY: {
08092 
08093                     PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
08094                     SENDCMDINPARAMS   cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
08095                     UCHAR             targetId;
08096 
08097                     KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
08098                     // Extract the target.
08099                     targetId = cmdInParameters.bDriveNumber;
08100                     KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
08101                     if((targetId >= deviceExtension->NumberChannels*2) ||
08102                        !(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
08103                         KdPrint2((PRINT_PREFIX "Error: xxx_ID_CMD for non-existant device\n"));
08104                         status = SRB_STATUS_SELECTION_TIMEOUT;
08105                         break;
08106                     }
08107 
08108                     switch(cmdInParameters.irDriveRegs.bCommandReg) {
08109                     case ID_CMD:
08110                         if((deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
08111                             KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n"));
08112                             status = SRB_STATUS_INVALID_REQUEST;
08113                             break;
08114                         }
08115                         /* FALL THROUGH */
08116                     case ATAPI_ID_CMD:
08117 
08118                         if(!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
08119                            (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) {
08120                             KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n"));
08121                             status = SRB_STATUS_INVALID_REQUEST;
08122                             break;
08123                         }
08124 
08125                         len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE);
08126                         // Zero the output buffer
08127                         RtlZeroMemory(cmdOutParameters, len);
08128 /*                        for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
08129                             ((PUCHAR)cmdOutParameters)[i] = 0;
08130                         }*/
08131 
08132                         // Build status block.
08133                         cmdOutParameters->cBufferSize = min(IDENTIFY_BUFFER_SIZE, len - sizeof(SENDCMDOUTPARAMS) + 1);
08134                         cmdOutParameters->DriverStatus.bDriverError = 0;
08135                         cmdOutParameters->DriverStatus.bIDEError = 0;
08136 
08137                         // Extract the identify data from the device extension.
08138                         ScsiPortMoveMemory (cmdOutParameters->bBuffer, &deviceExtension->lun[targetId].IdentifyData,
08139                             cmdOutParameters->cBufferSize);
08140 
08141                         KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
08142 
08143                         status = SRB_STATUS_SUCCESS;
08144 
08145                         break;
08146                     default:
08147                         KdPrint2((PRINT_PREFIX "AtapiStartIo: not supported ID code %x\n",
08148                             cmdInParameters.irDriveRegs.bCommandReg));
08149                         status = SRB_STATUS_INVALID_REQUEST;
08150                         break;
08151                     }
08152                     break;
08153                 }
08154 
08155                 case  IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
08156                 case  IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
08157                 case  IOCTL_SCSI_MINIPORT_ENABLE_SMART:
08158                 case  IOCTL_SCSI_MINIPORT_DISABLE_SMART:
08159                 case  IOCTL_SCSI_MINIPORT_RETURN_STATUS:
08160                 case  IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
08161                 case  IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
08162                 case  IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
08163 
08164                     if(commPort) {
08165                         KdPrint2((PRINT_PREFIX 
08166                                    "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
08167                         // Indicate no device found at this address.
08168                         KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
08169                         status = SRB_STATUS_SELECTION_TIMEOUT;
08170                         break;
08171                     }
08172 
08173                     PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
08174 
08175                     if(PostReq || TopLevel) {
08176                         UniataQueueRequest(chan, Srb);
08177                         AtaReq = (PATA_REQ)(Srb->SrbExtension);
08178                         AtaReq->ReqState = REQ_STATE_QUEUED;
08179                     }
08180 
08181                     if(PostReq) {
08182 
08183                         KdPrint2((PRINT_PREFIX "Non-empty queue (SMART)\n"));
08184                         status = SRB_STATUS_PENDING;
08185 
08186                         KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
08187                     } else {
08188 
08189                         status = IdeSendSmartCommand(HwDeviceExtension,Srb);
08190                     }
08191                     break;
08192 
08193                 default :
08194                     KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
08195                                 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
08196                     status = SRB_STATUS_INVALID_REQUEST;
08197                     break;
08198 
08199                 }
08200             } else
08201             if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) {
08202 
08203                 PUNIATA_CTL AtaCtl = (PUNIATA_CTL)(Srb->DataBuffer);
08204                 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
08205                 ULONG DeviceNumber = AtaCtl->addr.TargetId;
08206                 BOOLEAN bad_ldev;
08207                 ULONG i;
08208                 //chan = &(deviceExtension->chan[lChannel]);
08209 
08210                 if(AtaCtl->addr.Lun ||
08211                    AtaCtl->addr.TargetId >= deviceExtension->NumberLuns || 
08212                    AtaCtl->addr.PathId >= deviceExtension->NumberChannels) {
08213 
08214                     chan = NULL;
08215                     bad_ldev = TRUE;
08216                     LunExt = NULL;
08217 
08218                 } else {
08219                     bad_ldev = FALSE;
08220                     lChannel = AtaCtl->addr.PathId;
08221                     chan = &(deviceExtension->chan[lChannel]);
08222                     LunExt = chan->lun[DeviceNumber];
08223                 }
08224 
08225                 KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl->hdr.ControlCode, DeviceNumber));
08226 
08227                 /* check for valid LUN */
08228                 switch (AtaCtl->hdr.ControlCode) {
08229                 case  IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
08230                 case  IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE:
08231                     // this would be BUS reset
08232                     if(bad_ldev &&
08233                        (AtaCtl->addr.PathId >= deviceExtension->NumberChannels ||
08234                         AtaCtl->addr.TargetId != 0xff ||
08235                         AtaCtl->addr.Lun != 0
08236                         )) {
08237                         if(AtaCtl->hdr.ControlCode == IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES &&
08238                            DeviceNumber < deviceExtension->NumberLuns) { // AtaCtl->addr.TargetId != 0xff
08239                             lChannel = AtaCtl->addr.PathId;
08240                             chan = &(deviceExtension->chan[lChannel]);
08241                             LunExt = chan->lun[DeviceNumber];
08242                             // OK
08243                         } else {
08244                             goto handle_bad_ldev;
08245                         }
08246                     } else {
08247                         lChannel = AtaCtl->addr.PathId;
08248                         chan = &(deviceExtension->chan[lChannel]);
08249                     }
08250                     break;
08251                 case  IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE:
08252                 case  IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
08253                 case  IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE:
08254                 case  IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
08255 //                case  IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
08256                     if(bad_ldev) {
08257 handle_bad_ldev:
08258                         KdPrint2((PRINT_PREFIX 
08259                                    "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
08260                         // Indicate no device found at this address.
08261                         goto reject_srb;
08262                     }
08263                 }
08264 
08265                 /* check if queueing is necessary */
08266                 switch (AtaCtl->hdr.ControlCode) {
08267                 case  IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
08268                     if(!LunExt->nBadBlocks) {
08269                         break;
08270                     }
08271                     goto uata_ctl_queue;
08272                 case  IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
08273                     if(!AtaCtl->SetMode.ApplyImmediately) {
08274                         break;
08275                     }
08276                     goto uata_ctl_queue;
08277                 case  IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
08278                 //case  IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
08279 uata_ctl_queue:
08280                     KdPrint2((PRINT_PREFIX "put to queue (UNIATA)\n"));
08281                     PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
08282 
08283                     if(PostReq || TopLevel) {
08284                         UniataQueueRequest(chan, Srb);
08285                         AtaReq = (PATA_REQ)(Srb->SrbExtension);
08286                         AtaReq->ReqState = REQ_STATE_QUEUED;
08287                     }
08288                     if(PostReq) {
08289                         KdPrint2((PRINT_PREFIX "Non-empty queue (UNIATA)\n"));
08290                         status = SRB_STATUS_PENDING;
08291 
08292                         KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
08293                         goto complete_req;
08294                     } 
08295                 } // end switch (AtaCtl->hdr.ControlCode)
08296 
08297                 /* process request */
08298                 switch (AtaCtl->hdr.ControlCode) {
08299                 case  IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
08300 
08301                     KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n"));
08302 
08303                     if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
08304                         KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
08305                         if(AtaCtl->addr.TargetId != 0xff) {
08306                             LunExt->DeviceFlags &= ~DFLAGS_HIDDEN;
08307                         } else {
08308                         }
08309                     }
08310 
08311                     for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
08312                         AtapiStallExecution(1000 * 1000);
08313                     }
08314 
08315                     FindDevices(HwDeviceExtension,
08316                                 ((AtaCtl->addr.TargetId == 0xff) && (AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE))
08317                                      ? UNIATA_FIND_DEV_UNHIDE : 0,
08318                                 AtaCtl->addr.PathId);
08319                     status = SRB_STATUS_SUCCESS;
08320 
08321                     break;
08322 
08323                 case  IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: {
08324 
08325                     KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId));
08326 
08327                     LunExt->DeviceFlags = 0;
08328                     if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
08329                         KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n"));
08330                         LunExt->DeviceFlags |= DFLAGS_HIDDEN;
08331                     }
08332 
08333                     for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
08334                         AtapiStallExecution(1000 * 1000);
08335                     }
08336 
08337                     status = SRB_STATUS_SUCCESS;
08338                     break;
08339                 }
08340                 case  IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: {
08341 
08342                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n"));
08343 
08344                     if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
08345                         LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
08346                     }
08347                     if(AtaCtl->SetMode.MaxMode != IOMODE_NOT_SPECIFIED) {
08348                         LunExt->LimitedTransferMode = (UCHAR)(AtaCtl->SetMode.MaxMode);
08349                         if(LunExt->LimitedTransferMode > 
08350                            LunExt->OrigTransferMode) {
08351                             // check for incorrect value
08352                             LunExt->LimitedTransferMode =
08353                                 LunExt->OrigTransferMode;
08354                         }
08355                     }
08356                     LunExt->TransferMode = min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode);
08357 
08358                     LunExt->DeviceFlags |= DFLAGS_REINIT_DMA;  // force PIO/DMA reinit
08359                     if(AtaCtl->SetMode.ApplyImmediately) {
08360                         AtapiDmaInit__(deviceExtension, LunExt);
08361                     }
08362 /*                    LunExt->TransferMode =
08363                     LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
08364                     status = SRB_STATUS_SUCCESS;
08365                     break;
08366                 }
08367                 case  IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE: {
08368 
08369                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get transfer mode\n"));
08370 
08371                     AtaCtl->GetMode.OrigMode    = LunExt->OrigTransferMode;
08372                     AtaCtl->GetMode.MaxMode     = LunExt->LimitedTransferMode;
08373                     AtaCtl->GetMode.CurrentMode = LunExt->TransferMode;
08374 
08375                     status = SRB_STATUS_SUCCESS;
08376                     break;
08377                 }
08378                 case  IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION: {
08379 
08380                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n"));
08381 
08382                     AtaCtl->Version.Length      = sizeof(GETDRVVERSION);
08383                     AtaCtl->Version.VersionMj   = UNIATA_VER_MJ;
08384                     AtaCtl->Version.VersionMn   = UNIATA_VER_MN;
08385                     AtaCtl->Version.SubVerMj    = UNIATA_VER_SUB_MJ;
08386                     AtaCtl->Version.SubVerMn    = UNIATA_VER_SUB_MN;
08387 
08388                     status = SRB_STATUS_SUCCESS;
08389                     break;
08390                 }
08391                 case  IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO: {
08392 
08393                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n"));
08394 
08395                     AtaCtl->AdapterInfo.HeaderLength = FIELD_OFFSET(ADAPTERINFO, Chan);
08396 
08397                     if(len < AtaCtl->AdapterInfo.HeaderLength + sizeof(AtaCtl->AdapterInfo.Chan)) {
08398                         KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", len,
08399                             AtaCtl->AdapterInfo.HeaderLength + sizeof(AtaCtl->AdapterInfo.Chan)));
08400                         status = SRB_STATUS_DATA_OVERRUN;
08401                         break;
08402                     }
08403 
08404                     AtaCtl->AdapterInfo.DevID      = deviceExtension->DevID;
08405                     AtaCtl->AdapterInfo.RevID      = deviceExtension->RevID;
08406                     AtaCtl->AdapterInfo.slotNumber = deviceExtension->slotNumber;
08407                     AtaCtl->AdapterInfo.SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
08408                     AtaCtl->AdapterInfo.DevIndex   = deviceExtension->DevIndex;
08409                     AtaCtl->AdapterInfo.Channel    = deviceExtension->Channel;
08410                     AtaCtl->AdapterInfo.HbaCtrlFlags = deviceExtension->HbaCtrlFlags;
08411                     AtaCtl->AdapterInfo.simplexOnly= deviceExtension->simplexOnly;
08412                     AtaCtl->AdapterInfo.MemIo      = FALSE;/*deviceExtension->MemIo;*/
08413                     AtaCtl->AdapterInfo.UnknownDev = deviceExtension->UnknownDev;
08414                     AtaCtl->AdapterInfo.MasterDev  = deviceExtension->MasterDev;
08415                     AtaCtl->AdapterInfo.MaxTransferMode = deviceExtension->MaxTransferMode;
08416                     AtaCtl->AdapterInfo.HwFlags    = deviceExtension->HwFlags;
08417                     AtaCtl->AdapterInfo.OrigAdapterInterfaceType = deviceExtension->OrigAdapterInterfaceType;
08418                     AtaCtl->AdapterInfo.BusInterruptLevel = deviceExtension->BusInterruptLevel;
08419                     AtaCtl->AdapterInfo.InterruptMode = deviceExtension->InterruptMode;
08420                     AtaCtl->AdapterInfo.BusInterruptVector = deviceExtension->BusInterruptVector;
08421                     AtaCtl->AdapterInfo.NumberChannels = deviceExtension->NumberChannels;
08422                     AtaCtl->AdapterInfo.NumberLuns = (UCHAR)deviceExtension->NumberLuns;
08423                     AtaCtl->AdapterInfo.AdapterInterfaceType = deviceExtension->AdapterInterfaceType;
08424                     if(deviceExtension->FullDevName) {
08425                         strncpy(AtaCtl->AdapterInfo.DeviceName, deviceExtension->FullDevName, 64);
08426                     }
08427                     AtaCtl->AdapterInfo.ChanInfoValid = FALSE;
08428                     AtaCtl->AdapterInfo.LunInfoValid = FALSE;
08429 
08430                     RtlZeroMemory(&AtaCtl->AdapterInfo.Chan, sizeof(AtaCtl->AdapterInfo.Chan));
08431 
08432                     status = SRB_STATUS_SUCCESS;
08433                     break;
08434                 }
08435                 case  IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: {
08436                     
08437                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Forget BB list\n"));
08438 
08439                     ForgetBadBlocks(LunExt);
08440 
08441                     status = SRB_STATUS_SUCCESS;
08442                     break;
08443                 }
08444                 case  IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: {
08445 
08446                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device\n"));
08447 
08448                     if(bad_ldev) {
08449                         goto do_bus_reset;
08450                     } else {
08451                         UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId);
08452                     }
08453 
08454                     status = SRB_STATUS_SUCCESS;
08455                     break;
08456                 }
08457                 default :
08458                     KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
08459                                 AtaCtl->hdr.ControlCode ));
08460                     status = SRB_STATUS_INVALID_REQUEST;
08461                     break;
08462                 }
08463 
08464             } else {
08465                 KdPrint2((PRINT_PREFIX "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
08466                             ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,
08467                             "SCSIDISK", "-UNIATA-"));
08468 
08469                 status = SRB_STATUS_INVALID_REQUEST;
08470                 break;
08471             }
08472 
08473             break;
08474         } // end SRB_FUNCTION_IO_CONTROL
08475         default:
08476 
08477             KdPrint2((PRINT_PREFIX "AtapiStartIo: Unknown IOCTL\n"));
08478             // Indicate unsupported command.
08479             status = SRB_STATUS_INVALID_REQUEST;
08480 
08481 //            break;
08482 
08483         } // end switch
08484 
08485 complete_req:
08486 
08487         PathId   = Srb->PathId;
08488         TargetId = Srb->TargetId;
08489         Lun      = Srb->Lun;
08490 
08491         if (status != SRB_STATUS_PENDING) {
08492 
08493             KdPrint2((PRINT_PREFIX 
08494                        "AtapiStartIo: Srb %#x complete with status %#x\n",
08495                        Srb,
08496                        status));
08497 
08498             // Set status in SRB.
08499             Srb->SrbStatus = (UCHAR)status;
08500 
08501             AtapiDmaDBSync(chan, Srb);
08502             UniataRemoveRequest(chan, Srb);
08503             // Indicate command complete.
08504             ScsiPortNotification(RequestComplete,
08505                                  deviceExtension,
08506                                  Srb);
08507 
08508             // Remove current Srb & get next one
08509             if((Srb = UniataGetCurRequest(chan))) {
08510                 AtaReq = (PATA_REQ)(Srb->SrbExtension);
08511                 if(AtaReq->ReqState > REQ_STATE_QUEUED) {
08512                     // current request is under precessing, thus
08513                     // we should do nothing here
08514                     Srb = NULL;
08515                 }
08516             }
08517             if(!chan) {
08518                 //ASSERT(TopLevel);
08519             }
08520         }
08521         KdPrint2((PRINT_PREFIX "AtapiStartIo: next Srb %x\n", Srb));
08522 
08523     } while (Srb && (status != SRB_STATUS_PENDING));
08524 
08525     KdPrint2((PRINT_PREFIX "AtapiStartIo: query PORT for next request\n"));
08526     // Indicate ready for next request.
08527     ScsiPortNotification(NextRequest,
08528                          deviceExtension,
08529                          NULL);
08530 
08531     ScsiPortNotification(NextLuRequest,
08532                          deviceExtension, 
08533                          PathId,
08534                          TargetId,
08535                          Lun);
08536 
08537     return TRUE;
08538 
08539 } // end AtapiStartIo__()
08540 
08541 
08542 void
08543 NTAPI
08544 UniataInitAtaCommands()
08545 {
08546     int i;
08547     UCHAR command;
08548     UCHAR flags;
08549 
08550     KdPrint2((PRINT_PREFIX "UniataInitAtaCommands:\n"));
08551 
08552     for(i=0; i<256; i++) {
08553 
08554         flags = 0;
08555         command = i;
08556 
08557         KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
08558 
08559         switch(command) {
08560         case IDE_COMMAND_READ_DMA48:
08561         case IDE_COMMAND_READ_DMA_Q48:
08562         case IDE_COMMAND_READ_STREAM_DMA48:
08563         case IDE_COMMAND_READ_STREAM48:
08564         case IDE_COMMAND_WRITE_DMA48:
08565         case IDE_COMMAND_WRITE_DMA_Q48:
08566         case IDE_COMMAND_READ_DMA_Q:
08567         case IDE_COMMAND_READ_DMA:
08568         case IDE_COMMAND_WRITE_DMA:
08569         case IDE_COMMAND_WRITE_DMA_Q:
08570         case IDE_COMMAND_WRITE_STREAM_DMA48:
08571         case IDE_COMMAND_WRITE_STREAM48:
08572         case IDE_COMMAND_WRITE_FUA_DMA48:
08573         case IDE_COMMAND_WRITE_FUA_DMA_Q48:
08574         case IDE_COMMAND_READ_LOG_DMA48:
08575         case IDE_COMMAND_WRITE_LOG_DMA48:
08576         case IDE_COMMAND_TRUSTED_RCV_DMA:
08577         case IDE_COMMAND_TRUSTED_SEND_DMA:
08578             KdPrint2((PRINT_PREFIX "DMA "));
08579             flags |= ATA_CMD_FLAG_DMA;
08580         }
08581 
08582         switch(command) {
08583         case IDE_COMMAND_READ48:
08584         case IDE_COMMAND_READ_DMA48:
08585         case IDE_COMMAND_READ_DMA_Q48:
08586         case IDE_COMMAND_READ_MUL48:
08587         case IDE_COMMAND_READ_STREAM_DMA48:
08588         case IDE_COMMAND_READ_STREAM48:
08589         case IDE_COMMAND_WRITE48:
08590         case IDE_COMMAND_WRITE_DMA48:
08591         case IDE_COMMAND_WRITE_DMA_Q48:
08592         case IDE_COMMAND_WRITE_MUL48:
08593         case IDE_COMMAND_WRITE_STREAM_DMA48:
08594         case IDE_COMMAND_WRITE_STREAM48:
08595         case IDE_COMMAND_WRITE_FUA_DMA48:
08596         case IDE_COMMAND_WRITE_FUA_DMA_Q48:
08597         case IDE_COMMAND_WRITE_MUL_FUA48:
08598         case IDE_COMMAND_FLUSH_CACHE48:
08599         case IDE_COMMAND_VERIFY48:
08600 
08601             KdPrint2((PRINT_PREFIX "48 "));
08602             flags |= ATA_CMD_FLAG_48;
08603             /* FALL THROUGH */
08604 
08605         case IDE_COMMAND_READ:
08606         case IDE_COMMAND_READ_MULTIPLE:
08607         case IDE_COMMAND_READ_DMA:
08608         case IDE_COMMAND_READ_DMA_Q:
08609         case IDE_COMMAND_WRITE:
08610         case IDE_COMMAND_WRITE_MULTIPLE:
08611         case IDE_COMMAND_WRITE_DMA:
08612         case IDE_COMMAND_WRITE_DMA_Q:
08613         case IDE_COMMAND_FLUSH_CACHE:
08614         case IDE_COMMAND_VERIFY:
08615 
08616             KdPrint2((PRINT_PREFIX "LBA "));
08617             flags |= ATA_CMD_FLAG_LBAIOsupp;
08618         }
08619 
08620         flags |= ATA_CMD_FLAG_48supp;
08621 
08622         switch (command) {
08623         case IDE_COMMAND_READ:
08624             command = IDE_COMMAND_READ48; break;
08625         case IDE_COMMAND_READ_MULTIPLE:
08626             command = IDE_COMMAND_READ_MUL48; break;
08627         case IDE_COMMAND_READ_DMA:
08628             command = IDE_COMMAND_READ_DMA48; break;
08629         case IDE_COMMAND_READ_DMA_Q:
08630             command = IDE_COMMAND_READ_DMA_Q48; break;
08631         case IDE_COMMAND_WRITE:
08632             command = IDE_COMMAND_WRITE48; break;
08633         case IDE_COMMAND_WRITE_MULTIPLE:
08634             command = IDE_COMMAND_WRITE_MUL48; break;
08635         case IDE_COMMAND_WRITE_DMA:
08636             command = IDE_COMMAND_WRITE_DMA48; break;
08637         case IDE_COMMAND_WRITE_DMA_Q:
08638             command = IDE_COMMAND_WRITE_DMA_Q48; break;
08639         case IDE_COMMAND_FLUSH_CACHE:
08640             command = IDE_COMMAND_FLUSH_CACHE48; break;
08641     //    case IDE_COMMAND_READ_NATIVE_SIZE:
08642     //            command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
08643         case IDE_COMMAND_SET_NATIVE_SIZE:
08644             command = IDE_COMMAND_SET_NATIVE_SIZE48; break;
08645         case IDE_COMMAND_VERIFY:
08646             command = IDE_COMMAND_VERIFY48; break;
08647         default:
08648             KdPrint2((PRINT_PREFIX "!28->48 "));
08649             flags &= ~ATA_CMD_FLAG_48supp;
08650         }
08651 
08652         KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
08653         AtaCommands48[i]   = command;
08654         AtaCommandFlags[i] = flags;
08655     }
08656 } // end UniataInitAtaCommands()
08657 
08658 /*++
08659 
08660 Routine Description:
08661 
08662     Installable driver initialization entry point for system.
08663 
08664 Arguments:
08665 
08666     Driver Object
08667 
08668 Return Value:
08669 
08670     Status from ScsiPortInitialize()
08671 
08672 --*/
08673 extern "C"
08674 ULONG
08675 NTAPI
08676 DriverEntry(
08677     IN PVOID DriverObject,
08678     IN PVOID Argument2
08679     )
08680 {
08681     HW_INITIALIZATION_DATA_COMMON hwInitializationData;
08682     ULONG                  adapterCount;
08683     ULONG                  i, c, alt;
08684     ULONG                  statusToReturn, newStatus;
08685     PUNICODE_STRING        RegistryPath = (PUNICODE_STRING)Argument2;
08686     BOOLEAN                ReEnter = FALSE;
08687     WCHAR                  a;
08688 #ifndef USE_REACTOS_DDK
08689     NTSTATUS               status;
08690 #endif
08691 
08692     PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation();
08693     BOOLEAN PrimaryClaimed   = FALSE;
08694     BOOLEAN SecondaryClaimed = FALSE;
08695 
08696     LARGE_INTEGER t0, t1;
08697 
08698     Connect_DbgPrint();
08699     KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string));
08700     a = (WCHAR)strlen(ver_string);
08701 
08702     g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0);
08703     if(g_opt_Verbose) {
08704         _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR "\n");
08705     }
08706 
08707     if(!SavedDriverObject) {
08708         SavedDriverObject = (PDRIVER_OBJECT)DriverObject;
08709 #ifdef USE_REACTOS_DDK
08710         KdPrint(("UniATA Init: OS should be ReactOS\n"));
08711         MajorVersion=0x04;
08712         MinorVersion=0x01;
08713         BuildNumber=1;
08714 #else
08715         // we are here for the 1st time
08716         // init CrossNT and get OS version
08717         if(!NT_SUCCESS(status = CrNtInit(SavedDriverObject, RegistryPath))) {
08718             KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status));
08719             //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
08720             return status;
08721         }
08722 #endif // USE_REACTOS_DDK
08723         KdPrint(("UniATA Init: OS ver %x.%x (%d)\n", MajorVersion, MinorVersion, BuildNumber));
08724 
08725         KeQuerySystemTime(&t0);
08726         do {
08727             KeQuerySystemTime(&t1);
08728         } while(t0.QuadPart == t1.QuadPart);
08729         t0=t1;
08730         g_Perf=0;
08731         do {
08732             KeQuerySystemTime(&t1);
08733             g_Perf++;
08734         } while(t0.QuadPart == t1.QuadPart);
08735         g_PerfDt = (ULONG)((t1.QuadPart - t0.QuadPart)/10);
08736         KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt, g_Perf ));
08737     } else {
08738         KdPrint(("UniATA Init: ReEnter\n"));
08739         ReEnter = TRUE;
08740     }
08741 
08742     // (re)read bad block list
08743     InitBadBlocks(NULL);
08744 
08745     if(!ReEnter) {
08746         // init ATA command translation table
08747         UniataInitAtaCommands();
08748         // get registry path to settings
08749         RtlCopyMemory(&SavedRegPath, RegistryPath, sizeof(UNICODE_STRING));
08750         SavedRegPath.Buffer = (PWCHAR)&SavedRegPathBuffer;
08751         SavedRegPath.Length = min(RegistryPath->Length, 255*sizeof(WCHAR));
08752         SavedRegPath.MaximumLength = 255*sizeof(WCHAR);
08753         RtlCopyMemory(SavedRegPath.Buffer, RegistryPath->Buffer, SavedRegPath.Length);
08754         SavedRegPath.Buffer[SavedRegPath.Length/sizeof(WCHAR)] = 0;
08755     }
08756 
08757     if(WinVer_Id() >= WinVer_2k) {
08758         if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"1", 0)) {
08759             KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
08760             WinVer_WDM_Model = TRUE;
08761         }
08762         if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"5", 0)) {
08763             KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
08764             WinVer_WDM_Model = TRUE;
08765         }
08766     }
08767 
08768     SkipRaids = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"SkipRaids", 1);
08769     ForceSimplex = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"ForceSimplex", 0);
08770 #ifdef _DEBUG
08771     g_LogToDisplay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"LogToDisplay", 0);
08772 #endif //_DEBUG
08773 
08774     statusToReturn = 0xffffffff;
08775 
08776     // Zero out structure.
08777     RtlZeroMemory(((PCHAR)&hwInitializationData), sizeof(hwInitializationData));
08778 
08779     // Set size of hwInitializationData.
08780     hwInitializationData.comm.HwInitializationDataSize =
08781       sizeof(hwInitializationData.comm) +
08782 //      sizeof(hwInitializationData.nt4) +
08783       ((WinVer_Id() <= WinVer_NT) ? 0 : sizeof(hwInitializationData.w2k));
08784     KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData.comm.HwInitializationDataSize));
08785 
08786     // Set entry points.
08787     hwInitializationData.comm.HwInitialize = (PHW_INITIALIZE)AtapiHwInitialize;
08788     hwInitializationData.comm.HwResetBus = (PHW_RESET_BUS)AtapiResetController;
08789     hwInitializationData.comm.HwStartIo = (PHW_STARTIO)AtapiStartIo;
08790     hwInitializationData.comm.HwInterrupt = (PHW_INTERRUPT)AtapiInterrupt;
08791 
08792     // Specify size of extensions.
08793     hwInitializationData.comm.DeviceExtensionSize     = sizeof(HW_DEVICE_EXTENSION);
08794     hwInitializationData.comm.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION);
08795     hwInitializationData.comm.SrbExtensionSize        = sizeof(ATA_REQ);
08796 
08797     // Indicate PIO device.
08798     hwInitializationData.comm.MapBuffers = TRUE;
08799     // Set PnP-specific API
08800     if(WinVer_Id() > WinVer_NT) {
08801         KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
08802         hwInitializationData.comm.NeedPhysicalAddresses = TRUE;
08803         KdPrint(("set AtapiAdapterControl() ptr\n"));
08804         hwInitializationData.w2k.HwAdapterControl = (PHW_ADAPTER_CONTROL)AtapiAdapterControl;
08805     }
08806 
08807     KdPrint2((PRINT_PREFIX "\n\nATAPI IDE enum supported BusMaster Devices\n"));
08808 
08809     if(!ReEnter) {
08810 
08811         g_opt_VirtualMachine = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualMachineType", g_opt_VirtualMachine);
08812         if(g_opt_VirtualMachine > VM_MAX_KNOWN) {
08813             g_opt_VirtualMachine = 0;
08814         }
08815         if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualBox", (g_opt_VirtualMachine == VM_VBOX))) {
08816             g_opt_VirtualMachine = VM_VBOX;
08817         }
08818         // Pre-scan PCI bus, also check if we are under VM
08819         UniataEnumBusMasterController(DriverObject, Argument2);
08820 
08821         switch(g_opt_VirtualMachine) {
08822         case VM_VBOX:
08823             // adjust options for VirtualBox
08824             g_opt_WaitBusyCount = 20000;
08825             g_opt_WaitBusyDelay = 150;
08826             g_opt_WaitDrqDelay  = 100;
08827             g_opt_AtapiSendDisableIntr = 0;
08828             g_opt_AtapiDmaRawRead = FALSE;
08829             break;
08830         }
08831 
08832         g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000
08833         g_opt_WaitBusyDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyDelay", g_opt_WaitBusyDelay); // 10 vs 150
08834         g_opt_WaitDrqDelay  = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay",  g_opt_WaitDrqDelay);  // 10 vs 100
08835         g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr",  g_opt_AtapiSendDisableIntr);  // 1 vs 0
08836         g_opt_AtapiDmaRawRead      = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead",       g_opt_AtapiDmaRawRead);       // 1 vs 0
08837 
08838     }
08839 
08840     // Look for legacy ISA-bridged PCI IDE controller (onboard)
08841     KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
08842     KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: BMListLen %d\n", BMListLen));
08843     for (i=0; i <BMListLen; i++) {
08844 
08845         if(!BMList[i].MasterDev) {
08846             KdPrint2((PRINT_PREFIX "!BMList[i].MasterDev\n"));
08847             break;
08848         }
08849         if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
08850             break;
08851         }
08852         if(ReEnter) {
08853             KdPrint2((PRINT_PREFIX "ReEnter, skip it\n"));
08854             if(BMList[i].ChanInitOk & 0x03) {
08855                 KdPrint2((PRINT_PREFIX "Already initialized, skip it\n"));
08856                 statusToReturn =
08857                 newStatus = STATUS_SUCCESS;
08858             }
08859             continue;
08860         }
08861         if(GlobalConfig->AtDiskPrimaryAddressClaimed)
08862             PrimaryClaimed = TRUE;
08863         if(GlobalConfig->AtDiskSecondaryAddressClaimed)
08864             SecondaryClaimed = TRUE;
08865 
08866         BMList[i].AltInitMasterDev = (UCHAR)0xff;
08867 
08868         if(g_opt_Verbose) {
08869             _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
08870         }
08871 
08872         for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) {
08873 
08874             for(c=0; c<2; c++) {
08875 
08876                 if(AtapiRegCheckDevValue(NULL, c, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
08877                     break;
08878                 }
08879                 if(c==0) {
08880                     if(PrimaryClaimed) {
08881                         KdPrint2((PRINT_PREFIX "Primary already claimed\n"));
08882                         continue;
08883                     }
08884                 } else
08885                 if(c==1) {
08886                     if(SecondaryClaimed) {
08887                         KdPrint2((PRINT_PREFIX "Secondary already claimed\n"));
08888                         continue;
08889                     }
08890                 }
08891 
08892                 if((WinVer_Id() < WinVer_2k)) {
08893                     // do not even try if already claimed
08894                     if(c==0) {
08895                         GlobalConfig->AtDiskPrimaryAddressClaimed = FALSE;
08896                     } else
08897                     if(c==1) {
08898                         GlobalConfig->AtDiskSecondaryAddressClaimed = FALSE;
08899                     }
08900                 }
08901                 if(!WinVer_WDM_Model) {
08902                     hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
08903                 } else {
08904                     // in WDM model things are different....
08905                     hwInitializationData.comm.HwFindAdapter = (c == 0) ?
08906                         UniataFindCompatBusMasterController1 : UniataFindCompatBusMasterController2;
08907                 }
08908                 hwInitializationData.comm.NumberOfAccessRanges = 6;
08909                 hwInitializationData.comm.AdapterInterfaceType = Isa;
08910 
08911                 if(!WinVer_WDM_Model) {
08912                     BMList[i].channel = (UCHAR)c;
08913                 }
08914 
08915                 KdPrint2((PRINT_PREFIX "Try init channel %d, method %d\n", c, alt));
08916                 newStatus = ScsiPortInitialize(DriverObject,
08917                                                Argument2,
08918                                                &hwInitializationData.comm,
08919                                                (PVOID)(i | (alt ? 0x80000000 : 0)));
08920                 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
08921                 if (newStatus < statusToReturn) {
08922                     statusToReturn = newStatus;
08923                 }
08924                 if (newStatus == STATUS_SUCCESS) {
08925                     BMList[i].ChanInitOk |= 0x01 << c;
08926 /*
08927                     if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
08928                         c = 1; // this will break our for()
08929                         BMList[i].ChanInitOk |= 0x01 << c;
08930                     }
08931 */
08932                 }
08933             }
08934             if(WinVer_Id() >= WinVer_2k) {
08935                 // the following doesn't work under higher OSes
08936                 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
08937                 continue;
08938             }
08939             if(BMList[i].ChanInitOk & 0x03) {
08940                 // under NT we receive status immediately, so
08941                 // we can omit alternative init method id STATUS_SUCCESS returned
08942                 KdPrint2((PRINT_PREFIX "Ok, no more retries required\n"));
08943                 break;
08944             }
08945             // if (WinVer_Id() == WinVer_NT) and some error occured
08946             // try alternative init method
08947         } // for(alt...)
08948 #if 0
08949         if(WinVer_WDM_Model) {
08950             hwInitializationData.comm.HwFindAdapter = UniataFindFakeBusMasterController;
08951             hwInitializationData.comm.NumberOfAccessRanges = 5;
08952             hwInitializationData.comm.AdapterInterfaceType = PCIBus;
08953 
08954             hwInitializationData.comm.VendorId             = BMList[i].VendorId;
08955             hwInitializationData.comm.VendorIdLength       = (USHORT) BMList[i].VendorIdLength;
08956             hwInitializationData.comm.DeviceId             = BMList[i].DeviceId;
08957             hwInitializationData.comm.DeviceIdLength       = (USHORT) BMList[i].DeviceIdLength;
08958 
08959             //BMList[i].channel = 0/*(UCHAR)c*/;
08960 
08961             KdPrint2((PRINT_PREFIX "Try init fake: %4.4s %4.4s \n",
08962                                    hwInitializationData.comm.VendorId,
08963                                    hwInitializationData.comm.DeviceId));
08964             newStatus = ScsiPortInitialize(DriverObject,
08965                                            Argument2,
08966                                            &hwInitializationData.comm,
08967                                            (PVOID)i);
08968             KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
08969         }
08970 #endif //0
08971         if(g_opt_Verbose) {
08972             if(BMList[i].ChanInitOk & 0x03) {
08973                 _PrintNtConsole("  OK\n");
08974             } else {
08975                 _PrintNtConsole("  failed\n");
08976             }
08977         }
08978 
08979     }
08980 
08981 /*    KeBugCheckEx(0xc000000e,
08982                  (i << 16) | BMList[0].ChanInitOk,
08983                  c, 
08984                  newStatus, statusToReturn);*/
08985 
08986     // Look for PCI IDE controller
08987     KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for PCI IDE controller\n"));
08988     KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: i %d, BMListLen %d\n", i, BMListLen));
08989     for (; i <BMListLen; i++) {
08990 
08991         if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", 0)) {
08992             break;
08993         }
08994 /*        if(BMList[i].MasterDev)
08995             continue;*/
08996         if(g_opt_Verbose) {
08997             _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
08998                 BMList[i].VendorId, BMList[i].DeviceId,
08999                 BMList[i].busNumber,
09000                 BMList[i].slotNumber % PCI_MAX_FUNCTION,
09001                 (BMList[i].slotNumber / PCI_MAX_FUNCTION) % PCI_MAX_DEVICES);
09002         }
09003 
09004         hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
09005         hwInitializationData.comm.NumberOfAccessRanges = 6;
09006         hwInitializationData.comm.AdapterInterfaceType = PCIBus;
09007 
09008         hwInitializationData.comm.VendorId             = BMList[i].VendorId;
09009         hwInitializationData.comm.VendorIdLength       = (USHORT) BMList[i].VendorIdLength;
09010         hwInitializationData.comm.DeviceId             = BMList[i].DeviceId;
09011         hwInitializationData.comm.DeviceIdLength       = (USHORT) BMList[i].DeviceIdLength;
09012 
09013         BMList[i].channel = 0/*(UCHAR)c*/;
09014 
09015         KdPrint2((PRINT_PREFIX "Try init %4.4s %4.4s \n",
09016                                hwInitializationData.comm.VendorId,
09017                                hwInitializationData.comm.DeviceId));
09018         newStatus = ScsiPortInitialize(DriverObject,
09019                                        Argument2,
09020                                        &hwInitializationData.comm,
09021                                        (PVOID)i);
09022         KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
09023         if(newStatus == (ULONG)STATUS_DEVICE_DOES_NOT_EXIST && BMList[i].NeedAltInit) {
09024             // Note: this is actually a BUG in scsiport.sys
09025             // It stops scanning PCI bus when reaches empty PCI Function inside Slot
09026             // However, this PCI Slot may have higher non-empty Functions
09027             // UniATA will perform all staff instead of ScsiPort under NT,
09028             // but for ReactOS it is better to patch ScsiPort.
09029             KdPrint2((PRINT_PREFIX "STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
09030             hwInitializationData.comm.AdapterInterfaceType = Isa;
09031             newStatus = ScsiPortInitialize(DriverObject,
09032                                            Argument2,
09033                                            &hwInitializationData.comm,
09034                                            (PVOID)(i | 0x80000000));
09035             KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x (2)\n", newStatus));
09036         }
09037         if (newStatus < statusToReturn)
09038             statusToReturn = newStatus;
09039 
09040         if(g_opt_Verbose) {
09041             if(newStatus == STATUS_SUCCESS) {
09042                 _PrintNtConsole("  OK\n");
09043             } else {
09044                 _PrintNtConsole("  failed\n");
09045             }
09046         }
09047 
09048     }
09049 
09050 /*    KeBugCheckEx(0xc000000e,
09051                  i,
09052                  c, 
09053                  newStatus, statusToReturn);*/
09054 
09055     // --------------
09056 
09057     hwInitializationData.comm.VendorId             = 0;
09058     hwInitializationData.comm.VendorIdLength       = 0;
09059     hwInitializationData.comm.DeviceId             = 0;
09060     hwInitializationData.comm.DeviceIdLength       = 0;
09061 
09062     // The adapter count is used by the find adapter routine to track how
09063     // which adapter addresses have been tested.
09064 
09065     // Indicate 2 access ranges and reset FindAdapter.
09066     hwInitializationData.comm.NumberOfAccessRanges = 2;
09067     hwInitializationData.comm.HwFindAdapter = AtapiFindController;
09068 
09069     if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsa", 0)) {
09070         // Indicate ISA bustype.
09071         hwInitializationData.comm.AdapterInterfaceType = Isa;
09072         adapterCount = 0;
09073 
09074         // Call initialization for ISA bustype.
09075         KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for ISA Controllers\n"));
09076         newStatus =  ScsiPortInitialize(DriverObject,
09077                                         Argument2,
09078                                         &hwInitializationData.comm,
09079                                         &adapterCount);
09080         KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
09081         if (newStatus < statusToReturn)
09082             statusToReturn = newStatus;
09083     }
09084     if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreMca", 0)) {
09085         // Set up for MCA
09086         KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for MCA Controllers\n"));
09087         hwInitializationData.comm.AdapterInterfaceType = MicroChannel;
09088         adapterCount = 0;
09089 
09090         newStatus =  ScsiPortInitialize(DriverObject,
09091                                         Argument2,
09092                                         &hwInitializationData.comm,
09093                                         &adapterCount);
09094         KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
09095         if (newStatus < statusToReturn)
09096             statusToReturn = newStatus;
09097     }
09098     InDriverEntry = FALSE;
09099 
09100     KdPrint2((PRINT_PREFIX "\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn));
09101 
09102     return statusToReturn;
09103 
09104 } // end DriverEntry()
09105 
09106 
09107 PSCSI_REQUEST_BLOCK
09108 NTAPI
09109 BuildMechanismStatusSrb(
09110     IN PVOID HwDeviceExtension,
09111     IN PSCSI_REQUEST_BLOCK Srb
09112     )
09113 {
09114     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
09115     PSCSI_REQUEST_BLOCK srb;
09116     PCDB cdb;
09117     PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
09118 
09119     srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
09120 
09121     RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
09122 
09123     srb->PathId     = (UCHAR)(Srb->PathId);
09124     srb->TargetId   = (UCHAR)(Srb->TargetId);
09125     srb->Function   = SRB_FUNCTION_EXECUTE_SCSI;
09126     srb->Length     = sizeof(SCSI_REQUEST_BLOCK);
09127 
09128     // Set flags to disable synchronous negociation.
09129     srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
09130 
09131     // Set timeout to 4 seconds.
09132     srb->TimeOutValue = 4;
09133 
09134     srb->CdbLength          = 6;
09135     srb->DataBuffer         = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusData);
09136     srb->DataTransferLength = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
09137     srb->SrbExtension       = AtaReq;
09138 
09139     // Set CDB operation code.
09140     cdb = (PCDB)srb->Cdb;
09141     cdb->MECH_STATUS.OperationCode       = SCSIOP_MECHANISM_STATUS;
09142     cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
09143 
09144     return srb;
09145 } // end BuildMechanismStatusSrb()
09146 
09147 #endif //UNIATA_CORE
09148 
09149 PSCSI_REQUEST_BLOCK
09150 NTAPI
09151 BuildRequestSenseSrb (
09152     IN PVOID HwDeviceExtension,
09153     IN PSCSI_REQUEST_BLOCK Srb
09154     )
09155 {
09156     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
09157     PSCSI_REQUEST_BLOCK srb;
09158     PCDB cdb;
09159     PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
09160 
09161     srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
09162 
09163     RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
09164 
09165     srb->PathId     = (UCHAR)(Srb->PathId);
09166     srb->TargetId   = (UCHAR)(Srb->TargetId);
09167     srb->Function   = SRB_FUNCTION_EXECUTE_SCSI;
09168     srb->Length     = sizeof(SCSI_REQUEST_BLOCK);
09169 
09170     // Set flags to disable synchronous negociation.
09171     srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
09172 
09173     // Set timeout to 2 seconds.
09174     srb->TimeOutValue = 4;
09175 
09176     srb->CdbLength          = 6;
09177     srb->DataBuffer         = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusSense);
09178     srb->DataTransferLength = sizeof(SENSE_DATA);
09179     srb->SrbExtension       = AtaReq;
09180 
09181     // Set CDB operation code.
09182     cdb = (PCDB)srb->Cdb;
09183     cdb->CDB6INQUIRY.OperationCode    = SCSIOP_REQUEST_SENSE;
09184     cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
09185 
09186     return srb;
09187 } // end BuildRequestSenseSrb()
09188 
09189 #ifndef UNIATA_CORE
09190 
09191 ULONG
09192 NTAPI
09193 AtapiRegCheckDevLunValue(
09194     IN PVOID HwDeviceExtension,
09195     IN PCWCH NamePrefix,
09196     IN ULONG chan,
09197     IN ULONG dev,
09198     IN PCWSTR Name,
09199     IN ULONG Default
09200     )
09201 {
09202     WCHAR namex[160];
09203     ULONG val = Default;
09204 
09205     val = AtapiRegCheckParameterValue(
09206         HwDeviceExtension, NamePrefix, Name, val);
09207 
09208     if(chan != CHAN_NOT_SPECIFIED) {
09209         swprintf(namex, L"%s\\Chan_%1.1d", NamePrefix, chan);
09210         val = AtapiRegCheckParameterValue(
09211             HwDeviceExtension, namex, Name, val);
09212         if(dev != DEVNUM_NOT_SPECIFIED) {
09213             swprintf(namex, L"%s\\Chan_%1.1d\\%s", NamePrefix, chan, (dev & 0x01) ? L"Lun_1" : L"Lun_0");
09214             val = AtapiRegCheckParameterValue(
09215                 HwDeviceExtension, namex, Name, val);
09216         }
09217     }
09218     return val;
09219 } // end AtapiRegCheckDevLunValue()
09220 
09221 ULONG
09222 NTAPI
09223 EncodeVendorStr(
09224    OUT PWCHAR Buffer,
09225     IN PUCHAR Str,
09226     IN ULONG  Length
09227     )
09228 {
09229     ULONG i,j;
09230     WCHAR a;
09231 
09232     for(i=0, j=0; i<Length; i++, j++) {
09233         // fix byte-order
09234         a = Str[i ^ 0x01];
09235         if(!a) {
09236             Buffer[j] = 0;
09237             return j;
09238         } else
09239         if(a == ' ') {
09240             Buffer[j] = '_';
09241         } else
09242         if((a == '_') ||
09243            (a == '#') ||
09244            (a == '\\') ||
09245            (a == '\"') ||
09246            (a == '\'') ||
09247            (a <  ' ') ||
09248            (a >= 127)) {
09249             Buffer[j] = '#';
09250             j++;
09251             swprintf(Buffer+j, L"%2.2x", a);
09252             j++;
09253         } else {
09254             Buffer[j] = a;
09255         }
09256     }
09257     Buffer[j] = 0;
09258     return j;
09259 } // end EncodeVendorStr()
09260 
09261 ULONG
09262 NTAPI
09263 AtapiRegCheckDevValue(
09264     IN PVOID HwDeviceExtension,
09265     IN ULONG chan,
09266     IN ULONG dev,
09267     IN PCWSTR Name,
09268     IN ULONG Default
09269     )
09270 {
09271     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
09272 //    WCHAR name0[11];
09273 //    WCHAR name1[11+4+5];
09274 //    WCHAR name2[11+4+4+10];
09275 //    WCHAR name3[11+4+4+5+20];
09276 //    WCHAR name3[11+4+4+5+20+1];
09277     WCHAR namex[160];
09278 
09279     WCHAR namev[16];
09280     WCHAR named[16];
09281     WCHAR names[20];
09282 
09283     IN ULONG VendorID;
09284     IN ULONG DeviceID;
09285     IN ULONG SlotNumber;
09286 
09287     ULONG val = Default;
09288 
09289     KdPrint(( " Parameter %ws\n", Name));
09290 
09291     if(deviceExtension) {
09292         VendorID   =  deviceExtension->DevID        & 0xffff;
09293         DeviceID   = (deviceExtension->DevID >> 16) & 0xffff;
09294         SlotNumber = deviceExtension->slotNumber;
09295     } else {
09296         VendorID   = 0xffff;
09297         DeviceID   = 0xffff;
09298         SlotNumber = 0xffffffff;
09299     }
09300 
09301     val = AtapiRegCheckDevLunValue(
09302         HwDeviceExtension, L"Parameters", chan, dev, Name, val);
09303 
09304     if(deviceExtension) {
09305         if(deviceExtension->AdapterInterfaceType == PCIBus) {
09306             // PCI
09307             swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex);
09308             swprintf(namex, L"Parameters%s", namev);
09309             val = AtapiRegCheckDevLunValue(
09310                 HwDeviceExtension, namex, chan, dev, Name, val);
09311 
09312 
09313             swprintf(namev, L"\\Ven_%4.4x", VendorID);
09314             swprintf(named, L"\\Dev_%4.4x", DeviceID);
09315             swprintf(names, L"\\Slot_%8.8x", SlotNumber);
09316 
09317             swprintf(namex, L"Parameters%s", namev);
09318             val = AtapiRegCheckDevLunValue(
09319                 HwDeviceExtension, namex, chan, dev, Name, val);
09320 
09321             swprintf(namex, L"Parameters%s%s", namev, named);
09322             val = AtapiRegCheckDevLunValue(
09323                 HwDeviceExtension, namex, chan, dev, Name, val);
09324 
09325             swprintf(namex, L"Parameters%s%s%s", namev, named, names);
09326             val = AtapiRegCheckDevLunValue(
09327                 HwDeviceExtension, namex, chan, dev, Name, val);
09328         } else
09329         if(deviceExtension->AdapterInterfaceType == Isa) {
09330             // Isa
09331             swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen);
09332             swprintf(namex, L"Parameters%s", namev);
09333             val = AtapiRegCheckDevLunValue(
09334                 HwDeviceExtension, namex, chan, dev, Name, val);
09335 
09336             swprintf(namev, L"\\ISA_%d", deviceExtension->DevIndex);
09337             swprintf(namex, L"Parameters%s", namev);
09338             val = AtapiRegCheckDevLunValue(
09339                 HwDeviceExtension, namex, chan, dev, Name, val);
09340 
09341         } else
09342         if(deviceExtension->AdapterInterfaceType == MicroChannel) {
09343             // MicroChannel
09344             swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen+IsaCount);
09345             swprintf(namex, L"Parameters%s", namev);
09346             val = AtapiRegCheckDevLunValue(
09347                 HwDeviceExtension, namex, chan, dev, Name, val);
09348 
09349             swprintf(namev, L"\\MCA_%d", deviceExtension->DevIndex);
09350             swprintf(namex, L"Parameters%s", namev);
09351             val = AtapiRegCheckDevLunValue(
09352                 HwDeviceExtension, namex, chan, dev, Name, val);
09353 
09354         }
09355     }
09356 
09357     KdPrint(( " Parameter %ws = %#x\n", Name, val));
09358     return val;
09359 
09360 } // end AtapiRegCheckDevValue()
09361 
09362 /*
09363     The user must specify that Xxx is to run on the platform
09364     by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
09365     Services\UniATA\Xxx:REG_DWORD:Zzz.
09366 
09367     The user can override the global setting to enable or disable Xxx on a
09368     specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
09369     CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
09370 
09371     If this registry value does not exist or contains the value zero then
09372     the timer to check for media change does not run.
09373 
09374     Arguments:
09375 
09376     RegistryPath - pointer to the unicode string inside
09377                    ...\CurrentControlSet\Services\UniATA
09378     DeviceNumber - The number of the HBA device object
09379 
09380     Returns:    Registry Key value
09381  */
09382 ULONG
09383 NTAPI
09384 AtapiRegCheckParameterValue(
09385     IN PVOID HwDeviceExtension,
09386     IN PCWSTR PathSuffix,
09387     IN PCWSTR Name,
09388     IN ULONG Default
09389     )
09390 {
09391 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched 
09392 
09393 //    PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
09394     NTSTATUS          status;
09395     LONG              zero = Default;
09396 
09397     RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
09398 
09399 //    LONG              tmp = 0;
09400     LONG              doRun = Default;
09401 
09402     PUNICODE_STRING   RegistryPath = &SavedRegPath;
09403 
09404     UNICODE_STRING    paramPath;
09405 
09406     // <SavedRegPath><PathSuffix> -> <Name>
09407 //    KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
09408 //    KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
09409 
09410     paramPath.Length = 0;
09411     paramPath.MaximumLength = RegistryPath->Length +
09412         (wcslen(PathSuffix)+2)*sizeof(WCHAR);
09413     paramPath.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, paramPath.MaximumLength);
09414     if(!paramPath.Buffer) {
09415         KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
09416         return Default;
09417     }
09418 
09419     RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength);
09420     RtlAppendUnicodeToString(&paramPath, RegistryPath->Buffer);
09421     RtlAppendUnicodeToString(&paramPath, L"\\");
09422     RtlAppendUnicodeToString(&paramPath, REGRTL_STR_PTYPE PathSuffix);
09423 
09424     // Check for the Xxx value.
09425     RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
09426 
09427     parameters[0].Flags         = RTL_QUERY_REGISTRY_DIRECT;
09428     parameters[0].Name          = REGRTL_STR_PTYPE Name;
09429     parameters[0].EntryContext  = &doRun;
09430     parameters[0].DefaultType   = REG_DWORD;
09431     parameters[0].DefaultData   = &zero;
09432     parameters[0].DefaultLength = sizeof(ULONG);
09433 
09434     status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
09435                                     paramPath.Buffer, parameters, NULL, NULL);
09436     KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
09437 
09438     ExFreePool(paramPath.Buffer);
09439 
09440     if(!NT_SUCCESS(status)) {
09441         doRun = Default;
09442     }
09443 
09444     return doRun;
09445 
09446 #undef ITEMS_TO_QUERY
09447 
09448 } // end AtapiRegCheckParameterValue()
09449 
09450 
09451 SCSI_ADAPTER_CONTROL_STATUS
09452 NTAPI
09453 AtapiAdapterControl(
09454     IN PVOID HwDeviceExtension,
09455     IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
09456     IN PVOID Parameters
09457     )
09458 {
09459     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
09460     PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList;
09461     ULONG                numberChannels  = deviceExtension->NumberChannels;
09462     ULONG c;
09463     NTSTATUS status;
09464 
09465     KdPrint(( "AtapiAdapterControl: %#x\n", ControlType));
09466 
09467     switch(ControlType) {
09468         case ScsiQuerySupportedControlTypes: {
09469             BOOLEAN supportedTypes[ScsiAdapterControlMax] = {
09470                 TRUE,       // ScsiQuerySupportedControlTypes
09471                 TRUE,       // ScsiStopAdapter
09472                 TRUE,       // ScsiRestartAdapter
09473                 FALSE,      // ScsiSetBootConfig
09474                 FALSE       // ScsiSetRunningConfig
09475             };
09476 
09477             ULONG lim = ScsiAdapterControlMax;
09478             ULONG i;
09479 
09480             pControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST) Parameters;
09481 
09482             if(pControlTypeList->MaxControlType < lim) {
09483                 lim = pControlTypeList->MaxControlType;
09484             }
09485 
09486             for(i = 0; i < lim; i++) {
09487                 pControlTypeList->SupportedTypeList[i] = supportedTypes[i];
09488             }
09489 
09490             break;
09491 
09492         }
09493         case ScsiStopAdapter: {
09494 
09495             KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
09496             // Shut down all interrupts on the adapter.  They'll get re-enabled
09497             // by the initialization routines.
09498             for (c = 0; c < numberChannels; c++) {
09499                 AtapiResetController(deviceExtension, c);
09500                 AtapiDisableInterrupts(deviceExtension, c);
09501             }
09502             if(deviceExtension->AdapterInterfaceType == PCIBus) {
09503                 // we must never get here for non-PCI
09504                 status = UniataDisconnectIntr2(HwDeviceExtension);
09505                 BMList[deviceExtension->DevIndex].Isr2Enable = FALSE;
09506             }
09507             break;
09508         }
09509         case ScsiRestartAdapter: {
09510 
09511             KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
09512             // Enable all the interrupts on the adapter while port driver call
09513             // for power up an HBA that was shut down for power management
09514 
09515             AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
09516             status = UniataConnectIntr2(HwDeviceExtension);
09517             for (c = 0; c < numberChannels; c++) {
09518                 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c);
09519                 FindDevices(HwDeviceExtension, 0, c);
09520                 AtapiEnableInterrupts(deviceExtension, c);
09521                 AtapiHwInitialize__(deviceExtension, c);
09522             }
09523             if(deviceExtension->Isr2DevObj) {
09524                 // we must never get here for non-PCI
09525                 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
09526             }
09527 
09528             break;
09529         }
09530 
09531         default: {
09532             KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
09533             return ScsiAdapterControlUnsuccessful;
09534         }
09535     }
09536 
09537     return ScsiAdapterControlSuccess;
09538 } // end AtapiAdapterControl()
09539 
09540 #endif //UNIATA_CORE
09541 
09542 extern "C"
09543 NTHALAPI
09544 VOID
09545 NTAPI
09546 HalDisplayString (
09547     PUCHAR String
09548     );
09549 
09550 extern "C"
09551 VOID
09552 _cdecl
09553 _PrintNtConsole(
09554     PCCH DebugMessage,
09555     ...
09556     )
09557 {
09558     int len;
09559     UCHAR dbg_print_tmp_buff[512];
09560 //    UNICODE_STRING msgBuff;
09561     va_list ap;
09562     va_start(ap, DebugMessage);
09563 
09564     len = _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], 511, DebugMessage, ap);
09565 
09566     dbg_print_tmp_buff[511] = 0;
09567 
09568     KdPrint(((PCHAR)&(dbg_print_tmp_buff[0])));
09569     HalDisplayString(dbg_print_tmp_buff);
09570 
09571     va_end(ap);
09572 
09573 } // end PrintNtConsole()
09574 

Generated on Sat May 26 2012 04:26:56 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.