Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenid_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(¶mPath, RegistryPath->Buffer); 09421 RtlAppendUnicodeToString(¶mPath, L"\\"); 09422 RtlAppendUnicodeToString(¶mPath, 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
1.7.6.1
|