1 /*++ 2 3 Copyright (c) 2002-2018 Alexandr A. Telyatnikov (Alter) 4 5 Module Name: 6 id_ata.cpp 7 8 Abstract: 9 This is the miniport driver for ATA/ATAPI IDE/SATA/AHCI controllers 10 with Busmaster DMA and Serial ATA support 11 12 Author: 13 Alexander A. Telyatnikov (Alter) 14 15 Environment: 16 kernel mode only 17 18 Notes: 19 20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 Revision History: 32 33 The skeleton was taken from standard ATAPI.SYS from NT4 DDK by 34 Mike Glass (MGlass) 35 Chuck Park (ChuckP) 36 37 Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by 38 S�ren Schmidt, Copyright (c) 1998-2007 39 40 All parts of code are significantly changed/updated by 41 Alter, Copyright (c) 2002-2014: 42 43 1. Internal command queueing/reordering 44 2. Drive identification 45 3. Support for 2 _independent_ channels in a single PCI device 46 4. Smart host<->drive transfer rate slowdown (for bad cable) 47 5. W2k support (binary compatibility) 48 6. HDD hot swap under NT4 49 7. XP support (binary compatibility) 50 8. Serial ATA (SATA/SATA2/SATA3) support 51 9. NT 3.51 support (binary compatibility) 52 10. AHCI support 53 54 etc. (See todo.txt) 55 56 Licence: 57 GPLv2 58 59 --*/ 60 61 #include "stdafx.h" 62 63 #ifndef UNIATA_CORE 64 65 static const CHAR ver_string[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR "\n"; 66 67 static const CHAR uniata_comm_name[] = UNIATA_COMM_PORT_VENDOR_STR " \n"; 68 69 UNICODE_STRING SavedRegPath; 70 WCHAR SavedRegPathBuffer[256]; 71 72 #endif //UNIATA_CORE 73 74 //UCHAR AtaCommands48[256]; 75 //UCHAR AtaCommandFlags[256]; 76 77 ULONG SkipRaids = 1; 78 ULONG ForceSimplex = 0; 79 80 LONGLONG g_Perf = 0; 81 ULONG g_PerfDt = 0; 82 83 #ifdef _DEBUG 84 ULONG g_LogToDisplay = 0; 85 #endif //_DEBUG 86 87 ULONG g_WaitBusyInISR = 1; 88 89 ULONG g_opt_WaitBusyResetCount = 10000; // 20000 90 ULONG g_opt_WaitBusyCount = 200; // 20000 91 ULONG g_opt_WaitBusyDelay = 10; // 150 92 ULONG g_opt_WaitDrqDelay = 10; // 100 93 ULONG g_opt_WaitBusyLongCount = 2000; // 2000 94 ULONG g_opt_WaitBusyLongDelay = 250; // 250 95 ULONG g_opt_MaxIsrWait = 40; 96 97 ULONG g_opt_DriveSelectNanoDelay = 0; // 400; // ns 98 99 BOOLEAN g_opt_AtapiSendDisableIntr = 0; // 0 100 BOOLEAN g_opt_AtapiDmaRawRead = 1; // 0 101 BOOLEAN g_opt_AtapiNoDma = FALSE; 102 BOOLEAN g_opt_BochsDmaReadWorkaround = FALSE; 103 BOOLEAN hasPCI = FALSE; 104 105 ULONG g_opt_VirtualMachine = 0; // Auto 106 107 BOOLEAN InDriverEntry = TRUE; 108 BOOLEAN g_Dump = FALSE; 109 110 BOOLEAN g_opt_Verbose = 0; 111 112 BOOLEAN WinVer_WDM_Model = FALSE; 113 ULONG CPU_num = 1; 114 115 //UCHAR EnableDma = FALSE; 116 //UCHAR EnableReorder = FALSE; 117 118 UCHAR g_foo = 0; 119 120 BOOLEAN 121 NTAPI 122 AtapiResetController__( 123 IN PVOID HwDeviceExtension, 124 IN ULONG PathId, 125 IN UCHAR CompleteType 126 ); 127 128 VOID 129 NTAPI 130 AtapiHwInitialize__( 131 IN PHW_DEVICE_EXTENSION deviceExtension, 132 IN ULONG lChannel 133 ); 134 135 VOID 136 NTAPI 137 UniataUserDeviceReset( 138 PHW_DEVICE_EXTENSION deviceExtension, 139 PHW_LU_EXTENSION LunExt, 140 ULONG lChannel 141 ); 142 143 #define RESET_COMPLETE_CURRENT 0x00 144 #define RESET_COMPLETE_ALL 0x01 145 #define RESET_COMPLETE_NONE 0x02 146 147 #ifndef UNIATA_CORE 148 149 VOID 150 NTAPI 151 AtapiCallBack_X( 152 IN PVOID HwDeviceExtension 153 ); 154 155 #ifdef UNIATA_USE_XXableInterrupts 156 #define RETTYPE_XXableInterrupts BOOLEAN 157 #define RETVAL_XXableInterrupts TRUE 158 #else 159 #define RETTYPE_XXableInterrupts VOID 160 #define RETVAL_XXableInterrupts 161 #endif 162 163 RETTYPE_XXableInterrupts 164 NTAPI 165 AtapiInterruptDpc( 166 IN PVOID HwDeviceExtension 167 ); 168 169 RETTYPE_XXableInterrupts 170 NTAPI 171 AtapiEnableInterrupts__( 172 IN PVOID HwDeviceExtension 173 ); 174 175 VOID 176 NTAPI 177 AtapiQueueTimerDpc( 178 IN PVOID HwDeviceExtension, 179 IN ULONG lChannel, 180 IN PHW_TIMER HwScsiTimer, 181 IN ULONG MiniportTimerValue 182 ); 183 184 SCSI_ADAPTER_CONTROL_STATUS 185 NTAPI 186 AtapiAdapterControl( 187 IN PVOID HwDeviceExtension, 188 IN SCSI_ADAPTER_CONTROL_TYPE ControlType, 189 IN PVOID Parameters 190 ); 191 192 #endif //UNIATA_CORE 193 194 #ifndef UNIATA_CORE 195 196 BOOLEAN 197 NTAPI 198 AtapiRegGetStringParameterValue( 199 IN PWSTR RegistryPath, 200 IN PWSTR Name, 201 IN PWCHAR Str, 202 IN ULONG MaxLen 203 ) 204 { 205 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched 206 NTSTATUS status; 207 RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY]; 208 UNICODE_STRING ustr; 209 210 ustr.Buffer = Str; 211 ustr.Length = 212 ustr.MaximumLength = (USHORT)MaxLen; 213 RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY)); 214 215 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 216 parameters[0].Name = Name; 217 parameters[0].EntryContext = &ustr; 218 parameters[0].DefaultType = REG_SZ; 219 parameters[0].DefaultData = Str; 220 parameters[0].DefaultLength = MaxLen; 221 222 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/, 223 RegistryPath, parameters, NULL, NULL); 224 225 if(!NT_SUCCESS(status)) 226 return FALSE; 227 228 return TRUE; 229 230 #undef ITEMS_TO_QUERY 231 } // end AtapiRegGetStringParameterValue() 232 233 234 #endif //UNIATA_CORE 235 236 VOID 237 DDKFASTAPI 238 UniataNanoSleep( 239 ULONG nano 240 ) 241 { 242 LONGLONG t; 243 LARGE_INTEGER t0; 244 245 #ifdef NAVO_TEST 246 return; 247 #endif //NAVO_TEST 248 249 if(!nano || !g_Perf || !g_PerfDt) 250 return; 251 t = (g_Perf * nano) / g_PerfDt / 1000; 252 if(!t) { 253 t = 1; 254 } 255 do { 256 KeQuerySystemTime(&t0); 257 t--; 258 } while(t); 259 } // end UniataNanoSleep() 260 261 #define AtapiWritePortN_template(_type, _Type, sz) \ 262 VOID \ 263 DDKFASTAPI \ 264 AtapiWritePort##sz( \ 265 IN PHW_CHANNEL chan, \ 266 IN ULONGIO_PTR _port, \ 267 IN _type data \ 268 ) \ 269 { \ 270 PIORES res; \ 271 if(_port >= IDX_MAX_REG) { \ 272 res = (PIORES)(_port); \ 273 } else \ 274 if(chan) { \ 275 res = &chan->RegTranslation[_port]; \ 276 } else { \ 277 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \ 278 return; \ 279 } \ 280 if(res->Proc) { \ 281 KdPrint(("PROC io write request @ ch %x, res* %x\n", chan, _port)); \ 282 ASSERT(FALSE); /* We should never get here */ \ 283 } \ 284 if(!res->MemIo) { \ 285 ScsiPortWritePort##_Type((_type*)(ULONGIO_PTR)(res->Addr), data); \ 286 } else { \ 287 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \ 288 ScsiPortWriteRegister##_Type((_type*)(ULONG_PTR)(res->Addr), data); \ 289 } \ 290 return; \ 291 } 292 293 AtapiWritePortN_template(ULONG, Ulong, 4); 294 AtapiWritePortN_template(USHORT, Ushort, 2); 295 AtapiWritePortN_template(UCHAR, Uchar, 1); 296 297 #define AtapiWritePortExN_template(_type, _Type, sz) \ 298 VOID \ 299 DDKFASTAPI \ 300 AtapiWritePortEx##sz( \ 301 IN PHW_CHANNEL chan, \ 302 IN ULONGIO_PTR _port, \ 303 IN ULONG offs, \ 304 IN _type data \ 305 ) \ 306 { \ 307 PIORES res; \ 308 if(_port >= IDX_MAX_REG) { \ 309 res = (PIORES)(_port); \ 310 } else \ 311 if(chan) { \ 312 res = &chan->RegTranslation[_port]; \ 313 } else { \ 314 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \ 315 return; \ 316 } \ 317 if(res->Proc) { \ 318 KdPrint(("PROC io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \ 319 ASSERT(FALSE); /* We should never get here */ \ 320 } \ 321 if(!res->MemIo) { \ 322 ScsiPortWritePort##_Type((_type*)(ULONGIO_PTR)(res->Addr+offs), data); \ 323 } else { \ 324 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \ 325 ScsiPortWriteRegister##_Type((_type*)(ULONG_PTR)(res->Addr+offs), data); \ 326 } \ 327 return; \ 328 } 329 330 AtapiWritePortExN_template(ULONG, Ulong, 4); 331 //AtapiWritePortExN_template(USHORT, Ushort, 2); 332 AtapiWritePortExN_template(UCHAR, Uchar, 1); 333 334 #define AtapiReadPortN_template(_type, _Type, sz) \ 335 _type \ 336 DDKFASTAPI \ 337 AtapiReadPort##sz( \ 338 IN PHW_CHANNEL chan, \ 339 IN ULONGIO_PTR _port \ 340 ) \ 341 { \ 342 PIORES res; \ 343 if(_port >= IDX_MAX_REG) { \ 344 res = (PIORES)(_port); \ 345 } else \ 346 if(chan) { \ 347 res = &chan->RegTranslation[_port]; \ 348 } else { \ 349 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \ 350 return (_type)(-1); \ 351 } \ 352 if(res->Proc) { \ 353 KdPrint(("PROC io read request @ ch %x, res* %x\n", chan, _port)); \ 354 ASSERT(FALSE); /* We should never get here */ \ 355 } \ 356 if(!res->MemIo) { \ 357 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \ 358 return ScsiPortReadPort##_Type((_type*)(ULONGIO_PTR)(res->Addr)); \ 359 } else { \ 360 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \ 361 return ScsiPortReadRegister##_Type((_type*)(ULONG_PTR)(res->Addr)); \ 362 } \ 363 } 364 365 AtapiReadPortN_template(ULONG, Ulong, 4); 366 AtapiReadPortN_template(USHORT, Ushort, 2); 367 AtapiReadPortN_template(UCHAR, Uchar, 1); 368 369 #define AtapiReadPortExN_template(_type, _Type, sz) \ 370 _type \ 371 DDKFASTAPI \ 372 AtapiReadPortEx##sz( \ 373 IN PHW_CHANNEL chan, \ 374 IN ULONGIO_PTR _port, \ 375 IN ULONG offs \ 376 ) \ 377 { \ 378 PIORES res; \ 379 if(_port >= IDX_MAX_REG) { \ 380 res = (PIORES)(_port); \ 381 } else \ 382 if(chan) { \ 383 res = &chan->RegTranslation[_port]; \ 384 } else { \ 385 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \ 386 return (_type)(-1); \ 387 } \ 388 if(res->Proc) { \ 389 KdPrint(("PROC io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \ 390 ASSERT(FALSE); /* We should never get here */ \ 391 } \ 392 if(!res->MemIo) { \ 393 return ScsiPortReadPort##_Type((_type*)(ULONGIO_PTR)(res->Addr+offs)); \ 394 } else { \ 395 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \ 396 return ScsiPortReadRegister##_Type((_type*)(ULONG_PTR)(res->Addr+offs)); \ 397 } \ 398 } 399 400 AtapiReadPortExN_template(ULONG, Ulong, 4); 401 //AtapiReadPortExN_template(USHORT, Ushort, 2); 402 AtapiReadPortExN_template(UCHAR, Uchar, 1); 403 404 #define AtapiReadPortBufferN_template(_type, _Type, sz) \ 405 VOID \ 406 DDKFASTAPI \ 407 AtapiReadBuffer##sz( \ 408 IN PHW_CHANNEL chan, \ 409 IN ULONGIO_PTR _port, \ 410 IN PVOID Buffer, \ 411 IN ULONG Count, \ 412 IN ULONG Timing \ 413 ) \ 414 { \ 415 PIORES res; \ 416 \ 417 if(Timing) { \ 418 while(Count) { \ 419 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \ 420 Count--; \ 421 Buffer = ((_type*)Buffer)+1; \ 422 UniataNanoSleep(Timing); \ 423 } \ 424 return; \ 425 } \ 426 \ 427 if(_port >= IDX_MAX_REG) { \ 428 res = (PIORES)(_port); \ 429 } else \ 430 if(chan) { \ 431 res = &chan->RegTranslation[_port]; \ 432 } else { \ 433 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \ 434 return; \ 435 } \ 436 if(!res->MemIo) { \ 437 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \ 438 ScsiPortReadPortBuffer##_Type((_type*)(ULONGIO_PTR)(res->Addr), (_type*)Buffer, Count); \ 439 return; \ 440 } \ 441 while(Count) { \ 442 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(ULONG_PTR)(res->Addr)); \ 443 Count--; \ 444 Buffer = ((_type*)Buffer)+1; \ 445 } \ 446 return; \ 447 } 448 449 #define AtapiWritePortBufferN_template(_type, _Type, sz) \ 450 VOID \ 451 DDKFASTAPI \ 452 AtapiWriteBuffer##sz( \ 453 IN PHW_CHANNEL chan, \ 454 IN ULONGIO_PTR _port, \ 455 IN PVOID Buffer, \ 456 IN ULONG Count, \ 457 IN ULONG Timing \ 458 ) \ 459 { \ 460 PIORES res; \ 461 \ 462 if(Timing) { \ 463 while(Count) { \ 464 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \ 465 Buffer = ((_type*)Buffer)+1; \ 466 Count--; \ 467 UniataNanoSleep(Timing); \ 468 } \ 469 return; \ 470 } \ 471 \ 472 if(_port >= IDX_MAX_REG) { \ 473 res = (PIORES)(_port); \ 474 } else \ 475 if(chan) { \ 476 res = &chan->RegTranslation[_port]; \ 477 } else { \ 478 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \ 479 return; \ 480 } \ 481 if(!res->MemIo) { \ 482 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \ 483 ScsiPortWritePortBuffer##_Type((_type*)(ULONGIO_PTR)(res->Addr), (_type*)Buffer, Count); \ 484 return; \ 485 } \ 486 while(Count) { \ 487 ScsiPortWriteRegister##_Type((_type*)(ULONG_PTR)(res->Addr), *((_type*)Buffer)); \ 488 Count--; \ 489 Buffer = ((_type*)Buffer)+1; \ 490 } \ 491 return; \ 492 } 493 494 AtapiWritePortBufferN_template(ULONG, Ulong, 4); 495 AtapiWritePortBufferN_template(USHORT, Ushort, 2); 496 497 AtapiReadPortBufferN_template(ULONG, Ulong, 4); 498 AtapiReadPortBufferN_template(USHORT, Ushort, 2); 499 500 501 UCHAR 502 DDKFASTAPI 503 AtapiSuckPort2( 504 IN PHW_CHANNEL chan 505 ) 506 { 507 UCHAR statusByte; 508 ULONG i; 509 510 // Assume, proper drive is already seleted 511 WaitOnBusyLong(chan); 512 for (i = 0; i < 0x10000; i++) { 513 514 GetStatus(chan, statusByte); 515 if (statusByte & IDE_STATUS_DRQ) { 516 // Suck out any remaining bytes and throw away. 517 AtapiReadPort2(chan, IDX_IO1_i_Data); 518 UniataNanoSleep(PIO0_TIMING); 519 } else { 520 break; 521 } 522 } 523 if(i) { 524 KdPrint2((PRINT_PREFIX "AtapiSuckPort2: overrun detected (%#x words)\n", i )); 525 } 526 return statusByte; 527 } // AtapiSuckPort2() 528 529 ULONG 530 DDKFASTAPI 531 AtapiSuckPortBuffer2( 532 IN PHW_CHANNEL chan, 533 IN PUSHORT Buffer, 534 IN ULONG Count 535 ) 536 { 537 UCHAR statusByte; 538 ULONG i; 539 USHORT data; 540 BOOLEAN retry = FALSE; 541 542 // Assume, proper drive is already seleted 543 WaitOnBusyLong(chan); 544 for (i = 0; i < Count; i++) { 545 546 GetStatus(chan, statusByte); 547 if (statusByte & IDE_STATUS_DRQ) { 548 // Suck out any remaining bytes and throw away. 549 data = AtapiReadPort2(chan, IDX_IO1_i_Data); 550 (*Buffer) = data; 551 Count--; 552 Buffer++; 553 UniataNanoSleep(PIO0_TIMING); 554 retry = FALSE; 555 } else { 556 if(i<Count && !retry) { 557 KdPrint2((PRINT_PREFIX " wait...\n")); 558 WaitForDrq(chan); 559 retry = TRUE; 560 } 561 break; 562 } 563 } 564 if(i) { 565 KdPrint2((PRINT_PREFIX "AtapiSuckPortBuffer2: %#x words\n", i )); 566 if(i==Count) { 567 AtapiSuckPort2(chan); 568 } 569 } 570 return i; 571 } // AtapiSuckPortBuffer2() 572 573 #ifdef __REACTOS__ 574 VOID 575 DDKFASTAPI 576 FillDeviceIdentificationString( 577 IN OUT PINQUIRYDATA InquiryData, 578 IN PIDENTIFY_DATA2 IdentifyData) 579 { 580 ULONG i; 581 ULONG IdentifierLen, FirstWordLen; 582 583 /* We need to copy a field which is 20 chars long to two fields which are 8+16 bytes long (VendorId + ProductId) 584 * Note that a space will be added between those fields when displaying them. 585 * => Try to split identifier on space char. 586 */ 587 588 #define IDENTIFIER_LETTER(Identifier, i) (((PUCHAR)Identifier)[(i) ^ 1]) 589 590 for (IdentifierLen = 20; IdentifierLen > 0 && IDENTIFIER_LETTER(IdentifyData->ModelNumber, IdentifierLen - 1) == ' '; IdentifierLen--) 591 ; 592 593 /* Strategy 1: copy first word to VendorId if len <= 8. Copy other chars to ProductId */ 594 for (FirstWordLen = 0; IDENTIFIER_LETTER(IdentifyData->ModelNumber, FirstWordLen) != ' ' && FirstWordLen < IdentifierLen; FirstWordLen++) 595 ; 596 if (FirstWordLen <= 8) 597 { 598 for (i = 0; i < FirstWordLen; i++) 599 InquiryData->VendorId[i] = IDENTIFIER_LETTER(IdentifyData->ModelNumber, i); 600 for (i = FirstWordLen + 1; i < IdentifierLen; i++) 601 InquiryData->ProductId[i - FirstWordLen - 1] = IDENTIFIER_LETTER(IdentifyData->ModelNumber, i); 602 return; 603 } 604 605 /* Strategy 2: copy everything to ProductId */ 606 if (IdentifierLen <= 16) 607 { 608 for (i = 0; i < IdentifierLen; i++) 609 InquiryData->ProductId[i] = IDENTIFIER_LETTER(IdentifyData->ModelNumber, i); 610 return; 611 } 612 613 /* Strategy 3: copy first to VendorId, then to ProductId */ 614 for (i = 0; i < 24; i += 2) 615 MOV_DW_SWP(InquiryData->DeviceIdentificationString[i], ((PUCHAR)IdentifyData->ModelNumber)[i]); 616 } 617 #endif 618 619 UCHAR 620 DDKFASTAPI 621 SelectDrive( 622 IN PHW_CHANNEL chan, 623 IN ULONG DeviceNumber 624 ) 625 { 626 if(!chan) { 627 return 0; 628 } 629 /* 630 if(chan->lun[DeviceNumber] && 631 (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_CHANGER)) { 632 KdPrint3((" Select %d\n", DeviceNumber)); 633 } 634 */ 635 if(chan->last_devsel == DeviceNumber) { 636 //KdPrint3((" Selected %d\n", DeviceNumber)); 637 return 1; 638 } 639 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1); \ 640 chan->last_devsel = DeviceNumber ? 1 : 0; 641 if(!g_opt_DriveSelectNanoDelay) { 642 //KdPrint3((" Select %d\n", DeviceNumber)); 643 return 2; 644 } 645 //KdPrint3((" Select %d (%d ns)\n", DeviceNumber, g_opt_DriveSelectNanoDelay)); 646 UniataNanoSleep(g_opt_DriveSelectNanoDelay); 647 return 2; 648 } // end SelectDrive() 649 650 UCHAR 651 DDKFASTAPI 652 WaitOnBusy( 653 IN PHW_CHANNEL chan 654 ) 655 { 656 ULONG i; 657 UCHAR Status; 658 659 GetStatus(chan, Status); 660 for (i=0; i<g_opt_WaitBusyCount; i++) { 661 if (Status & IDE_STATUS_BUSY) { 662 AtapiStallExecution(g_opt_WaitBusyDelay); 663 GetStatus(chan, Status); 664 continue; 665 } else { 666 break; 667 } 668 } 669 return Status; 670 } // end WaitOnBusy() 671 672 UCHAR 673 DDKFASTAPI 674 WaitOnBusyLong( 675 IN PHW_CHANNEL chan 676 ) 677 { 678 ULONG i; 679 UCHAR Status; 680 681 Status = WaitOnBusy(chan); 682 if(!(Status & IDE_STATUS_BUSY)) 683 return Status; 684 for (i=0; i<g_opt_WaitBusyLongCount; i++) { 685 GetStatus(chan, Status); 686 if (Status & IDE_STATUS_BUSY) { 687 AtapiStallExecution(g_opt_WaitBusyLongDelay); 688 continue; 689 } else { 690 break; 691 } 692 } 693 return Status; 694 } // end WaitOnBusyLong() 695 696 UCHAR 697 DDKFASTAPI 698 WaitOnBaseBusy( 699 IN PHW_CHANNEL chan 700 ) 701 { 702 ULONG i; 703 UCHAR Status = IDE_STATUS_WRONG; 704 for (i=0; i<g_opt_WaitBusyCount; i++) { 705 GetBaseStatus(chan, Status); 706 if (Status & IDE_STATUS_BUSY) { 707 AtapiStallExecution(g_opt_WaitBusyDelay); 708 continue; 709 } else { 710 break; 711 } 712 } 713 return Status; 714 } // end WaitOnBaseBusy() 715 716 UCHAR 717 DDKFASTAPI 718 WaitOnBaseBusyLong( 719 IN PHW_CHANNEL chan 720 ) 721 { 722 ULONG i; 723 UCHAR Status; 724 725 Status = WaitOnBaseBusy(chan); 726 if(!(Status & IDE_STATUS_BUSY)) 727 return Status; 728 for (i=0; i<2000; i++) { 729 GetBaseStatus(chan, Status); 730 if (Status & IDE_STATUS_BUSY) { 731 AtapiStallExecution(250); 732 continue; 733 } else { 734 break; 735 } 736 } 737 return Status; 738 } // end WaitOnBaseBusyLong() 739 740 UCHAR 741 DDKFASTAPI 742 UniataIsIdle( 743 IN struct _HW_DEVICE_EXTENSION* deviceExtension, 744 IN UCHAR Status 745 ) 746 { 747 UCHAR Status2; 748 749 if(Status == IDE_STATUS_WRONG) { 750 return IDE_STATUS_WRONG; 751 } 752 if(Status & IDE_STATUS_BUSY) { 753 return Status; 754 } 755 // if(deviceExtension->HwFlags & UNIATA_SATA) { 756 if(UniataIsSATARangeAvailable(deviceExtension, 0)) { 757 if(Status & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) { 758 return Status; 759 } 760 } else { 761 Status2 = Status & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX); 762 if ((Status & IDE_STATUS_BUSY) || 763 (Status2 != IDE_STATUS_IDLE && Status2 != IDE_STATUS_DRDY)) { 764 return Status; 765 } 766 } 767 return IDE_STATUS_IDLE; 768 } // end UniataIsIdle() 769 770 UCHAR 771 DDKFASTAPI 772 WaitForIdleLong( 773 IN PHW_CHANNEL chan 774 ) 775 { 776 ULONG i; 777 UCHAR Status; 778 UCHAR Status2; 779 for (i=0; i<20000; i++) { 780 GetStatus(chan, Status); 781 Status2 = UniataIsIdle(chan->DeviceExtension, Status); 782 if(Status2 == IDE_STATUS_WRONG) { 783 // no drive ? 784 break; 785 } else 786 if(Status2 & IDE_STATUS_BUSY) { 787 AtapiStallExecution(10); 788 continue; 789 } else { 790 break; 791 } 792 } 793 return Status; 794 } // end WaitForIdleLong() 795 796 UCHAR 797 DDKFASTAPI 798 WaitForDrq( 799 IN PHW_CHANNEL chan 800 ) 801 { 802 ULONG i; 803 UCHAR Status; 804 for (i=0; i<1000; i++) { 805 GetStatus(chan, Status); 806 if (Status & IDE_STATUS_BUSY) { 807 AtapiStallExecution(g_opt_WaitDrqDelay); 808 } else if (Status & IDE_STATUS_DRQ) { 809 break; 810 } else { 811 AtapiStallExecution(g_opt_WaitDrqDelay*2); 812 } 813 } 814 return Status; 815 } // end WaitForDrq() 816 817 UCHAR 818 DDKFASTAPI 819 WaitShortForDrq( 820 IN PHW_CHANNEL chan 821 ) 822 { 823 ULONG i; 824 UCHAR Status; 825 for (i=0; i<2; i++) { 826 GetStatus(chan, Status); 827 if (Status & IDE_STATUS_BUSY) { 828 AtapiStallExecution(g_opt_WaitDrqDelay); 829 } else if (Status & IDE_STATUS_DRQ) { 830 break; 831 } else { 832 AtapiStallExecution(g_opt_WaitDrqDelay); 833 } 834 } 835 return Status; 836 } // end WaitShortForDrq() 837 838 VOID 839 DDKFASTAPI 840 AtapiSoftReset( 841 IN PHW_CHANNEL chan, 842 IN ULONG DeviceNumber 843 ) 844 { 845 //ULONG c = chan->lChannel; 846 ULONG i = 30 * 1000; 847 UCHAR dma_status = 0; 848 KdPrint2((PRINT_PREFIX "AtapiSoftReset:\n")); 849 UCHAR statusByte0, statusByte2; 850 851 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { 852 UniataAhciSoftReset(chan->DeviceExtension, chan->lChannel, DeviceNumber); 853 return; 854 } 855 856 GetBaseStatus(chan, statusByte2); 857 KdPrint2((PRINT_PREFIX " statusByte2 %x:\n", statusByte2)); 858 SelectDrive(chan, DeviceNumber); 859 if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MANUAL_CHS) { 860 // For ESDI/MFM 861 KdPrint2((PRINT_PREFIX " ESDI/MFM\n")); 862 AtapiStallExecution(10000); 863 for (i = 0; i < 1000; i++) { 864 AtapiStallExecution(999); 865 } 866 /* } else 867 // Seems to be unnecessary, verified by KtP 868 if(!hasPCI) { 869 // original atapi.sys behavior for old ISA-only hardware 870 AtapiStallExecution(10000); 871 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET); 872 for (i = 0; i < 1000; i++) { 873 AtapiStallExecution(999); 874 } */ 875 } else { 876 AtapiStallExecution(500); 877 GetBaseStatus(chan, statusByte2); 878 statusByte0 = statusByte2; 879 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET); 880 881 // Do not wait for BUSY assertion if it was initially set, jump to 882 // BUSY release wait loop 883 if(!(statusByte0 & IDE_STATUS_BUSY)) { 884 // Wait for BUSY assertion, in some cases delay may occure 885 // 100ms should be enough 886 if(g_opt_VirtualMachine == VM_BOCHS) { 887 i = 100; 888 } else { 889 i = 10*1000; 890 } 891 statusByte2 = AtapiReadPort1(chan, IDX_IO1_i_Status); 892 while (!(statusByte2 & IDE_STATUS_BUSY) && 893 i--) 894 { 895 if(!(statusByte0 & IDE_STATUS_ERROR) && (statusByte2 & IDE_STATUS_ERROR)) { 896 KdPrint2((PRINT_PREFIX " Command aborted, statusByte2 %x:\n", statusByte2)); 897 break; 898 } 899 AtapiStallExecution(10); 900 } 901 } 902 903 i = 30 * 1000; 904 // ReactOS modification: Already stop looping when we know that the drive has finished resetting. 905 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that 906 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original 907 // implementation. (which is around 1 second) 908 while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) && 909 i--) 910 { 911 AtapiStallExecution(30); 912 } 913 KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n")); 914 chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_REINIT_DMA; 915 } 916 917 chan->last_devsel = -1; // make sure proper drive would be selected 918 SelectDrive(chan, DeviceNumber); 919 WaitOnBusy(chan); 920 GetBaseStatus(chan, statusByte2); 921 AtapiStallExecution(500); 922 923 GetBaseStatus(chan, statusByte2); 924 if(chan && chan->DeviceExtension) { 925 dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel); 926 KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status)); 927 } else { 928 KdPrint2((PRINT_PREFIX " can't get DMA status\n")); 929 } 930 if(dma_status & BM_STATUS_INTR) { 931 // bullshit, we have DMA interrupt, but had never initiate DMA operation 932 KdPrint2((PRINT_PREFIX " clear unexpected DMA intr on ATAPI reset\n")); 933 AtapiDmaDone(chan->DeviceExtension, DeviceNumber, chan->lChannel, NULL); 934 GetBaseStatus(chan, statusByte2); 935 } 936 if(chan->DeviceExtension->HwFlags & UNIATA_SATA) { 937 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, DeviceNumber); 938 /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) { 939 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1); 940 }*/ 941 } 942 return; 943 944 } // end AtapiSoftReset() 945 946 VOID 947 DDKFASTAPI 948 AtapiHardReset( 949 IN struct _HW_CHANNEL* chan, 950 IN BOOLEAN DisableInterrupts, 951 IN ULONG Delay 952 ) 953 { 954 KdPrint2((PRINT_PREFIX "AtapiHardReset: %d, dis=%d\n", Delay, DisableInterrupts)); 955 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_RESET_CONTROLLER | 956 (DisableInterrupts ? IDE_DC_DISABLE_INTERRUPTS : 0)); 957 chan->last_devsel = -1; 958 AtapiStallExecution(Delay); 959 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_REENABLE_CONTROLLER); 960 } // end AtapiHardReset() 961 962 /* 963 Send command to device. 964 Translate to 48-Lba form if required 965 */ 966 UCHAR 967 NTAPI 968 AtaCommand48( 969 IN PHW_DEVICE_EXTENSION deviceExtension, 970 IN ULONG DeviceNumber, 971 IN ULONG lChannel, 972 IN UCHAR command, 973 IN ULONGLONG lba, 974 IN USHORT count, 975 IN USHORT feature, 976 IN ULONG wait_flags 977 ) 978 { 979 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 980 UCHAR statusByte; 981 ULONG i; 982 PUCHAR plba; 983 984 KdPrint2((PRINT_PREFIX "AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n", 985 deviceExtension->DevIndex, deviceExtension->Channel, DeviceNumber, command, lba, count, feature )); 986 987 if(deviceExtension->HwFlags & UNIATA_AHCI) { 988 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); 989 990 KdPrint3((" (ahci)\n")); 991 992 statusByte = UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber, 993 (PSCSI_REQUEST_BLOCK)NULL, 994 NULL, 995 0, 996 command, 997 lba, count, 998 feature, 999 0 /* ahci flags */ , 1000 wait_flags, 1001 1000 /* timeout 1 sec */ 1002 ); 1003 1004 return statusByte; 1005 } 1006 1007 SelectDrive(chan, DeviceNumber); 1008 1009 statusByte = WaitOnBusy(chan); 1010 1011 /* ready to issue command ? */ 1012 if (statusByte & IDE_STATUS_BUSY) { 1013 KdPrint2((PRINT_PREFIX " Returning BUSY status\n")); 1014 return statusByte; 1015 } 1016 // !!! We should not check ERROR condition here 1017 // ERROR bit may be asserted durring previous operation 1018 // and not cleared after SELECT 1019 1020 //>>>>>> NV: 2006/08/03 1021 if(((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp|ATA_CMD_FLAG_FUA)) == ATA_CMD_FLAG_LBAIOsupp) && 1022 CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) { 1023 KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count)); 1024 return IDE_STATUS_ERROR; 1025 //return SRB_STATUS_ERROR; 1026 } 1027 //<<<<<< NV: 2006/08/03 1028 1029 /* only use 48bit addressing if needed because of the overhead */ 1030 if (UniAta_need_lba48(command, lba, count, 1031 chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48)) { 1032 1033 KdPrint2((PRINT_PREFIX " dev %#x USE_LBA_48\n", DeviceNumber )); 1034 /* translate command into 48bit version */ 1035 if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) { 1036 command = AtaCommands48[command]; 1037 } else { 1038 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n")); 1039 return (UCHAR)-1; 1040 } 1041 1042 chan->ChannelCtrlFlags |= CTRFLAGS_LBA48; 1043 plba = (PUCHAR)&lba; 1044 1045 AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)(feature>>8)); 1046 AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)feature); 1047 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)(count>>8)); 1048 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)count); 1049 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[3])); 1050 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[0])); 1051 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[4])); 1052 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[1])); 1053 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[5])); 1054 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[2])); 1055 1056 //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber )); 1057 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) ); 1058 } else { 1059 1060 plba = (PUCHAR)&lba; //ktp 1061 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48; 1062 1063 //if(feature || 1064 // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) { 1065 AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)feature); 1066 //} 1067 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)count); 1068 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)plba[0]); 1069 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)plba[1]); 1070 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)plba[2]); 1071 if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) { 1072 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber )); 1073 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) ); 1074 } else { 1075 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber )); 1076 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) ); 1077 } 1078 } 1079 1080 // write command code to device 1081 AtapiWritePort1(chan, IDX_IO1_o_Command, command); 1082 1083 switch (wait_flags) { 1084 case ATA_WAIT_INTR: 1085 1086 // caller requested wait for interrupt 1087 for(i=0;i<4;i++) { 1088 WaitOnBusy(chan); 1089 statusByte = WaitForDrq(chan); 1090 if (statusByte & IDE_STATUS_DRQ) 1091 break; 1092 AtapiStallExecution(500); 1093 KdPrint2((PRINT_PREFIX " retry waiting DRQ, status %#x\n", statusByte)); 1094 } 1095 1096 return statusByte; 1097 1098 case ATA_WAIT_IDLE: 1099 1100 // caller requested wait for entering Wait state 1101 for (i=0; i<30 * 1000; i++) { 1102 1103 GetStatus(chan, statusByte); 1104 statusByte = UniataIsIdle(deviceExtension, statusByte); 1105 if(statusByte == IDE_STATUS_WRONG) { 1106 // no drive ? 1107 break; 1108 } else 1109 if(statusByte & IDE_STATUS_ERROR) { 1110 break; 1111 } else 1112 if(statusByte & IDE_STATUS_BUSY) { 1113 AtapiStallExecution(100); 1114 continue; 1115 } else 1116 if((statusByte & ~IDE_STATUS_INDEX) == IDE_STATUS_IDLE) { 1117 break; 1118 } else { 1119 //if(deviceExtension->HwFlags & UNIATA_SATA) { 1120 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 1121 break; 1122 } 1123 AtapiStallExecution(100); 1124 } 1125 } 1126 //statusByte |= IDE_STATUS_BUSY; 1127 break; 1128 1129 case ATA_WAIT_READY: 1130 statusByte = WaitOnBusyLong(chan); 1131 break; 1132 case ATA_WAIT_BASE_READY: 1133 statusByte = WaitOnBaseBusyLong(chan); 1134 break; 1135 case ATA_IMMEDIATE: 1136 GetStatus(chan, statusByte); 1137 if (statusByte & IDE_STATUS_ERROR) { 1138 KdPrint2((PRINT_PREFIX " Warning: Immed Status %#x :(\n", statusByte)); 1139 if(statusByte == (IDE_STATUS_IDLE | IDE_STATUS_ERROR)) { 1140 break; 1141 } 1142 KdPrint2((PRINT_PREFIX " try to continue\n")); 1143 statusByte &= ~IDE_STATUS_ERROR; 1144 1145 } else { 1146 //KdPrint2((PRINT_PREFIX " send Status %#x\n", statusByte)); 1147 } 1148 UniataExpectChannelInterrupt(chan, TRUE); 1149 // !!!!! 1150 InterlockedExchange(&(chan->CheckIntr), 1151 CHECK_INTR_IDLE); 1152 1153 statusByte = IDE_STATUS_SUCCESS; 1154 break; 1155 } 1156 1157 //KdPrint2((PRINT_PREFIX " Status %#x\n", statusByte)); 1158 1159 return statusByte; 1160 } // end AtaCommand48() 1161 1162 /* 1163 Send command to device. 1164 This is simply wrapper for AtaCommand48() 1165 */ 1166 UCHAR 1167 NTAPI 1168 AtaCommand( 1169 IN PHW_DEVICE_EXTENSION deviceExtension, 1170 IN ULONG DeviceNumber, 1171 IN ULONG lChannel, 1172 IN UCHAR command, 1173 IN USHORT cylinder, 1174 IN UCHAR head, 1175 IN UCHAR sector, 1176 IN UCHAR count, 1177 IN UCHAR feature, 1178 IN ULONG wait_flags 1179 ) 1180 { 1181 if(!(deviceExtension->HwFlags & UNIATA_AHCI)) { 1182 return AtaCommand48(deviceExtension, DeviceNumber, lChannel, 1183 command, 1184 (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24), 1185 count, feature, wait_flags); 1186 } else { 1187 return UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber, 1188 (PSCSI_REQUEST_BLOCK)NULL, 1189 NULL, 1190 0, 1191 command, 1192 (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24), 1193 count, 1194 feature, 1195 0 /* ahci flags */ , 1196 wait_flags, 1197 1000 /* timeout 1 sec */ 1198 ); 1199 1200 } 1201 } // end AtaCommand() 1202 1203 LONG 1204 NTAPI 1205 AtaPio2Mode(LONG pio) 1206 { 1207 switch (pio) { 1208 default: return ATA_PIO; 1209 case 0: return ATA_PIO0; 1210 case 1: return ATA_PIO1; 1211 case 2: return ATA_PIO2; 1212 case 3: return ATA_PIO3; 1213 case 4: return ATA_PIO4; 1214 case 5: return ATA_PIO5; 1215 } 1216 } // end AtaPio2Mode() 1217 1218 LONG 1219 NTAPI 1220 AtaPioMode(PIDENTIFY_DATA2 ident) 1221 { 1222 if (ident->PioTimingsValid) { 1223 if (ident->AdvancedPIOModes & AdvancedPIOModes_5) 1224 return 5; 1225 if (ident->AdvancedPIOModes & AdvancedPIOModes_4) 1226 return 4; 1227 if (ident->AdvancedPIOModes & AdvancedPIOModes_3) 1228 return 3; 1229 } 1230 if (ident->PioCycleTimingMode == 2) 1231 return 2; 1232 if (ident->PioCycleTimingMode == 1) 1233 return 1; 1234 if (ident->PioCycleTimingMode == 0) 1235 return 0; 1236 return IOMODE_NOT_SPECIFIED; 1237 } // end AtaPioMode() 1238 1239 LONG 1240 NTAPI 1241 AtaWmode(PIDENTIFY_DATA2 ident) 1242 { 1243 if (ident->MultiWordDMASupport & 0x04) 1244 return 2; 1245 if (ident->MultiWordDMASupport & 0x02) 1246 return 1; 1247 if (ident->MultiWordDMASupport & 0x01) 1248 return 0; 1249 return IOMODE_NOT_SPECIFIED; 1250 } // end AtaWmode() 1251 1252 LONG 1253 NTAPI 1254 AtaUmode(PIDENTIFY_DATA2 ident) 1255 { 1256 if (!ident->UdmaModesValid) 1257 return IOMODE_NOT_SPECIFIED; 1258 if (ident->UltraDMASupport & 0x40) 1259 return 6; 1260 if (ident->UltraDMASupport & 0x20) 1261 return 5; 1262 if (ident->UltraDMASupport & 0x10) 1263 return 4; 1264 if (ident->UltraDMASupport & 0x08) 1265 return 3; 1266 if (ident->UltraDMASupport & 0x04) 1267 return 2; 1268 if (ident->UltraDMASupport & 0x02) 1269 return 1; 1270 if (ident->UltraDMASupport & 0x01) 1271 return 0; 1272 return IOMODE_NOT_SPECIFIED; 1273 } // end AtaUmode() 1274 1275 LONG 1276 NTAPI 1277 AtaSAmode(PIDENTIFY_DATA2 ident) { 1278 if(!ident->SataCapabilities || 1279 ident->SataCapabilities == 0xffff) { 1280 return IOMODE_NOT_SPECIFIED; 1281 } 1282 if(ident->SataCapabilities & ATA_SATA_GEN3) { 1283 return ATA_SA600; 1284 } else 1285 if(ident->SataCapabilities & ATA_SATA_GEN2) { 1286 return ATA_SA300; 1287 } else 1288 if(ident->SataCapabilities & ATA_SATA_GEN1) { 1289 return ATA_SA150; 1290 } 1291 return IOMODE_NOT_SPECIFIED; 1292 } // end AtaSAmode() 1293 1294 #ifndef UNIATA_CORE 1295 1296 VOID 1297 NTAPI 1298 AtapiTimerDpc( 1299 IN PVOID HwDeviceExtension 1300 ) 1301 { 1302 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1303 PHW_TIMER HwScsiTimer; 1304 LARGE_INTEGER time; 1305 ULONG MiniportTimerValue; 1306 BOOLEAN recall = FALSE; 1307 ULONG lChannel; 1308 PHW_CHANNEL chan; 1309 1310 KdPrint2((PRINT_PREFIX "AtapiTimerDpc:\n")); 1311 1312 lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan; 1313 if(lChannel == CHAN_NOT_SPECIFIED) { 1314 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no items\n")); 1315 return; 1316 } 1317 chan = &(deviceExtension->chan[lChannel]); 1318 1319 while(TRUE) { 1320 1321 HwScsiTimer = chan->HwScsiTimer; 1322 chan->HwScsiTimer = NULL; 1323 1324 deviceExtension->FirstDpcChan = chan->NextDpcChan; 1325 if(deviceExtension->FirstDpcChan != CHAN_NOT_SPECIFIED) { 1326 recall = TRUE; 1327 } 1328 1329 HwScsiTimer(HwDeviceExtension); 1330 1331 chan->NextDpcChan = CHAN_NOT_SPECIFIED; 1332 1333 lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan; 1334 if(lChannel == CHAN_NOT_SPECIFIED) { 1335 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no more items\n")); 1336 deviceExtension->FirstDpcChan = 1337 deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED; 1338 return; 1339 } 1340 1341 KeQuerySystemTime(&time); 1342 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart)); 1343 1344 chan = &deviceExtension->chan[lChannel]; 1345 if(time.QuadPart >= chan->DpcTime - 10) { 1346 // call now 1347 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n", 1348 (ULONG)(chan->DpcTime >> 32), (ULONG)(chan->DpcTime))); 1349 continue; 1350 } 1351 break; 1352 } 1353 1354 if(recall) { 1355 deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED; 1356 MiniportTimerValue = (ULONG)(time.QuadPart - chan->DpcTime)/10; 1357 if(!MiniportTimerValue) 1358 MiniportTimerValue = 1; 1359 1360 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: recall AtapiTimerDpc\n")); 1361 ScsiPortNotification(RequestTimerCall, HwDeviceExtension, 1362 AtapiTimerDpc, 1363 MiniportTimerValue 1364 ); 1365 } 1366 return; 1367 1368 } // end AtapiTimerDpc() 1369 1370 /* 1371 Wrapper for ScsiPort, that implements smart Dpc 1372 queueing. We need it to allow parallel functioning 1373 of IDE channels with shared interrupt. Standard Dpc mechanism 1374 cancels previous Dpc request (if any), but we need Dpc queue. 1375 */ 1376 VOID 1377 NTAPI 1378 AtapiQueueTimerDpc( 1379 IN PVOID HwDeviceExtension, 1380 IN ULONG lChannel, 1381 IN PHW_TIMER HwScsiTimer, 1382 IN ULONG MiniportTimerValue 1383 ) 1384 { 1385 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1386 LARGE_INTEGER time; 1387 LARGE_INTEGER time2; 1388 ULONG i; 1389 PHW_CHANNEL prev_chan; 1390 PHW_CHANNEL chan; 1391 // BOOLEAN UseRequestTimerCall = TRUE; 1392 1393 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel)); 1394 KeQuerySystemTime(&time); 1395 time2 = time; 1396 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart)); 1397 time.QuadPart += MiniportTimerValue*10; 1398 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time.HighPart, time.LowPart)); 1399 1400 KdPrint2((PRINT_PREFIX " ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension->ActiveDpcChan, deviceExtension->FirstDpcChan)); 1401 1402 i = deviceExtension->FirstDpcChan; 1403 chan = prev_chan = NULL; 1404 while(i != CHAN_NOT_SPECIFIED) { 1405 prev_chan = chan; 1406 chan = &(deviceExtension->chan[i]); 1407 if(chan->DpcTime > time.QuadPart) { 1408 break; 1409 } 1410 i = chan->NextDpcChan; 1411 } 1412 chan = &(deviceExtension->chan[lChannel]); 1413 if(!prev_chan) { 1414 deviceExtension->FirstDpcChan = lChannel; 1415 } else { 1416 prev_chan->NextDpcChan = lChannel; 1417 } 1418 chan->NextDpcChan = i; 1419 chan->HwScsiTimer = HwScsiTimer; 1420 chan->DpcTime = time.QuadPart; 1421 1422 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2.HighPart, time2.LowPart)); 1423 if(time.QuadPart <= time2.QuadPart) { 1424 MiniportTimerValue = 1; 1425 } else { 1426 MiniportTimerValue = (ULONG)((time.QuadPart - time2.QuadPart) / 10); 1427 } 1428 1429 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel)); 1430 ScsiPortNotification(RequestTimerCall, HwDeviceExtension, 1431 AtapiTimerDpc, 1432 MiniportTimerValue); 1433 1434 } // end AtapiQueueTimerDpc() 1435 1436 #endif //UNIATA_CORE 1437 1438 #ifdef _DEBUG 1439 VOID 1440 NTAPI 1441 UniataDumpATARegs( 1442 IN PHW_CHANNEL chan 1443 ) 1444 { 1445 ULONG j; 1446 UCHAR statusByteAlt; 1447 1448 GetStatus(chan, statusByteAlt); 1449 KdPrint2((PRINT_PREFIX " AltStatus (%#x)\n", statusByteAlt)); 1450 1451 for(j=1; j<IDX_IO1_SZ; j++) { 1452 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j); 1453 KdPrint2((PRINT_PREFIX 1454 " Reg_%#x (%#x) = %#x\n", 1455 j, 1456 chan->RegTranslation[IDX_IO1+j].Addr, 1457 statusByteAlt)); 1458 } 1459 if(!chan->RegTranslation[IDX_BM_IO].Addr) { 1460 return; 1461 } 1462 for(j=0; j<IDX_BM_IO_SZ-1; j++) { 1463 statusByteAlt = AtapiReadPort1(chan, IDX_BM_IO+j); 1464 KdPrint2((PRINT_PREFIX 1465 " BM_%#x (%#x) = %#x\n", 1466 j, 1467 chan->RegTranslation[IDX_BM_IO+j].Addr, 1468 statusByteAlt)); 1469 } 1470 return; 1471 } // end UniataDumpATARegs() 1472 #endif //_DEBUG 1473 1474 VOID 1475 NTAPI 1476 UniataSnapAtaRegs( 1477 IN PHW_CHANNEL chan, 1478 IN ULONG DeviceNumber, 1479 IN OUT PIDEREGS_EX regs 1480 ) 1481 { 1482 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { 1483 // AHCI 1484 UniataAhciSnapAtaRegs(chan, DeviceNumber, regs); 1485 } else { 1486 // SATA/PATA, assume drive is selected 1487 ULONG j; 1488 UCHAR statusByteAlt; 1489 1490 if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { 1491 for(j=IDX_IO1_i_Error; j<=IDX_IO1_i_Status; j++) { 1492 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j); 1493 ((PUCHAR)regs)[j-1] = statusByteAlt; 1494 } 1495 regs->bOpFlags = 0; 1496 } else { 1497 regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect); 1498 for(j=IDX_IO1_i_Error; j<IDX_IO1_i_DriveSelect; j++) { 1499 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j); 1500 ((PUCHAR)regs)[j-1] = statusByteAlt; 1501 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j); 1502 ((PUCHAR)regs)[j+8-1] = statusByteAlt; 1503 } 1504 regs->bCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status); 1505 } 1506 } 1507 return; 1508 } // end UniataSnapAtaRegs() 1509 1510 /*++ 1511 1512 Routine Description: 1513 1514 Issue IDENTIFY command to a device. 1515 1516 Arguments: 1517 1518 HwDeviceExtension - HBA miniport driver's adapter data storage 1519 DeviceNumber - Indicates which device. 1520 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY. 1521 1522 Return Value: 1523 1524 TRUE if all goes well. 1525 1526 --*/ 1527 BOOLEAN 1528 NTAPI 1529 IssueIdentify( 1530 IN PVOID HwDeviceExtension, 1531 IN ULONG DeviceNumber, 1532 IN ULONG lChannel, 1533 IN UCHAR Command, 1534 IN BOOLEAN NoSetup 1535 ) 1536 { 1537 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1538 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 1539 ULONG waitCount = 50000; 1540 ULONG j; 1541 UCHAR statusByte; 1542 //UCHAR statusByte2; 1543 UCHAR signatureLow, 1544 signatureHigh; 1545 BOOLEAN atapiDev = FALSE; 1546 BOOLEAN use_ahci = FALSE; 1547 PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber]; 1548 1549 use_ahci = UniataIsSATARangeAvailable(deviceExtension, lChannel) && 1550 (deviceExtension->HwFlags & UNIATA_AHCI); 1551 1552 if(chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) { 1553 if(chan->PmLunMap & (1 << DeviceNumber)) { 1554 // OK 1555 } else { 1556 KdPrint2((PRINT_PREFIX "IssueIdentify: PM empty port\n")); 1557 return FALSE; 1558 } 1559 } else 1560 if(DeviceNumber && (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) { 1561 KdPrint2((PRINT_PREFIX "IssueIdentify: NO SLAVE\n")); 1562 return FALSE; 1563 } 1564 if(LunExt->DeviceFlags & DFLAGS_HIDDEN) { 1565 KdPrint2((PRINT_PREFIX "IssueIdentify: HIDDEN\n")); 1566 return FALSE; 1567 } 1568 1569 if(use_ahci) { 1570 statusByte = WaitOnBusyLong(chan); 1571 #ifdef _DEBUG 1572 if(!chan->AhciInternalAtaReq) { 1573 KdPrint2((PRINT_PREFIX "!AhciInternalAtaReq\n")); 1574 } 1575 #endif 1576 } else { 1577 SelectDrive(chan, DeviceNumber); 1578 AtapiStallExecution(10); 1579 statusByte = WaitOnBusyLong(chan); 1580 // Check that the status register makes sense. 1581 GetBaseStatus(chan, statusByte); 1582 /* 1583 // unnecessary 1584 if(!hasPCI) { 1585 // original atapi.sys behavior for old ISA-only hardware 1586 AtapiStallExecution(100); 1587 } 1588 */ 1589 } 1590 1591 if (Command == IDE_COMMAND_IDENTIFY) { 1592 // Mask status byte ERROR bits. 1593 statusByte = UniataIsIdle(deviceExtension, statusByte & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX)); 1594 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte)); 1595 // Check if register value is reasonable. 1596 1597 if(statusByte != IDE_STATUS_IDLE) { 1598 1599 // No reset here !!! 1600 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte != IDE_STATUS_IDLE\n")); 1601 1602 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) { 1603 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 1604 SelectDrive(chan, DeviceNumber); 1605 WaitOnBusyLong(chan); 1606 1607 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow); 1608 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh); 1609 1610 if (signatureLow == ATAPI_MAGIC_LSB && 1611 signatureHigh == ATAPI_MAGIC_MSB) { 1612 // Device is Atapi. 1613 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber)); 1614 return FALSE; 1615 } 1616 1617 // We really should wait up to 31 seconds 1618 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds! 1619 // (30 seconds for device 1) 1620 do { 1621 // Wait for Busy to drop. 1622 AtapiStallExecution(100); 1623 GetStatus(chan, statusByte); 1624 if(statusByte == IDE_STATUS_WRONG) { 1625 KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber)); 1626 return FALSE; 1627 } 1628 1629 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--); 1630 GetBaseStatus(chan, statusByte); 1631 1632 SelectDrive(chan, DeviceNumber); 1633 } else { 1634 GetBaseStatus(chan, statusByte); 1635 } 1636 // Another check for signature, to deal with one model Atapi that doesn't assert signature after 1637 // a soft reset. 1638 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow); 1639 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh); 1640 1641 if (signatureLow == ATAPI_MAGIC_LSB && 1642 signatureHigh == ATAPI_MAGIC_MSB) { 1643 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber)); 1644 // Device is Atapi. 1645 return FALSE; 1646 } 1647 1648 statusByte = UniataIsIdle(deviceExtension, statusByte) & ~IDE_STATUS_INDEX; 1649 if (statusByte != IDE_STATUS_IDLE) { 1650 // Give up on this. 1651 KdPrint2((PRINT_PREFIX "IssueIdentify: no dev (dev %d)\n", DeviceNumber)); 1652 return FALSE; 1653 } 1654 } 1655 } else { 1656 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte)); 1657 if(statusByte == IDE_STATUS_WRONG) { 1658 return FALSE; 1659 } 1660 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) { 1661 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 1662 statusByte = WaitForIdleLong(chan); 1663 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte)); 1664 } 1665 atapiDev = TRUE; 1666 } 1667 1668 // if(deviceExtension->HwFlags & UNIATA_SATA) { 1669 if(use_ahci) { 1670 statusByte = UniataAhciSendPIOCommand(HwDeviceExtension, lChannel, DeviceNumber, 1671 (PSCSI_REQUEST_BLOCK)NULL, 1672 (PUCHAR)(&deviceExtension->FullIdentifyData), 1673 DEV_BSIZE, 1674 Command, 1675 0, 0, 1676 0, 1677 0 /* ahci flags */ , 1678 ATA_WAIT_INTR, 1679 1000 /* timeout 1 sec */ 1680 ); 1681 j = 9; // AHCI is rather different, skip loop at all 1682 } else 1683 if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) { 1684 j = 9; // don't send IDENTIFY, assume it is not supported 1685 KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS\n")); 1686 RtlZeroMemory(&(deviceExtension->FullIdentifyData), sizeof(deviceExtension->FullIdentifyData)); 1687 RtlCopyMemory(&(deviceExtension->FullIdentifyData), &(LunExt->IdentifyData), sizeof(LunExt->IdentifyData)); 1688 } else 1689 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 1690 j = 4; // skip old-style checks 1691 } else { 1692 j = 0; 1693 } 1694 for (; j < 4*2; j++) { 1695 // Send IDENTIFY command. 1696 1697 // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer. 1698 1699 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, (j < 4) ? DEV_BSIZE : 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR); 1700 // Clear interrupt 1701 1702 if (!statusByte) { 1703 KdPrint2((PRINT_PREFIX "IssueIdentify: 0-status, not present\n")); 1704 return FALSE; 1705 } else 1706 if (statusByte & IDE_STATUS_DRQ) { 1707 // Read status to acknowledge any interrupts generated. 1708 KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte)); 1709 GetBaseStatus(chan, statusByte); 1710 // One last check for Atapi. 1711 if (Command == IDE_COMMAND_IDENTIFY) { 1712 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow); 1713 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh); 1714 1715 if (signatureLow == ATAPI_MAGIC_LSB && 1716 signatureHigh == ATAPI_MAGIC_MSB) { 1717 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber)); 1718 // Device is Atapi. 1719 return FALSE; 1720 } 1721 } 1722 break; 1723 } else { 1724 KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte)); 1725 if (Command == IDE_COMMAND_IDENTIFY) { 1726 // Check the signature. If DRQ didn't come up it's likely Atapi. 1727 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow); 1728 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh); 1729 1730 if (signatureLow == ATAPI_MAGIC_LSB && 1731 signatureHigh == ATAPI_MAGIC_MSB) { 1732 // Device is Atapi. 1733 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber)); 1734 return FALSE; 1735 } 1736 } else { 1737 if(!(statusByte & IDE_STATUS_ERROR) && (statusByte & IDE_STATUS_BUSY)) { 1738 KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n")); 1739 break; 1740 } 1741 } 1742 // Device didn't respond correctly. It will be given one more chance. 1743 KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n", 1744 statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error))); 1745 GetBaseStatus(chan, statusByte); 1746 AtapiSoftReset(chan,DeviceNumber); 1747 1748 AtapiDisableInterrupts(deviceExtension, lChannel); 1749 AtapiEnableInterrupts(deviceExtension, lChannel); 1750 1751 GetBaseStatus(chan, statusByte); 1752 //GetStatus(chan, statusByte); 1753 KdPrint2((PRINT_PREFIX "IssueIdentify: Status after soft reset (%#x)\n", statusByte)); 1754 } 1755 } 1756 // Check for error on really stupid master devices that assert random 1757 // patterns of bits in the status register at the slave address. 1758 if ((Command == IDE_COMMAND_IDENTIFY) && (statusByte & IDE_STATUS_ERROR)) { 1759 KdPrint2((PRINT_PREFIX "IssueIdentify: Exit on error (%#x)\n", statusByte)); 1760 return FALSE; 1761 } 1762 1763 if(use_ahci) { 1764 // everything should already be done by controller 1765 } else 1766 if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) { 1767 j = 9; // don't send IDENTIFY, assume it is not supported 1768 KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS (2)\n")); 1769 statusByte = WaitForDrq(chan); 1770 statusByte = WaitOnBusyLong(chan); 1771 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte)); 1772 GetBaseStatus(chan, statusByte); 1773 } else { 1774 1775 KdPrint2((PRINT_PREFIX "IssueIdentify: Status before read words %#x\n", statusByte)); 1776 // Suck out 256 words. After waiting for one model that asserts busy 1777 // after receiving the Packet Identify command. 1778 statusByte = WaitForDrq(chan); 1779 statusByte = WaitOnBusyLong(chan); 1780 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte)); 1781 1782 if (!(statusByte & IDE_STATUS_DRQ)) { 1783 KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte)); 1784 GetBaseStatus(chan, statusByte); 1785 return FALSE; 1786 } 1787 GetBaseStatus(chan, statusByte); 1788 KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte)); 1789 1790 #ifdef _DEBUG 1791 if(atapiDev) { 1792 j = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); 1793 KdPrint3((PRINT_PREFIX "IssueIdentify: iReason %x\n", j)); 1794 1795 j = 1796 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow); 1797 1798 j |= 1799 (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8; 1800 KdPrint3((PRINT_PREFIX "IssueIdentify: wCount %x\n", j)); 1801 1802 } 1803 #endif //_DEBUG 1804 1805 if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) { 1806 1807 KdPrint2((PRINT_PREFIX " use 16bit IO\n")); 1808 // ATI/SII chipsets with memory-mapped IO hangs when 1809 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled 1810 // Unfortunately, I don't know yet how to workaround it except 1811 // spacifying manual delay in the way you see below. 1812 ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING); 1813 1814 // Work around for some IDE and one model Atapi that will present more than 1815 // 256 bytes for the Identify data. 1816 KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte)); 1817 statusByte = AtapiSuckPort2(chan); 1818 } else { 1819 KdPrint2((PRINT_PREFIX " use 32bit IO\n")); 1820 ReadBuffer2(chan, (PULONG)&deviceExtension->FullIdentifyData, 256/2, PIO0_TIMING); 1821 } 1822 1823 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte)); 1824 statusByte = WaitForDrq(chan); 1825 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte)); 1826 GetBaseStatus(chan, statusByte); 1827 } 1828 KdPrint2((PRINT_PREFIX "IssueIdentify: Status after read words %#x\n", statusByte)); 1829 1830 if(NoSetup) { 1831 KdPrint2((PRINT_PREFIX "IssueIdentify: no setup, exiting\n")); 1832 return TRUE; 1833 } 1834 1835 KdPrint2((PRINT_PREFIX "Model: %20.20s\n", deviceExtension->FullIdentifyData.ModelNumber)); 1836 KdPrint2((PRINT_PREFIX "FW: %4.4s\n", deviceExtension->FullIdentifyData.FirmwareRevision)); 1837 KdPrint2((PRINT_PREFIX "S/N: %20.20s\n", deviceExtension->FullIdentifyData.SerialNumber)); 1838 if(g_opt_VirtualMachine == VM_AUTO) { 1839 if((deviceExtension->FullIdentifyData.FirmwareRevision[0] == 0 || 1840 deviceExtension->FullIdentifyData.FirmwareRevision[0] == ' ') && 1841 (deviceExtension->FullIdentifyData.FirmwareRevision[1] == 0 || 1842 deviceExtension->FullIdentifyData.FirmwareRevision[1] == ' ')) { 1843 // Check for BOCHS VM signature. If no additional PCI devices (e.g. VGA) 1844 // are declared BOCHS looks like regular PC 1845 if (!atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDH00", 6)) { 1846 KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS HDD\n")); 1847 g_opt_VirtualMachine = VM_BOCHS; 1848 } else 1849 if (atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDC00", 6)) { 1850 KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS CD\n")); 1851 g_opt_VirtualMachine = VM_BOCHS; 1852 } 1853 } 1854 } 1855 1856 KdPrint2((PRINT_PREFIX "Pio: %x\n", deviceExtension->FullIdentifyData.PioCycleTimingMode)); 1857 if(deviceExtension->FullIdentifyData.PioTimingsValid) { 1858 KdPrint2((PRINT_PREFIX "APio: %x\n", deviceExtension->FullIdentifyData.AdvancedPIOModes)); 1859 } 1860 KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive)); 1861 KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive)); 1862 if(deviceExtension->FullIdentifyData.UdmaModesValid) { 1863 KdPrint2((PRINT_PREFIX "UDMA: %x/%x\n", deviceExtension->FullIdentifyData.UltraDMAActive, deviceExtension->FullIdentifyData.UltraDMASupport)); 1864 } 1865 KdPrint2((PRINT_PREFIX "SATA: %x\n", deviceExtension->FullIdentifyData.SataEnable)); 1866 KdPrint2((PRINT_PREFIX "SATA support: %x, CAPs %#x\n", 1867 deviceExtension->FullIdentifyData.SataSupport, 1868 deviceExtension->FullIdentifyData.SataCapabilities)); 1869 1870 LunExt->LimitedTransferMode = 1871 LunExt->OrigTransferMode = 1872 (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_MAX); 1873 LunExt->TransferMode = 1874 (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_ACTIVE); 1875 1876 KdPrint2((PRINT_PREFIX "OrigTransferMode: %x, Active: %x\n", LunExt->OrigTransferMode, LunExt->TransferMode)); 1877 KdPrint2((PRINT_PREFIX "Accoustic %d, cur %d\n", 1878 deviceExtension->FullIdentifyData.VendorAcoustic, 1879 deviceExtension->FullIdentifyData.CurrentAcoustic 1880 )); 1881 KdPrint2((PRINT_PREFIX "AdvPowerMode %d\n", 1882 deviceExtension->FullIdentifyData.CfAdvPowerMode 1883 )); 1884 1885 KdPrint2((PRINT_PREFIX "PowerMngt %d/%d, APM %d/%d\n", 1886 deviceExtension->FullIdentifyData.FeaturesEnabled.PowerMngt, 1887 deviceExtension->FullIdentifyData.FeaturesSupport.PowerMngt, 1888 deviceExtension->FullIdentifyData.FeaturesEnabled.APM, 1889 deviceExtension->FullIdentifyData.FeaturesSupport.APM 1890 )); 1891 1892 // Check out a few capabilities / limitations of the device. 1893 if (deviceExtension->FullIdentifyData.RemovableStatus & 1) { 1894 // Determine if this drive supports the MSN functions. 1895 KdPrint2((PRINT_PREFIX "IssueIdentify: Marking drive %d as removable. SFE = %d\n", 1896 DeviceNumber, 1897 deviceExtension->FullIdentifyData.RemovableStatus)); 1898 LunExt->DeviceFlags |= DFLAGS_REMOVABLE_DRIVE; 1899 } 1900 if(use_ahci) { 1901 // AHCI doesn't recommend using PIO and multiblock 1902 LunExt->MaximumBlockXfer = 0; 1903 } else 1904 if (deviceExtension->FullIdentifyData.MaximumBlockTransfer) { 1905 // Determine max. block transfer for this device. 1906 LunExt->MaximumBlockXfer = 1907 (UCHAR)(deviceExtension->FullIdentifyData.MaximumBlockTransfer & 0xFF); 1908 } 1909 LunExt->NumOfSectors = 0; 1910 if (Command == IDE_COMMAND_IDENTIFY) { 1911 ULONGLONG NumOfSectors=0; 1912 ULONGLONG NativeNumOfSectors=0; 1913 ULONGLONG cylinders=0; 1914 ULONGLONG tmp_cylinders=0; 1915 1916 KdPrint2((PRINT_PREFIX "PhysLogSectorSize %#x, %#x, offset %#x\n", 1917 deviceExtension->FullIdentifyData.PhysLogSectorSize, 1918 deviceExtension->FullIdentifyData.LargeSectorSize, 1919 deviceExtension->FullIdentifyData.LogicalSectorOffset 1920 )); 1921 1922 KdPrint2((PRINT_PREFIX "NV PM_Sup %d, PM_En %d, En %d, PM ver %#x ver %#x\n", 1923 deviceExtension->FullIdentifyData.NVCache_PM_Supported, 1924 deviceExtension->FullIdentifyData.NVCache_PM_Enabled, 1925 deviceExtension->FullIdentifyData.NVCache_Enabled, 1926 deviceExtension->FullIdentifyData.NVCache_PM_Version, 1927 deviceExtension->FullIdentifyData.NVCache_Version 1928 )); 1929 1930 KdPrint2((PRINT_PREFIX "R-rate %d\n", 1931 deviceExtension->FullIdentifyData.NominalMediaRotationRate 1932 )); 1933 KdPrint2((PRINT_PREFIX "WC %d/%d, LA %d/%d, WB %d/%d, RB %d/%d, Q %d/%d\n", 1934 deviceExtension->FullIdentifyData.FeaturesEnabled.WriteCache, 1935 deviceExtension->FullIdentifyData.FeaturesSupport.WriteCache, 1936 deviceExtension->FullIdentifyData.FeaturesEnabled.LookAhead, 1937 deviceExtension->FullIdentifyData.FeaturesSupport.LookAhead, 1938 deviceExtension->FullIdentifyData.FeaturesEnabled.WriteBuffer, 1939 deviceExtension->FullIdentifyData.FeaturesSupport.WriteBuffer, 1940 deviceExtension->FullIdentifyData.FeaturesEnabled.ReadBuffer, 1941 deviceExtension->FullIdentifyData.FeaturesSupport.ReadBuffer, 1942 deviceExtension->FullIdentifyData.FeaturesEnabled.Queued, 1943 deviceExtension->FullIdentifyData.FeaturesSupport.Queued 1944 )); 1945 1946 KdPrint2((PRINT_PREFIX "Protected %d/%d status %#x, rev %#x\n", 1947 deviceExtension->FullIdentifyData.FeaturesEnabled.Protected, 1948 deviceExtension->FullIdentifyData.FeaturesSupport.Protected, 1949 deviceExtension->FullIdentifyData.SecurityStatus, 1950 deviceExtension->FullIdentifyData.MasterPasswdRevision 1951 )); 1952 1953 // Read very-old-style drive geometry 1954 KdPrint2((PRINT_PREFIX "CHS %#x:%#x:%#x\n", 1955 deviceExtension->FullIdentifyData.NumberOfCylinders, 1956 deviceExtension->FullIdentifyData.NumberOfHeads, 1957 deviceExtension->FullIdentifyData.SectorsPerTrack 1958 )); 1959 NumOfSectors = deviceExtension->FullIdentifyData.NumberOfCylinders * 1960 deviceExtension->FullIdentifyData.NumberOfHeads * 1961 deviceExtension->FullIdentifyData.SectorsPerTrack; 1962 KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors)); 1963 // Check for HDDs > 8Gb 1964 if ((deviceExtension->FullIdentifyData.NumberOfCylinders == 0x3fff) && 1965 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/ 1966 deviceExtension->FullIdentifyData.NumberOfHeads && 1967 deviceExtension->FullIdentifyData.SectorsPerTrack && 1968 (NumOfSectors < deviceExtension->FullIdentifyData.UserAddressableSectors)) { 1969 KdPrint2((PRINT_PREFIX "NumberOfCylinders == 0x3fff\n")); 1970 cylinders = 1971 (deviceExtension->FullIdentifyData.UserAddressableSectors / 1972 (deviceExtension->FullIdentifyData.NumberOfHeads * 1973 deviceExtension->FullIdentifyData.SectorsPerTrack)); 1974 1975 KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders)); 1976 1977 NumOfSectors = cylinders * 1978 deviceExtension->FullIdentifyData.NumberOfHeads * 1979 deviceExtension->FullIdentifyData.SectorsPerTrack; 1980 1981 KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors)); 1982 } else { 1983 1984 } 1985 // Check for LBA mode 1986 KdPrint2((PRINT_PREFIX "SupportLba flag %#x\n", deviceExtension->FullIdentifyData.SupportLba)); 1987 KdPrint2((PRINT_PREFIX "SupportDMA flag %#x\n", deviceExtension->FullIdentifyData.SupportDma)); 1988 KdPrint2((PRINT_PREFIX "SoftReset %#x\n", deviceExtension->FullIdentifyData.SoftReset)); 1989 KdPrint2((PRINT_PREFIX "SupportIordy %#x, DisableIordy %#x\n", 1990 deviceExtension->FullIdentifyData.SupportIordy, 1991 deviceExtension->FullIdentifyData.DisableIordy 1992 )); 1993 KdPrint2((PRINT_PREFIX "MajorRevision %#x\n", deviceExtension->FullIdentifyData.MajorRevision)); 1994 KdPrint2((PRINT_PREFIX "UserAddressableSectors %#x\n", deviceExtension->FullIdentifyData.UserAddressableSectors)); 1995 if ( deviceExtension->FullIdentifyData.SupportLba 1996 || 1997 (deviceExtension->FullIdentifyData.MajorRevision && 1998 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/ 1999 deviceExtension->FullIdentifyData.UserAddressableSectors)) { 2000 KdPrint2((PRINT_PREFIX "LBA mode\n")); 2001 LunExt->DeviceFlags |= DFLAGS_LBA_ENABLED; 2002 } else { 2003 KdPrint2((PRINT_PREFIX "Keep orig geometry\n")); 2004 LunExt->DeviceFlags |= DFLAGS_ORIG_GEOMETRY; 2005 goto skip_lba_staff; 2006 } 2007 // Check for LBA48 support 2008 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) { 2009 if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48 && 2010 deviceExtension->FullIdentifyData.FeaturesEnabled.Address48 && 2011 deviceExtension->FullIdentifyData.NumberOfHeads && 2012 deviceExtension->FullIdentifyData.SectorsPerTrack && 2013 (deviceExtension->FullIdentifyData.UserAddressableSectors48 > NumOfSectors) 2014 ) { 2015 KdPrint2((PRINT_PREFIX "LBA48\n")); 2016 cylinders = 2017 (deviceExtension->FullIdentifyData.UserAddressableSectors48 / 2018 (deviceExtension->FullIdentifyData.NumberOfHeads * 2019 deviceExtension->FullIdentifyData.SectorsPerTrack)); 2020 2021 KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders)); 2022 2023 NativeNumOfSectors = cylinders * 2024 deviceExtension->FullIdentifyData.NumberOfHeads * 2025 deviceExtension->FullIdentifyData.SectorsPerTrack; 2026 2027 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors)); 2028 2029 if(NativeNumOfSectors > NumOfSectors) { 2030 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors)); 2031 NumOfSectors = NativeNumOfSectors; 2032 } 2033 } 2034 2035 // Check drive capacity report for LBA48-capable drives. 2036 if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48) { 2037 ULONG hNativeNumOfSectors; 2038 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE48\n")); 2039 2040 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel, 2041 IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY); 2042 2043 if(!(statusByte & IDE_STATUS_ERROR)) { 2044 if(use_ahci) { 2045 NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba; 2046 } else { 2047 NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) | 2048 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) | 2049 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) ; 2050 2051 AtapiWritePort1(chan, IDX_IO2_o_Control, 2052 IDE_DC_USE_HOB ); 2053 2054 KdPrint2((PRINT_PREFIX "Read high order bytes\n")); 2055 NativeNumOfSectors |= 2056 (ULONG)((ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24 ); 2057 hNativeNumOfSectors= 2058 (ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) | 2059 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 8) ; 2060 ((PULONG)&NativeNumOfSectors)[1] = hNativeNumOfSectors; 2061 } 2062 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors)); 2063 2064 // Some drives report LBA48 capability while has capacity below 128Gb 2065 // Probably they support large block-counters. 2066 // But the problem is that some of them reports higher part of Max LBA equal to lower part. 2067 // Here we check this 2068 if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) { 2069 KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!!\n")); 2070 2071 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel, 2072 IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY); 2073 2074 if(!(statusByte & IDE_STATUS_ERROR)) { 2075 if(use_ahci) { 2076 NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba; 2077 } else { 2078 NativeNumOfSectors = (ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) | 2079 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24) | 2080 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8 ) | 2081 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 32) | 2082 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) | 2083 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 40) 2084 ; 2085 } 2086 } 2087 2088 if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) { 2089 KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!! (2)\n")); 2090 NativeNumOfSectors = 0; 2091 } 2092 } 2093 2094 if(NumOfSectors <= ATA_MAX_LBA28 && 2095 NativeNumOfSectors > NumOfSectors) { 2096 2097 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE48\n")); 2098 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors)); 2099 2100 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel, 2101 IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY); 2102 if(!(statusByte & IDE_STATUS_ERROR)) { 2103 NumOfSectors = NativeNumOfSectors; 2104 } 2105 } 2106 } // !error 2107 } 2108 2109 if(NumOfSectors < 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) { 2110 // check for native LBA size 2111 // some drives report ~32Gb in Identify Block 2112 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE\n")); 2113 2114 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_READ_NATIVE_SIZE, 2115 0, IDE_USE_LBA, 0, 0, 0, ATA_WAIT_READY); 2116 2117 if(!(statusByte & IDE_STATUS_ERROR)) { 2118 if(use_ahci) { 2119 NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba; 2120 } else { 2121 NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) | 2122 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) | 2123 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) | 2124 (((ULONG)AtapiReadPort1(chan, IDX_IO1_i_DriveSelect) & 0xf) << 24); 2125 } 2126 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors)); 2127 2128 if(NativeNumOfSectors > NumOfSectors) { 2129 2130 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE\n")); 2131 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors)); 2132 2133 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel, 2134 IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY); 2135 if(!(statusByte & IDE_STATUS_ERROR)) { 2136 NumOfSectors = NativeNumOfSectors; 2137 } 2138 } 2139 } 2140 } 2141 2142 if(NumOfSectors > ATA_MAX_IOLBA28) { 2143 KdPrint2((PRINT_PREFIX "2TB threshold, force LBA64 WRITE requirement\n")); 2144 LunExt->DeviceFlags |= DFLAGS_LBA32plus; 2145 } 2146 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) 2147 2148 // fill IdentifyData with bogus geometry 2149 KdPrint2((PRINT_PREFIX "requested LunExt->GeomType=%x\n", LunExt->opt_GeomType)); 2150 if(deviceExtension->FullIdentifyData.CurrentSectorsPerTrack && 2151 deviceExtension->FullIdentifyData.NumberOfCurrentHeads) { 2152 tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.CurrentSectorsPerTrack * 2153 deviceExtension->FullIdentifyData.NumberOfCurrentHeads); 2154 } else 2155 if(deviceExtension->FullIdentifyData.SectorsPerTrack && 2156 deviceExtension->FullIdentifyData.NumberOfHeads) { 2157 KdPrint2((PRINT_PREFIX "Current C/H = %#I64x/%#I64x\n", 2158 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack, 2159 deviceExtension->FullIdentifyData.NumberOfCurrentHeads)); 2160 tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.SectorsPerTrack * 2161 deviceExtension->FullIdentifyData.NumberOfHeads); 2162 } else { 2163 tmp_cylinders = 0; 2164 } 2165 KdPrint2((PRINT_PREFIX "tmp_cylinders = %#I64x\n", tmp_cylinders)); 2166 if((tmp_cylinders < 0xffff) || (LunExt->opt_GeomType == GEOM_ORIG)) { 2167 // ok, we can keep original values 2168 if(LunExt->opt_GeomType == GEOM_AUTO) { 2169 LunExt->opt_GeomType = GEOM_ORIG; 2170 } 2171 } else { 2172 tmp_cylinders = NumOfSectors / (255*63); 2173 if(tmp_cylinders < 0xffff) { 2174 // we can use generic values for H/S for generic geometry approach 2175 if(LunExt->opt_GeomType == GEOM_AUTO) { 2176 LunExt->opt_GeomType = GEOM_STD; 2177 } 2178 } else { 2179 // we should use UNIATA geometry approach 2180 if(LunExt->opt_GeomType == GEOM_AUTO) { 2181 LunExt->opt_GeomType = GEOM_UNIATA; 2182 } 2183 } 2184 } 2185 2186 if(!deviceExtension->FullIdentifyData.SectorsPerTrack || 2187 !deviceExtension->FullIdentifyData.NumberOfHeads) { 2188 KdPrint2((PRINT_PREFIX "Zero S/H -> Force Use GEOM_STD\n")); 2189 } 2190 2191 if(LunExt->opt_GeomType == GEOM_STD) { 2192 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack = 2193 deviceExtension->FullIdentifyData.SectorsPerTrack = 63; 2194 2195 deviceExtension->FullIdentifyData.NumberOfCurrentHeads = 2196 deviceExtension->FullIdentifyData.NumberOfHeads = 255; 2197 2198 cylinders = NumOfSectors / (255*63); 2199 KdPrint2((PRINT_PREFIX "Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders, 255, 63)); 2200 } else 2201 if(LunExt->opt_GeomType == GEOM_UNIATA) { 2202 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x80)) { 2203 cylinders /= 2; 2204 KdPrint2((PRINT_PREFIX "cylinders /= 2\n")); 2205 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2; 2206 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2; 2207 } 2208 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x80)) { 2209 cylinders /= 2; 2210 KdPrint2((PRINT_PREFIX "cylinders /= 2 (2)\n")); 2211 deviceExtension->FullIdentifyData.NumberOfHeads *= 2; 2212 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2; 2213 } 2214 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x8000)) { 2215 cylinders /= 2; 2216 KdPrint2((PRINT_PREFIX "cylinders /= 2 (3)\n")); 2217 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2; 2218 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2; 2219 } 2220 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x8000)) { 2221 cylinders /= 2; 2222 KdPrint2((PRINT_PREFIX "cylinders /= 2 (4)\n")); 2223 deviceExtension->FullIdentifyData.NumberOfHeads *= 2; 2224 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2; 2225 } 2226 KdPrint2((PRINT_PREFIX "Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders, 2227 deviceExtension->FullIdentifyData.NumberOfCurrentHeads, 2228 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack)); 2229 } 2230 if(!cylinders) { 2231 KdPrint2((PRINT_PREFIX "cylinders = tmp_cylinders (%x = %x)\n", cylinders, tmp_cylinders)); 2232 cylinders = tmp_cylinders; 2233 } 2234 deviceExtension->FullIdentifyData.NumberOfCurrentCylinders = 2235 deviceExtension->FullIdentifyData.NumberOfCylinders = (USHORT)cylinders; 2236 2237 skip_lba_staff: 2238 2239 KdPrint2((PRINT_PREFIX "Geometry: C %#x (%#x)\n", 2240 deviceExtension->FullIdentifyData.NumberOfCylinders, 2241 deviceExtension->FullIdentifyData.NumberOfCurrentCylinders 2242 )); 2243 KdPrint2((PRINT_PREFIX "Geometry: H %#x (%#x)\n", 2244 deviceExtension->FullIdentifyData.NumberOfHeads, 2245 deviceExtension->FullIdentifyData.NumberOfCurrentHeads 2246 )); 2247 KdPrint2((PRINT_PREFIX "Geometry: S %#x (%#x)\n", 2248 deviceExtension->FullIdentifyData.SectorsPerTrack, 2249 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack 2250 )); 2251 2252 if(NumOfSectors) { 2253 LunExt->NumOfSectors = NumOfSectors; 2254 } 2255 if(deviceExtension->FullIdentifyData.MajorRevision && 2256 deviceExtension->FullIdentifyData.DoubleWordIo) { 2257 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED; 2258 KdPrint2((PRINT_PREFIX "IssueIdentify: DWORDIO supported\n")); 2259 } 2260 } else { 2261 // ATAPI 2262 if(deviceExtension->FullIdentifyData.MajorRevision && 2263 deviceExtension->FullIdentifyData.DoubleWordIo) { 2264 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED; 2265 KdPrint2((PRINT_PREFIX "IssueIdentify: DFLAGS_DWORDIO_ENABLED.\n")); 2266 } 2267 if(deviceExtension->FullIdentifyData.AtapiDMA.DMADirRequired) { 2268 KdPrint2((PRINT_PREFIX "DMADirRequired.\n")); 2269 } 2270 if(deviceExtension->FullIdentifyData.AtapiByteCount0) { 2271 KdPrint2((PRINT_PREFIX "AtapiByteCount0=%x\n", deviceExtension->FullIdentifyData.AtapiByteCount0)); 2272 } 2273 } 2274 2275 ScsiPortMoveMemory(&LunExt->IdentifyData, 2276 &deviceExtension->FullIdentifyData,sizeof(IDENTIFY_DATA2)); 2277 2278 InitBadBlocks(LunExt); 2279 2280 if ((LunExt->IdentifyData.DrqType & ATAPI_DRQT_INTR) && 2281 (Command != IDE_COMMAND_IDENTIFY)) { 2282 2283 // This device interrupts with the assertion of DRQ after receiving 2284 // Atapi Packet Command 2285 LunExt->DeviceFlags |= DFLAGS_INT_DRQ; 2286 KdPrint2((PRINT_PREFIX "IssueIdentify: Device interrupts on assertion of DRQ.\n")); 2287 2288 } else { 2289 KdPrint2((PRINT_PREFIX "IssueIdentify: Device does not interrupt on assertion of DRQ.\n")); 2290 } 2291 2292 if(Command != IDE_COMMAND_IDENTIFY) { 2293 // ATAPI branch 2294 if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_TAPE) { 2295 // This is a tape. 2296 LunExt->DeviceFlags |= DFLAGS_TAPE_DEVICE; 2297 KdPrint2((PRINT_PREFIX "IssueIdentify: Device is a tape drive.\n")); 2298 } else 2299 if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM || 2300 LunExt->IdentifyData.DeviceType == ATAPI_TYPE_OPTICAL) { 2301 KdPrint2((PRINT_PREFIX "IssueIdentify: Device is CD/Optical drive.\n")); 2302 // set CD default costs 2303 LunExt->RwSwitchCost = REORDER_COST_SWITCH_RW_CD; 2304 LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_CD; 2305 LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_CD; 2306 statusByte = WaitForDrq(chan); 2307 } else { 2308 KdPrint2((PRINT_PREFIX "IssueIdentify: ATAPI drive type %#x.\n", 2309 LunExt->IdentifyData.DeviceType)); 2310 } 2311 KdPrint2((PRINT_PREFIX "IssueIdentify: AtapiCmdSize %#x\n", deviceExtension->FullIdentifyData.AtapiCmdSize)); 2312 } else { 2313 KdPrint2((PRINT_PREFIX "IssueIdentify: hard drive.\n")); 2314 } 2315 2316 GetBaseStatus(chan, statusByte); 2317 KdPrint2((PRINT_PREFIX "IssueIdentify: final Status on exit (%#x)\n", statusByte)); 2318 return TRUE; 2319 2320 } // end IssueIdentify() 2321 2322 2323 /*++ 2324 2325 Routine Description: 2326 Set drive parameters using the IDENTIFY data. 2327 2328 Arguments: 2329 HwDeviceExtension - HBA miniport driver's adapter data storage 2330 DeviceNumber - Indicates which device. 2331 2332 Return Value: 2333 TRUE if all goes well. 2334 2335 --*/ 2336 BOOLEAN 2337 NTAPI 2338 SetDriveParameters( 2339 IN PVOID HwDeviceExtension, 2340 IN ULONG DeviceNumber, 2341 IN ULONG lChannel 2342 ) 2343 { 2344 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 2345 PIDENTIFY_DATA2 identifyData; 2346 PHW_LU_EXTENSION LunExt; 2347 // ULONG i; 2348 UCHAR statusByte; 2349 UCHAR errorByte; 2350 2351 LunExt = deviceExtension->chan[lChannel].lun[DeviceNumber]; 2352 identifyData = &(LunExt->IdentifyData); 2353 2354 if(LunExt->DeviceFlags & 2355 (DFLAGS_LBA_ENABLED | DFLAGS_ORIG_GEOMETRY)) 2356 return TRUE; 2357 2358 KdPrint2((PRINT_PREFIX "SetDriveParameters: Number of heads %#x\n", identifyData->NumberOfHeads)); 2359 KdPrint2((PRINT_PREFIX "SetDriveParameters: Sectors per track %#x\n", identifyData->SectorsPerTrack)); 2360 2361 // Send SET PARAMETER command. 2362 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, 2363 IDE_COMMAND_SET_DRIVE_PARAMETERS, 0, 2364 (identifyData->NumberOfHeads - 1), 0, 2365 (UCHAR)identifyData->SectorsPerTrack, 0, ATA_WAIT_IDLE); 2366 2367 statusByte = UniataIsIdle(deviceExtension, statusByte); 2368 if(statusByte & IDE_STATUS_ERROR) { 2369 errorByte = AtapiReadPort1(&deviceExtension->chan[lChannel], IDX_IO1_i_Error); 2370 KdPrint2((PRINT_PREFIX "SetDriveParameters: Error bit set. Status %#x, error %#x\n", 2371 errorByte, statusByte)); 2372 return FALSE; 2373 } 2374 2375 if(statusByte == IDE_STATUS_IDLE) { 2376 return TRUE; 2377 } 2378 2379 return FALSE; 2380 2381 } // end SetDriveParameters() 2382 2383 VOID 2384 NTAPI 2385 UniataForgetDevice( 2386 PHW_LU_EXTENSION LunExt 2387 ) 2388 { 2389 // keep only DFLAGS_HIDDEN flag 2390 LunExt->DeviceFlags &= DFLAGS_HIDDEN; 2391 LunExt->AtapiReadyWaitDelay = 0; 2392 } // end UniataForgetDevice() 2393 2394 2395 /*++ 2396 2397 Routine Description: 2398 Reset IDE controller and/or Atapi device. 2399 ->HwResetBus 2400 2401 Arguments: 2402 HwDeviceExtension - HBA miniport driver's adapter data storage 2403 2404 Return Value: 2405 Nothing. 2406 2407 2408 --*/ 2409 BOOLEAN 2410 NTAPI 2411 AtapiResetController( 2412 IN PVOID HwDeviceExtension, 2413 IN ULONG PathId 2414 ) 2415 { 2416 KdPrint2((PRINT_PREFIX "AtapiResetController(%x)\n", PathId)); 2417 return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL); 2418 } // end AtapiResetController() 2419 2420 BOOLEAN 2421 NTAPI 2422 AtapiResetController__( 2423 IN PVOID HwDeviceExtension, 2424 IN ULONG PathId, 2425 IN BOOLEAN CompleteType 2426 ) 2427 { 2428 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 2429 ULONG numberChannels = deviceExtension->NumberChannels; 2430 PHW_CHANNEL chan = NULL; 2431 ULONG i,j; 2432 ULONG MaxLuns; 2433 UCHAR statusByte; 2434 PSCSI_REQUEST_BLOCK CurSrb; 2435 ULONG ChannelCtrlFlags; 2436 UCHAR dma_status = 0; 2437 2438 ULONG slotNumber = deviceExtension->slotNumber; 2439 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber; 2440 ULONG VendorID = deviceExtension->DevID & 0xffff; 2441 #ifdef _DEBUG 2442 ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff; 2443 #endif 2444 //ULONG RevID = deviceExtension->RevID; 2445 ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK; 2446 //UCHAR tmp8; 2447 USHORT tmp16; 2448 2449 KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber)); 2450 KdPrint2((PRINT_PREFIX "simplexOnly %d, VM %x\n", deviceExtension->simplexOnly, g_opt_VirtualMachine)); 2451 2452 if(!deviceExtension->simplexOnly && (PathId != CHAN_NOT_SPECIFIED)) { 2453 // we shall reset both channels on SimplexOnly devices, 2454 // It's not worth doing so on normal controllers 2455 j = PathId; 2456 numberChannels = min(j+1, deviceExtension->NumberChannels); 2457 } else { 2458 j=0; 2459 numberChannels = deviceExtension->NumberChannels; 2460 } 2461 2462 for (; j < numberChannels; j++) { 2463 2464 KdPrint2((PRINT_PREFIX "AtapiResetController: Reset lchannel %d[%d]\n", j, deviceExtension->Channel)); 2465 chan = &(deviceExtension->chan[j]); 2466 MaxLuns = chan->NumberLuns; 2467 // Save control flags 2468 ChannelCtrlFlags = chan->ChannelCtrlFlags; 2469 KdPrint2((PRINT_PREFIX " CompleteType %#x, Luns %d, chan %#x, sptr %#x, flags %#x\n", CompleteType, MaxLuns, chan, &chan, ChannelCtrlFlags)); 2470 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2; 2471 if(CompleteType != RESET_COMPLETE_NONE) { 2472 #ifndef UNIATA_CORE 2473 while((CurSrb = UniataGetCurRequest(chan))) { 2474 2475 PHW_LU_EXTENSION LunExt; 2476 PATA_REQ AtaReq = (PATA_REQ)(CurSrb->SrbExtension); 2477 2478 i = GET_CDEV(CurSrb); 2479 KdPrint2((PRINT_PREFIX " Lun %x\n", i)); 2480 LunExt = chan->lun[i]; 2481 2482 KdPrint2((PRINT_PREFIX "AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb, chan)); 2483 if(CurSrb->Cdb[0] == SCSIOP_MECHANISM_STATUS) { 2484 KdPrint2((PRINT_PREFIX " was MechStatus\n")); 2485 2486 if(!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)) { 2487 LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED; 2488 KdPrint2((PRINT_PREFIX " set DFLAGS_CHANGER_INITED\n")); 2489 } 2490 } 2491 // Check and see if we are processing an internal srb 2492 if (AtaReq->OriginalSrb) { 2493 KdPrint2((PRINT_PREFIX " restore original SRB %#x\n", AtaReq->OriginalSrb)); 2494 AtaReq->Srb = AtaReq->OriginalSrb; 2495 CurSrb->SrbExtension = NULL; 2496 AtaReq->OriginalSrb = NULL; 2497 // NOTE: internal SRB doesn't get to SRB queue !!! 2498 CurSrb = AtaReq->Srb; 2499 } 2500 2501 // Remove current request from queue 2502 UniataRemoveRequest(chan, CurSrb); 2503 2504 // Check if request is in progress. 2505 ASSERT(AtaReq->Srb == CurSrb); 2506 if (CurSrb) { 2507 // Complete outstanding request with SRB_STATUS_BUS_RESET. 2508 UCHAR CurPathId = CurSrb->PathId; 2509 UCHAR TargetId = CurSrb->TargetId; 2510 UCHAR Lun = CurSrb->Lun; 2511 2512 CurSrb->SrbStatus = ((CompleteType == RESET_COMPLETE_ALL) ? SRB_STATUS_BUS_RESET : SRB_STATUS_ABORTED) | SRB_STATUS_AUTOSENSE_VALID; 2513 CurSrb->ScsiStatus = SCSISTAT_CHECK_CONDITION; 2514 2515 if (CurSrb->SenseInfoBuffer) { 2516 2517 PSENSE_DATA senseBuffer = (PSENSE_DATA)CurSrb->SenseInfoBuffer; 2518 KdPrint2((PRINT_PREFIX " senseBuffer %#x, chan %#x, ReqFlags %#x\n", senseBuffer, chan, AtaReq->Flags)); 2519 2520 senseBuffer->ErrorCode = 0x70; 2521 senseBuffer->Valid = 1; 2522 senseBuffer->AdditionalSenseLength = 0xb; 2523 if(CompleteType == RESET_COMPLETE_ALL) { 2524 KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n")); 2525 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION; 2526 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_BUS_RESET; 2527 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_SCSI_BUS; 2528 } else { 2529 KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n")); 2530 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND; 2531 senseBuffer->AdditionalSenseCode = 0; 2532 senseBuffer->AdditionalSenseCodeQualifier = 0; 2533 } 2534 } 2535 2536 if(!ATAPI_DEVICE(chan, i) && AtaReq->bcount && AtaReq->retry < MAX_RETRIES) { 2537 KdPrint2((PRINT_PREFIX "Save IDE retry status %d\n", AtaReq->retry)); 2538 LunExt->errLastLba = AtaReq->lba; 2539 LunExt->errBCount = AtaReq->bcount; 2540 LunExt->errRetry = AtaReq->retry+1; 2541 //KdPrint2((PRINT_PREFIX "AtaReq->Flags & REQ_FLAG_RW_MASK = %x (%x)\n", (AtaReq->Flags & REQ_FLAG_RW_MASK), REQ_FLAG_READ)); 2542 //KdPrint2((PRINT_PREFIX "ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION = %x (%x)\n", ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE, CTRFLAGS_DMA_OPERATION)); 2543 //KdPrint2((PRINT_PREFIX "g_opt_VirtualMachine = %x (%x)\n", g_opt_VirtualMachine, VM_BOCHS)); 2544 if(((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_READ) && 2545 (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) && 2546 (g_opt_VirtualMachine == VM_BOCHS)) { 2547 KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS\n")); 2548 g_opt_BochsDmaReadWorkaround = TRUE; 2549 g_opt_AtapiNoDma = TRUE; 2550 } else { 2551 KdPrint2((PRINT_PREFIX "do nothing\n")); 2552 } 2553 } else 2554 if(ATAPI_DEVICE(chan, i) && AtaReq->bcount && !AtaReq->retry) { 2555 KdPrint2((PRINT_PREFIX "Save ATAPI retry status %d\n", AtaReq->retry)); 2556 LunExt->errLastLba = AtaReq->lba; 2557 LunExt->errBCount = AtaReq->bcount; 2558 LunExt->errRetry = AtaReq->retry+1; 2559 if(((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_READ) && 2560 (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) && 2561 (g_opt_VirtualMachine == VM_BOCHS)) { 2562 KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS ATAPI\n")); 2563 //g_opt_BochsDmaReadWorkaround = TRUE; 2564 g_opt_AtapiNoDma = TRUE; 2565 } else { 2566 KdPrint2((PRINT_PREFIX "do nothing\n")); 2567 } 2568 } else { 2569 LunExt->errRetry = 0; 2570 } 2571 2572 // Clear request tracking fields. 2573 AtaReq->WordsLeft = 0; 2574 AtaReq->DataBuffer = NULL; 2575 AtaReq->TransferLength = 0; 2576 KdPrint2((PRINT_PREFIX "chan %#x\n", chan)); 2577 2578 ScsiPortNotification(RequestComplete, 2579 deviceExtension, 2580 CurSrb); 2581 2582 // Indicate ready for next request. 2583 ScsiPortNotification(NextLuRequest, 2584 deviceExtension, 2585 CurPathId, 2586 TargetId, 2587 Lun); 2588 } 2589 if(CompleteType != RESET_COMPLETE_ALL) 2590 break; 2591 } // end while() 2592 #endif //UNIATA_CORE 2593 } // end if (!CompleteType != RESET_COMPLETE_NONE) 2594 2595 // Clear expecting interrupt flag. 2596 UniataExpectChannelInterrupt(chan, FALSE); 2597 chan->RDP = FALSE; 2598 chan->ChannelCtrlFlags = ChannelCtrlFlags & CTRFLAGS_PERMANENT; 2599 InterlockedExchange(&(chan->CheckIntr), 2600 CHECK_INTR_IDLE); 2601 2602 for (i = 0; i < MaxLuns; i++) { 2603 chan->lun[i]->PowerState = 0; 2604 } 2605 // Reset controller 2606 if(ChipFlags & UNIATA_AHCI) { 2607 KdPrint2((PRINT_PREFIX " AHCI path\n")); 2608 if(UniataAhciChanImplemented(deviceExtension, j)) { 2609 #ifdef _DEBUG 2610 UniataDumpAhciPortRegs(chan); 2611 #endif 2612 AtapiDisableInterrupts(deviceExtension, j); 2613 UniataAhciReset(HwDeviceExtension, j); 2614 } else { 2615 KdPrint2((PRINT_PREFIX " skip not implemented\n")); 2616 continue; 2617 } 2618 } else { 2619 KdPrint2((PRINT_PREFIX " ATA path, chan %#x\n", chan)); 2620 KdPrint2((PRINT_PREFIX " disable intr (0)\n")); 2621 AtapiDisableInterrupts(deviceExtension, j); 2622 KdPrint2((PRINT_PREFIX " done\n")); 2623 switch(VendorID) { 2624 case ATA_INTEL_ID: { 2625 ULONG mask; 2626 ULONG pshift; 2627 ULONG timeout; 2628 if(!(ChipFlags & UNIATA_SATA)) { 2629 goto default_reset; 2630 } 2631 if(!UniataIsSATARangeAvailable(deviceExtension, j)) { 2632 goto default_reset; 2633 } 2634 2635 #if 0 2636 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */ 2637 if(ChipFlags & UNIATA_AHCI) { 2638 mask = 0x0005 << j; 2639 } else { 2640 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */ 2641 GetPciConfig1(0x90, tmp8); 2642 if(tmp8 & 0x04) { 2643 mask = 0x0003; 2644 } else { 2645 mask = 0x0001 << j; 2646 } 2647 } 2648 #else 2649 mask = 1 << chan->lun[0]->SATA_lun_map; 2650 if (MaxLuns > 1) { 2651 mask |= (1 << chan->lun[1]->SATA_lun_map); 2652 } 2653 #endif 2654 ChangePciConfig2(0x92, a & ~mask); 2655 AtapiStallExecution(10); 2656 ChangePciConfig2(0x92, a | mask); 2657 timeout = 100; 2658 2659 /* Wait up to 1 sec for "connect well". */ 2660 if (ChipFlags & (I6CH | I6CH2)) { 2661 pshift = 8; 2662 } else { 2663 pshift = 4; 2664 } 2665 while (timeout--) { 2666 GetPciConfig2(0x92, tmp16); 2667 if (((tmp16 >> pshift) & mask) == mask) { 2668 GetBaseStatus(chan, statusByte); 2669 if(statusByte != IDE_STATUS_WRONG) { 2670 break; 2671 } 2672 } 2673 AtapiStallExecution(10000); 2674 } 2675 break; } 2676 case ATA_SIS_ID: { 2677 KdPrint2((PRINT_PREFIX " SIS\n")); 2678 if(!(ChipFlags & UNIATA_SATA)) 2679 goto default_reset; 2680 break; } 2681 #if 0 2682 case ATA_NVIDIA_ID: { 2683 KdPrint2((PRINT_PREFIX " nVidia\n")); 2684 if(!(ChipFlags & UNIATA_SATA)) 2685 goto default_reset; 2686 break; } 2687 #else 2688 case ATA_NVIDIA_ID: { 2689 ULONG offs; 2690 ULONG Channel = deviceExtension->Channel + j; 2691 KdPrint2((PRINT_PREFIX " nVidia\n")); 2692 if(!(ChipFlags & UNIATA_SATA)) { 2693 goto default_reset; 2694 } 2695 offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010; 2696 2697 KdPrint2((PRINT_PREFIX " disable Phy intr, offs %#x, c %u\n", offs, Channel)); 2698 /* disable device and PHY state change interrupts */ 2699 if(ChipFlags & NVQ) { 2700 KdPrint2((PRINT_PREFIX " NVQ, 32bits reg\n")); 2701 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4, 2702 AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) & ((~(ULONG)0x0000000d) << (!Channel*16)) ); 2703 } else { 2704 AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1, 2705 AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) & ((~(UCHAR)0x0d) << (!Channel*4)) ); 2706 } 2707 tmp16 = UniataSataPhyEnable(HwDeviceExtension, j, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE); 2708 2709 KdPrint2((PRINT_PREFIX " enable Phy intr, offs %#x\n", offs)); 2710 /* enable device and PHY state change interrupts */ 2711 if(ChipFlags & NVQ) { 2712 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4, 2713 AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) | (((ULONG)0x0000000d) << (!Channel*16)) ); 2714 } else { 2715 AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1, 2716 AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) | (((UCHAR)0x0d) << (!Channel*4)) ); 2717 } 2718 2719 KdPrint2((PRINT_PREFIX " dev status %#x\n", tmp16)); 2720 if(tmp16 != IDE_STATUS_WRONG) { 2721 goto default_reset; 2722 } 2723 break; } 2724 #endif //0 2725 case ATA_SILICON_IMAGE_ID: { 2726 ULONG offset; 2727 ULONG Channel = deviceExtension->Channel + j; 2728 if(!(ChipFlags & UNIATA_SATA)) 2729 goto default_reset; 2730 offset = ((Channel & 1) << 7) + ((Channel & 2) << 8); 2731 /* disable PHY state change interrupt */ 2732 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + offset, 0); 2733 2734 UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0); 2735 2736 /* reset controller part for this channel */ 2737 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48, 2738 AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) | (0xc0 >> Channel)); 2739 AtapiStallExecution(1000); 2740 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48, 2741 AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) & ~(0xc0 >> Channel)); 2742 2743 2744 break; } 2745 case ATA_PROMISE_ID: { 2746 break; } 2747 default: 2748 if(ChipFlags & UNIATA_SATA) { 2749 KdPrint2((PRINT_PREFIX " SATA generic reset\n")); 2750 UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0); 2751 } 2752 default_reset: 2753 /* 2754 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS | 2755 IDE_DC_RESET_CONTROLLER ); 2756 chan->last_devsel = -1; 2757 KdPrint2((PRINT_PREFIX " wait a little\n")); 2758 AtapiStallExecution(10000); 2759 // Disable interrupts 2760 KdPrint2((PRINT_PREFIX " disable intr\n")); 2761 AtapiDisableInterrupts(deviceExtension, j); 2762 AtapiStallExecution(100); 2763 KdPrint2((PRINT_PREFIX " re-enable intr\n")); 2764 AtapiEnableInterrupts(deviceExtension, j); 2765 KdPrint2((PRINT_PREFIX " wait a little (2)\n")); 2766 AtapiStallExecution(100000); 2767 */ 2768 AtapiHardReset(chan, TRUE, 100000); 2769 KdPrint2((PRINT_PREFIX " disable intr\n")); 2770 AtapiDisableInterrupts(deviceExtension, j); 2771 AtapiStallExecution(100); 2772 KdPrint2((PRINT_PREFIX " re-enable intr\n")); 2773 AtapiEnableInterrupts(deviceExtension, j); 2774 KdPrint2((PRINT_PREFIX " done\n")); 2775 2776 break; 2777 } // end switch() 2778 2779 //if(!(ChipFlags & UNIATA_SATA)) {} 2780 if(!UniataIsSATARangeAvailable(deviceExtension, j)) { 2781 // Reset DMA engine if active 2782 KdPrint2((PRINT_PREFIX " check DMA engine\n")); 2783 dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel); 2784 KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status)); 2785 if((ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) || 2786 (dma_status & BM_STATUS_INTR)) { 2787 AtapiDmaDone(HwDeviceExtension, 0, j, NULL); 2788 } 2789 } 2790 } // ATA vs AHCI 2791 2792 // all these shall be performed inside AtapiHwInitialize__() ? 2793 #if 1 2794 KdPrint2((PRINT_PREFIX " process connected devices 0 - %d\n", MaxLuns-1)); 2795 // Do special processing for ATAPI and IDE disk devices. 2796 for (i = 0; i < MaxLuns; i++) { 2797 2798 // Check if device present. 2799 KdPrint2((PRINT_PREFIX " Chan %#x\n", chan)); 2800 KdPrint2((PRINT_PREFIX " Lun %#x\n", i)); 2801 KdPrint2((PRINT_PREFIX " Lun ptr %#x\n", chan->lun[i])); 2802 if (!(chan->lun[i]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 2803 if(ChipFlags & UNIATA_AHCI) { 2804 // everything is done in UniataAhciReset() 2805 KdPrint2((PRINT_PREFIX " device have gone\n")); 2806 continue; 2807 } 2808 #ifdef NAVO_TEST 2809 continue; 2810 #else //NAVO_TEST 2811 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE)) 2812 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) { 2813 continue; 2814 } 2815 if(!CheckDevice(HwDeviceExtension, j, i, TRUE)) { 2816 continue; 2817 } 2818 } else { 2819 if(ChipFlags & UNIATA_AHCI) { 2820 // everything is done in UniataAhciReset() 2821 KdPrint2((PRINT_PREFIX " found some device\n")); 2822 2823 if(!IssueIdentify(HwDeviceExtension, 2824 i, j, 2825 ATAPI_DEVICE(chan, i) ? 2826 IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY, 2827 FALSE)) { 2828 KdPrint2((PRINT_PREFIX " identify failed !\n")); 2829 UniataForgetDevice(chan->lun[i]); 2830 } 2831 continue; 2832 } 2833 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) { 2834 KdPrint2((PRINT_PREFIX " device have gone\n")); 2835 UniataForgetDevice(chan->lun[i]); 2836 } 2837 #endif //NAVO_TEST 2838 } 2839 2840 SelectDrive(chan, i); 2841 AtapiStallExecution(10); 2842 statusByte = WaitOnBusyLong(chan); 2843 statusByte = UniataIsIdle(deviceExtension, statusByte); 2844 if(statusByte == IDE_STATUS_WRONG) { 2845 KdPrint2((PRINT_PREFIX 2846 "no drive, status %#x\n", 2847 statusByte)); 2848 UniataForgetDevice(chan->lun[i]); 2849 } else 2850 // Check for ATAPI disk. 2851 if (ATAPI_DEVICE(chan, i)) { 2852 // Issue soft reset and issue identify. 2853 GetStatus(chan, statusByte); 2854 KdPrint2((PRINT_PREFIX "AtapiResetController: Status before Atapi reset (%#x).\n", 2855 statusByte)); 2856 2857 AtapiDisableInterrupts(deviceExtension, j); 2858 AtapiSoftReset(chan, i); 2859 AtapiEnableInterrupts(deviceExtension, j); 2860 2861 GetStatus(chan, statusByte); 2862 2863 if(statusByte != IDE_STATUS_SUCCESS) { 2864 ULONG k; 2865 k = UniataAnybodyHome(deviceExtension, j, i); 2866 if(k == ATA_AT_HOME_HDD) { 2867 // device reset in progress, perform additional wait 2868 KdPrint2((PRINT_PREFIX " long reset, wait up to 4.5 s\n")); 2869 k = 30 * 1000; 2870 while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) && 2871 k--) 2872 { 2873 AtapiStallExecution(150); 2874 } 2875 KdPrint2((PRINT_PREFIX " exit after %u loops\n", k)); 2876 GetStatus(chan, statusByte); 2877 } 2878 } 2879 if(statusByte == IDE_STATUS_SUCCESS) { 2880 2881 IssueIdentify(HwDeviceExtension, 2882 i, j, 2883 IDE_COMMAND_ATAPI_IDENTIFY, FALSE); 2884 } else { 2885 2886 KdPrint2((PRINT_PREFIX 2887 "AtapiResetController: Status after soft reset %#x\n", 2888 statusByte)); 2889 } 2890 GetBaseStatus(chan, statusByte); 2891 2892 } else { 2893 // Issue identify and reinit after channel reset. 2894 2895 if (statusByte != IDE_STATUS_IDLE && 2896 statusByte != IDE_STATUS_SUCCESS && 2897 statusByte != IDE_STATUS_DRDY) { 2898 // result2 = FALSE; 2899 KdPrint2((PRINT_PREFIX "AtapiResetController: IdeHardReset failed\n")); 2900 } else 2901 if(!IssueIdentify(HwDeviceExtension, 2902 i, j, 2903 IDE_COMMAND_IDENTIFY, FALSE)) { 2904 // result2 = FALSE; 2905 KdPrint2((PRINT_PREFIX "AtapiResetController: IDE IssueIdentify failed\n")); 2906 } else 2907 // Set disk geometry parameters. 2908 if (!SetDriveParameters(HwDeviceExtension, i, j)) { 2909 KdPrint2((PRINT_PREFIX "AtapiResetController: SetDriveParameters failed\n")); 2910 } 2911 GetBaseStatus(chan, statusByte); 2912 } 2913 // force DMA mode reinit 2914 KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n")); 2915 chan->lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA; 2916 } 2917 #endif //0 2918 2919 // Enable interrupts, note, we can have here recursive disable 2920 AtapiStallExecution(10); 2921 KdPrint2((PRINT_PREFIX "AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n", 2922 j, 2923 chan->DisableIntr)); 2924 AtapiEnableInterrupts(deviceExtension, j); 2925 2926 // Call the HwInitialize routine to setup multi-block. 2927 AtapiHwInitialize__(deviceExtension, j); 2928 } // for(channel) 2929 ScsiPortNotification(NextRequest, deviceExtension, NULL); 2930 2931 return TRUE; 2932 2933 } // end AtapiResetController__() 2934 2935 2936 /*++ 2937 2938 Routine Description: 2939 This routine maps ATAPI and IDE errors to specific SRB statuses. 2940 2941 Arguments: 2942 HwDeviceExtension - HBA miniport driver's adapter data storage 2943 Srb - IO request packet 2944 2945 Return Value: 2946 SRB status 2947 2948 --*/ 2949 ULONG 2950 NTAPI 2951 MapError( 2952 IN PVOID HwDeviceExtension, 2953 IN PSCSI_REQUEST_BLOCK Srb 2954 ) 2955 { 2956 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 2957 ULONG lChannel = GET_CHANNEL(Srb); 2958 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 2959 // ULONG i; 2960 UCHAR errorByte = 0; 2961 UCHAR srbStatus = SRB_STATUS_SUCCESS; 2962 UCHAR scsiStatus; 2963 ULONG DeviceNumber = GET_CDEV(Srb); 2964 PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber]; 2965 2966 // Read the error register. 2967 2968 if(deviceExtension->HwFlags & UNIATA_AHCI) { 2969 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 2970 if(AtaReq) { 2971 errorByte = AtaReq->ahci.in_error; 2972 } else { 2973 } 2974 } else { 2975 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 2976 } 2977 KdPrint2((PRINT_PREFIX 2978 "MapError: Error register is %#x\n", 2979 errorByte)); 2980 2981 if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { 2982 2983 switch (errorByte >> 4) { 2984 case SCSI_SENSE_NO_SENSE: 2985 2986 KdPrint2((PRINT_PREFIX 2987 "ATAPI: No sense information\n")); 2988 scsiStatus = SCSISTAT_CHECK_CONDITION; 2989 srbStatus = SRB_STATUS_ERROR; 2990 break; 2991 2992 case SCSI_SENSE_RECOVERED_ERROR: 2993 2994 KdPrint2((PRINT_PREFIX 2995 "ATAPI: Recovered error\n")); 2996 scsiStatus = 0; 2997 srbStatus = SRB_STATUS_SUCCESS; 2998 break; 2999 3000 case SCSI_SENSE_NOT_READY: 3001 3002 KdPrint2((PRINT_PREFIX 3003 "ATAPI: Device not ready\n")); 3004 scsiStatus = SCSISTAT_CHECK_CONDITION; 3005 srbStatus = SRB_STATUS_ERROR; 3006 break; 3007 3008 case SCSI_SENSE_MEDIUM_ERROR: 3009 3010 KdPrint2((PRINT_PREFIX 3011 "ATAPI: Media error\n")); 3012 scsiStatus = SCSISTAT_CHECK_CONDITION; 3013 srbStatus = SRB_STATUS_ERROR; 3014 break; 3015 3016 case SCSI_SENSE_HARDWARE_ERROR: 3017 3018 KdPrint2((PRINT_PREFIX 3019 "ATAPI: Hardware error\n")); 3020 scsiStatus = SCSISTAT_CHECK_CONDITION; 3021 srbStatus = SRB_STATUS_ERROR; 3022 break; 3023 3024 case SCSI_SENSE_ILLEGAL_REQUEST: 3025 3026 KdPrint2((PRINT_PREFIX 3027 "ATAPI: Illegal request\n")); 3028 scsiStatus = SCSISTAT_CHECK_CONDITION; 3029 srbStatus = SRB_STATUS_ERROR; 3030 break; 3031 3032 case SCSI_SENSE_UNIT_ATTENTION: 3033 3034 KdPrint2((PRINT_PREFIX 3035 "ATAPI: Unit attention\n")); 3036 scsiStatus = SCSISTAT_CHECK_CONDITION; 3037 srbStatus = SRB_STATUS_ERROR; 3038 break; 3039 3040 case SCSI_SENSE_DATA_PROTECT: 3041 3042 KdPrint2((PRINT_PREFIX 3043 "ATAPI: Data protect\n")); 3044 scsiStatus = SCSISTAT_CHECK_CONDITION; 3045 srbStatus = SRB_STATUS_ERROR; 3046 break; 3047 3048 case SCSI_SENSE_BLANK_CHECK: 3049 3050 KdPrint2((PRINT_PREFIX 3051 "ATAPI: Blank check\n")); 3052 scsiStatus = SCSISTAT_CHECK_CONDITION; 3053 srbStatus = SRB_STATUS_ERROR; 3054 break; 3055 3056 case SCSI_SENSE_ABORTED_COMMAND: 3057 KdPrint2((PRINT_PREFIX 3058 "Atapi: Command Aborted\n")); 3059 scsiStatus = SCSISTAT_CHECK_CONDITION; 3060 srbStatus = SRB_STATUS_ERROR; 3061 break; 3062 3063 default: 3064 3065 KdPrint2((PRINT_PREFIX 3066 "ATAPI: Invalid sense information\n")); 3067 scsiStatus = 0; 3068 srbStatus = SRB_STATUS_ERROR; 3069 break; 3070 } 3071 3072 } else { 3073 3074 scsiStatus = 0; 3075 3076 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE. 3077 chan->ReturningMediaStatus = errorByte; 3078 3079 if (errorByte & IDE_ERROR_MEDIA_CHANGE_REQ) { 3080 KdPrint2((PRINT_PREFIX 3081 "IDE: Media change\n")); 3082 scsiStatus = SCSISTAT_CHECK_CONDITION; 3083 srbStatus = SRB_STATUS_ERROR; 3084 3085 if (Srb->SenseInfoBuffer) { 3086 3087 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 3088 3089 senseBuffer->ErrorCode = 0x70; 3090 senseBuffer->Valid = 1; 3091 senseBuffer->AdditionalSenseLength = 0xb; 3092 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION; 3093 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED; 3094 senseBuffer->AdditionalSenseCodeQualifier = 0; 3095 3096 srbStatus |= SRB_STATUS_AUTOSENSE_VALID; 3097 } 3098 3099 } else if (errorByte & IDE_ERROR_COMMAND_ABORTED) { 3100 KdPrint2((PRINT_PREFIX 3101 "IDE: Command abort\n")); 3102 srbStatus = SRB_STATUS_ABORTED; 3103 scsiStatus = SCSISTAT_CHECK_CONDITION; 3104 3105 if (Srb->SenseInfoBuffer) { 3106 3107 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 3108 3109 senseBuffer->ErrorCode = 0x70; 3110 senseBuffer->Valid = 1; 3111 senseBuffer->AdditionalSenseLength = 0xb; 3112 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND; 3113 senseBuffer->AdditionalSenseCode = 0; 3114 senseBuffer->AdditionalSenseCodeQualifier = 0; 3115 3116 srbStatus |= SRB_STATUS_AUTOSENSE_VALID; 3117 } 3118 3119 LunExt->ErrorCount++; 3120 3121 } else if (errorByte & IDE_ERROR_END_OF_MEDIA) { 3122 3123 KdPrint2((PRINT_PREFIX 3124 "IDE: End of media\n")); 3125 scsiStatus = SCSISTAT_CHECK_CONDITION; 3126 srbStatus = SRB_STATUS_ERROR; 3127 3128 if (Srb->SenseInfoBuffer) { 3129 3130 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 3131 3132 senseBuffer->ErrorCode = 0x70; 3133 senseBuffer->Valid = 1; 3134 senseBuffer->AdditionalSenseLength = 0xb; 3135 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION; 3136 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIA_STATE; 3137 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_END_OF_MEDIUM; 3138 senseBuffer->EndOfMedia = 1; 3139 3140 srbStatus |= SRB_STATUS_AUTOSENSE_VALID; 3141 } 3142 3143 if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){ 3144 LunExt->ErrorCount++; 3145 } 3146 3147 } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) { 3148 3149 KdPrint2((PRINT_PREFIX 3150 "IDE: Illegal length\n")); 3151 srbStatus = SRB_STATUS_INVALID_REQUEST; 3152 3153 if (Srb->SenseInfoBuffer) { 3154 3155 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 3156 3157 senseBuffer->ErrorCode = 0x70; 3158 senseBuffer->Valid = 1; 3159 senseBuffer->AdditionalSenseLength = 0xb; 3160 senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST; 3161 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_VALUE; 3162 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_PARAM_INVALID_VALUE; 3163 senseBuffer->IncorrectLength = 1; 3164 3165 srbStatus |= SRB_STATUS_AUTOSENSE_VALID; 3166 } 3167 3168 } else if (errorByte & IDE_ERROR_BAD_BLOCK) { 3169 3170 KdPrint2((PRINT_PREFIX 3171 "IDE: Bad block\n")); 3172 srbStatus = SRB_STATUS_ERROR; 3173 scsiStatus = SCSISTAT_CHECK_CONDITION; 3174 if (Srb->SenseInfoBuffer) { 3175 3176 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 3177 3178 senseBuffer->ErrorCode = 0x70; 3179 senseBuffer->Valid = 1; 3180 senseBuffer->AdditionalSenseLength = 0xb; 3181 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR; 3182 senseBuffer->AdditionalSenseCode = 0; 3183 senseBuffer->AdditionalSenseCodeQualifier = 0; 3184 3185 srbStatus |= SRB_STATUS_AUTOSENSE_VALID; 3186 } 3187 3188 } else if (errorByte & IDE_ERROR_ID_NOT_FOUND) { 3189 3190 KdPrint2((PRINT_PREFIX 3191 "IDE: Id not found\n")); 3192 srbStatus = SRB_STATUS_ERROR; 3193 scsiStatus = SCSISTAT_CHECK_CONDITION; 3194 3195 if (Srb->SenseInfoBuffer) { 3196 3197 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 3198 3199 senseBuffer->ErrorCode = 0x70; 3200 senseBuffer->Valid = 1; 3201 senseBuffer->AdditionalSenseLength = 0xb; 3202 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR; 3203 senseBuffer->AdditionalSenseCode = 0; 3204 senseBuffer->AdditionalSenseCodeQualifier = 0; 3205 3206 srbStatus |= SRB_STATUS_AUTOSENSE_VALID; 3207 } 3208 3209 LunExt->ErrorCount++; 3210 3211 } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) { 3212 3213 KdPrint2((PRINT_PREFIX 3214 "IDE: Media change\n")); 3215 scsiStatus = SCSISTAT_CHECK_CONDITION; 3216 srbStatus = SRB_STATUS_ERROR; 3217 3218 if (Srb->SenseInfoBuffer) { 3219 3220 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 3221 3222 senseBuffer->ErrorCode = 0x70; 3223 senseBuffer->Valid = 1; 3224 senseBuffer->AdditionalSenseLength = 0xb; 3225 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION; 3226 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED; 3227 senseBuffer->AdditionalSenseCodeQualifier = 0; 3228 3229 srbStatus |= SRB_STATUS_AUTOSENSE_VALID; 3230 } 3231 3232 } else if (errorByte & IDE_ERROR_DATA_ERROR) { 3233 3234 KdPrint2((PRINT_PREFIX 3235 "IDE: Data error\n")); 3236 scsiStatus = SCSISTAT_CHECK_CONDITION; 3237 srbStatus = SRB_STATUS_ERROR; 3238 3239 if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){ 3240 LunExt->ErrorCount++; 3241 } 3242 3243 // Build sense buffer 3244 if (Srb->SenseInfoBuffer) { 3245 3246 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 3247 3248 senseBuffer->ErrorCode = 0x70; 3249 senseBuffer->Valid = 1; 3250 senseBuffer->AdditionalSenseLength = 0xb; 3251 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR; 3252 senseBuffer->AdditionalSenseCode = 0; 3253 senseBuffer->AdditionalSenseCodeQualifier = 0; 3254 3255 srbStatus |= SRB_STATUS_AUTOSENSE_VALID; 3256 } 3257 } 3258 3259 if (LunExt->ErrorCount >= MAX_ERRORS) { 3260 // deviceExtension->DWordIO = FALSE; 3261 3262 KdPrint2((PRINT_PREFIX 3263 "MapError: ErrorCount >= MAX_ERRORS\n")); 3264 3265 LunExt->DeviceFlags &= ~DFLAGS_DWORDIO_ENABLED; 3266 LunExt->MaximumBlockXfer = 0; 3267 BrutePoint(); 3268 3269 KdPrint2((PRINT_PREFIX 3270 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n")); 3271 3272 // Log the error. 3273 KdPrint2((PRINT_PREFIX 3274 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n", 3275 HwDeviceExtension, 3276 Srb, 3277 Srb->PathId, 3278 Srb->TargetId, 3279 Srb->Lun, 3280 SP_BAD_FW_WARNING, 3281 4 3282 )); 3283 ScsiPortLogError( HwDeviceExtension, 3284 Srb, 3285 Srb->PathId, 3286 Srb->TargetId, 3287 Srb->Lun, 3288 SP_BAD_FW_WARNING, 3289 4); 3290 3291 // Reprogram to not use Multi-sector. 3292 UCHAR statusByte; 3293 3294 if (LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT && 3295 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) { 3296 3297 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY); 3298 3299 // Check for errors. Reset the value to 0 (disable MultiBlock) if the 3300 // command was aborted. 3301 if (statusByte & IDE_STATUS_ERROR) { 3302 3303 // Read the error register. 3304 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 3305 3306 KdPrint2((PRINT_PREFIX "MapError: Error setting multiple mode. Status %#x, error byte %#x\n", 3307 statusByte, 3308 errorByte)); 3309 3310 // Adjust the devExt. value, if necessary. 3311 LunExt->MaximumBlockXfer = 0; 3312 BrutePoint(); 3313 3314 } 3315 } 3316 } 3317 } 3318 3319 // Set SCSI status to indicate a check condition. 3320 Srb->ScsiStatus = scsiStatus; 3321 3322 return srbStatus; 3323 3324 } // end MapError() 3325 3326 3327 /*++ 3328 3329 Routine Description: 3330 3331 Arguments: 3332 HwDeviceExtension - HBA miniport driver's adapter data storage 3333 ->HwInitialize 3334 3335 Return Value: 3336 TRUE - if initialization successful. 3337 FALSE - if initialization unsuccessful. 3338 3339 --*/ 3340 BOOLEAN 3341 NTAPI 3342 AtapiHwInitialize( 3343 IN PVOID HwDeviceExtension 3344 ) 3345 { 3346 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 3347 ULONG numberChannels = deviceExtension->NumberChannels; 3348 ULONG c; 3349 3350 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base)\n")); 3351 3352 if(WinVer_WDM_Model) { 3353 AtapiResetController__(HwDeviceExtension, CHAN_NOT_SPECIFIED, RESET_COMPLETE_ALL); 3354 } 3355 if(deviceExtension->MasterDev) { 3356 KdPrint2((PRINT_PREFIX " mark chan %d of master controller [%x] as inited\n", 3357 deviceExtension->Channel, deviceExtension->DevIndex)); 3358 BMList[deviceExtension->DevIndex].ChanInitOk |= 0x01 << deviceExtension->Channel; 3359 } 3360 3361 /* do extra chipset specific setups */ 3362 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED); 3363 /* 3364 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) { 3365 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n")); 3366 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE; 3367 } 3368 */ 3369 for (c = 0; c < numberChannels; c++) { 3370 AtapiHwInitialize__(deviceExtension, c); 3371 } 3372 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base) done\n")); 3373 return TRUE; 3374 } // end AtapiHwInitialize() 3375 3376 VOID 3377 NTAPI 3378 AtapiHwInitialize__( 3379 IN PHW_DEVICE_EXTENSION deviceExtension, 3380 IN ULONG lChannel 3381 ) 3382 { 3383 ULONG i; 3384 UCHAR statusByte, errorByte; 3385 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 3386 PHW_LU_EXTENSION LunExt; 3387 // ULONG tmp32; 3388 ULONG PreferedMode = 0xffffffff; 3389 3390 if((deviceExtension->HwFlags & UNIATA_AHCI) && 3391 !UniataAhciChanImplemented(deviceExtension, lChannel)) { 3392 return; 3393 } 3394 3395 AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel); 3396 FindDevices(deviceExtension, 0, lChannel); 3397 3398 for (i = 0; i < chan->NumberLuns; i++) { 3399 3400 KdPrint3((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel, i)); 3401 3402 LunExt = chan->lun[i]; 3403 // skip empty slots 3404 if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 3405 continue; 3406 } 3407 3408 AtapiDisableInterrupts(deviceExtension, lChannel); 3409 AtapiStallExecution(1); 3410 3411 if (!(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) { 3412 3413 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: IDE branch\n")); 3414 // Enable media status notification 3415 IdeMediaStatus(TRUE,deviceExtension,lChannel,(UCHAR)i); 3416 3417 // If supported, setup Multi-block transfers. 3418 statusByte = AtaCommand(deviceExtension, i, lChannel, 3419 IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 3420 LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY); 3421 3422 // Check for errors. Reset the value to 0 (disable MultiBlock) if the 3423 // command was aborted. 3424 if (statusByte & IDE_STATUS_ERROR) { 3425 3426 // Read the error register. 3427 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 3428 3429 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n", 3430 statusByte, 3431 errorByte)); 3432 3433 statusByte = AtaCommand(deviceExtension, i, lChannel, 3434 IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 3435 0, 0, ATA_WAIT_BASE_READY); 3436 3437 if (statusByte & IDE_STATUS_ERROR) { 3438 // Read the error register. 3439 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 3440 3441 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n", 3442 statusByte, 3443 errorByte)); 3444 } 3445 // Adjust the devExt. value, if necessary. 3446 LunExt->MaximumBlockXfer = 0; 3447 3448 } else { 3449 KdPrint2((PRINT_PREFIX 3450 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n", 3451 i, 3452 LunExt->MaximumBlockXfer)); 3453 } 3454 3455 if(LunExt->IdentifyData.MajorRevision) { 3456 3457 if(LunExt->opt_ReadCacheEnable) { 3458 KdPrint2((PRINT_PREFIX " Try Enable Read Cache\n")); 3459 // If supported, setup read/write cacheing 3460 statusByte = AtaCommand(deviceExtension, i, lChannel, 3461 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 3462 0, ATA_C_F_ENAB_RCACHE, ATA_WAIT_BASE_READY); 3463 3464 // Check for errors. 3465 if (statusByte & IDE_STATUS_ERROR) { 3466 KdPrint2((PRINT_PREFIX 3467 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n", 3468 i)); 3469 LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED; 3470 } else { 3471 LunExt->DeviceFlags |= DFLAGS_RCACHE_ENABLED; 3472 } 3473 } else { 3474 KdPrint2((PRINT_PREFIX " Disable Read Cache\n")); 3475 statusByte = AtaCommand(deviceExtension, i, lChannel, 3476 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 3477 0, ATA_C_F_DIS_RCACHE, ATA_WAIT_BASE_READY); 3478 LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED; 3479 } 3480 if(LunExt->IdentifyData.FeaturesSupport.WriteCache) { 3481 if(LunExt->opt_WriteCacheEnable) { 3482 KdPrint2((PRINT_PREFIX " Try Enable Write Cache\n")); 3483 // If supported & allowed, setup write cacheing 3484 statusByte = AtaCommand(deviceExtension, i, lChannel, 3485 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 3486 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY); 3487 // Check for errors. 3488 if (statusByte & IDE_STATUS_ERROR) { 3489 KdPrint2((PRINT_PREFIX 3490 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n", 3491 i)); 3492 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; 3493 } else { 3494 LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED; 3495 } 3496 } else { 3497 KdPrint2((PRINT_PREFIX " Disable Write Cache\n")); 3498 statusByte = AtaCommand(deviceExtension, i, lChannel, 3499 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 3500 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY); 3501 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; 3502 } 3503 } 3504 3505 if(/*LunExt->IdentifyData.FeaturesSupport.PowerMngt ||*/ 3506 LunExt->IdentifyData.FeaturesSupport.APM) { 3507 3508 if(LunExt->opt_AdvPowerMode) { 3509 KdPrint2((PRINT_PREFIX " Try Enable Adv. Power Mgmt\n")); 3510 // setup APM 3511 statusByte = AtaCommand(deviceExtension, i, lChannel, 3512 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 3513 LunExt->opt_AdvPowerMode, ATA_C_F_ENAB_APM, ATA_WAIT_BASE_READY); 3514 // Check for errors. 3515 if (statusByte & IDE_STATUS_ERROR) { 3516 KdPrint2((PRINT_PREFIX 3517 "AtapiHwInitialize: Enable APM on Device %d failed\n", 3518 i)); 3519 } 3520 } else { 3521 KdPrint2((PRINT_PREFIX " Disable Adv. Power Mgmt\n")); 3522 statusByte = AtaCommand(deviceExtension, i, lChannel, 3523 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 3524 0, ATA_C_F_DIS_APM, ATA_WAIT_BASE_READY); 3525 } 3526 } 3527 if(LunExt->IdentifyData.FeaturesSupport.AutoAcoustic) { 3528 if(LunExt->opt_AcousticMode) { 3529 KdPrint2((PRINT_PREFIX " Try Enable Acoustic Mgmt\n")); 3530 // setup acoustic mgmt 3531 statusByte = AtaCommand(deviceExtension, i, lChannel, 3532 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 3533 LunExt->opt_AcousticMode, ATA_C_F_ENAB_ACOUSTIC, ATA_WAIT_BASE_READY); 3534 // Check for errors. 3535 if (statusByte & IDE_STATUS_ERROR) { 3536 KdPrint2((PRINT_PREFIX 3537 "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n", 3538 i)); 3539 } 3540 } else { 3541 KdPrint2((PRINT_PREFIX " Disable Acoustic Mgmt\n")); 3542 statusByte = AtaCommand(deviceExtension, i, lChannel, 3543 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 3544 0, ATA_C_F_DIS_ACOUSTIC, ATA_WAIT_BASE_READY); 3545 } 3546 } 3547 if(LunExt->IdentifyData.FeaturesSupport.Standby) { 3548 KdPrint2((PRINT_PREFIX " Try init standby timer: %d\n")); 3549 // setup standby timer 3550 statusByte = AtaCommand(deviceExtension, i, lChannel, 3551 IDE_COMMAND_IDLE, 0, 0, 0, 3552 LunExt->opt_StandbyTimer, 0, ATA_WAIT_BASE_READY); 3553 // Check for errors. 3554 if (statusByte & IDE_STATUS_ERROR) { 3555 KdPrint2((PRINT_PREFIX 3556 "AtapiHwInitialize: standby timer on Device %d failed\n", 3557 i)); 3558 } 3559 } 3560 } 3561 3562 } else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){ 3563 3564 ULONG j; 3565 //BOOLEAN isSanyo = FALSE; 3566 CCHAR vendorId[26]; 3567 3568 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n")); 3569 3570 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc. 3571 for (j = 0; j < 26; j += 2) { 3572 3573 // Build a buffer based on the identify data. 3574 MOV_DW_SWP(vendorId[j], ((PUCHAR)LunExt->IdentifyData.ModelNumber)[j]); 3575 } 3576 3577 if (!AtapiStringCmp (vendorId, "CD-ROM CDR", 11)) { 3578 3579 // Inquiry string for older model had a '-', newer is '_' 3580 if (vendorId[12] == 'C') { 3581 3582 // Torisan changer. Set the bit. This will be used in several places 3583 // acting like 1) a multi-lun device and 2) building the 'special' TUR's. 3584 LunExt->DeviceFlags |= (DFLAGS_CHANGER_INITED | DFLAGS_SANYO_ATAPI_CHANGER); 3585 LunExt->DiscsPresent = 3; 3586 //isSanyo = TRUE; 3587 } 3588 } 3589 } 3590 3591 PreferedMode = LunExt->opt_MaxTransferMode; 3592 if((PreferedMode == 0xffffffff) || (PreferedMode > chan->MaxTransferMode)) { 3593 KdPrint2((PRINT_PREFIX "MaxTransferMode (overriden): %#x\n", chan->MaxTransferMode)); 3594 PreferedMode = chan->MaxTransferMode; 3595 } 3596 3597 if(LunExt->opt_PreferedTransferMode != 0xffffffff) { 3598 KdPrint2((PRINT_PREFIX "PreferedTransferMode: %#x\n", PreferedMode)); 3599 PreferedMode = min(LunExt->opt_PreferedTransferMode, PreferedMode); 3600 } 3601 3602 KdPrint2((PRINT_PREFIX " try mode %#x\n", PreferedMode)); 3603 LunExt->LimitedTransferMode = 3604 LunExt->TransferMode = 3605 (CHAR)PreferedMode; 3606 3607 AtapiDmaInit__(deviceExtension, LunExt); 3608 3609 LunExt->LimitedTransferMode = 3610 LunExt->TransferMode; 3611 KdPrint2((PRINT_PREFIX "Using %#x mode\n", LunExt->TransferMode)); 3612 3613 // We need to get our device ready for action before 3614 // returning from this function 3615 3616 // According to the atapi spec 2.5 or 2.6, an atapi device 3617 // clears its status BSY bit when it is ready for atapi commands. 3618 // However, some devices (Panasonic SQ-TC500N) are still 3619 // not ready even when the status BSY is clear. They don't react 3620 // to atapi commands. 3621 // 3622 // Since there is really no other indication that tells us 3623 // the drive is really ready for action. We are going to check BSY 3624 // is clear and then just wait for an arbitrary amount of time! 3625 // 3626 if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { 3627 ULONG waitCount; 3628 3629 // have to get out of the loop sometime! 3630 // 10000 * 100us = 1000,000us = 1000ms = 1s 3631 waitCount = 10000; 3632 GetStatus(chan, statusByte); 3633 if(statusByte == IDE_STATUS_WRONG) { 3634 waitCount = 0; 3635 } 3636 while ((statusByte & IDE_STATUS_BUSY) && waitCount) { 3637 3638 KdPrint2((PRINT_PREFIX "Wait for ATAPI (status %x)\n", statusByte)); 3639 // Wait for Busy to drop. 3640 AtapiStallExecution(100); 3641 GetStatus(chan, statusByte); 3642 waitCount--; 3643 } 3644 3645 // 5000 * 100us = 500,000us = 500ms = 0.5s 3646 if(statusByte != IDE_STATUS_WRONG) { 3647 waitCount = 5000; 3648 do { 3649 AtapiStallExecution(100); 3650 } while (waitCount--); 3651 } 3652 } 3653 GetBaseStatus(chan, statusByte); 3654 AtapiEnableInterrupts(deviceExtension, lChannel); 3655 AtapiStallExecution(10); 3656 } 3657 3658 return; 3659 3660 } // end AtapiHwInitialize__() 3661 3662 3663 #ifndef UNIATA_CORE 3664 3665 VOID 3666 NTAPI 3667 AtapiHwInitializeChanger( 3668 IN PVOID HwDeviceExtension, 3669 IN PSCSI_REQUEST_BLOCK Srb, 3670 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus) 3671 { 3672 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 3673 ULONG lChannel = GET_CHANNEL(Srb); 3674 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 3675 ULONG DeviceNumber = GET_CDEV(Srb); 3676 PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber]; 3677 3678 if (MechanismStatus) { 3679 LunExt->DiscsPresent = MechanismStatus->NumberAvailableSlots; 3680 if (LunExt->DiscsPresent > 1) { 3681 LunExt->DeviceFlags |= DFLAGS_ATAPI_CHANGER; 3682 } 3683 } 3684 return; 3685 } // end AtapiHwInitializeChanger() 3686 3687 3688 /*++ 3689 3690 Routine Description: 3691 This routine will parse the string for a match on the keyword, then 3692 calculate the value for the keyword and return it to the caller. 3693 3694 Arguments: 3695 String - The ASCII string to parse. 3696 KeyWord - The keyword for the value desired. 3697 3698 Return Values: 3699 Zero if value not found 3700 Value converted from ASCII to binary. 3701 3702 --*/ 3703 ULONG 3704 NTAPI 3705 AtapiParseArgumentString( 3706 IN PCCH String, 3707 IN PCCH KeyWord 3708 ) 3709 { 3710 PCCH cptr; 3711 PCCH kptr; 3712 ULONG value; 3713 ULONG stringLength = 0; 3714 ULONG keyWordLength = 0; 3715 ULONG index; 3716 3717 if (!String) { 3718 return 0; 3719 } 3720 if (!KeyWord) { 3721 return 0; 3722 } 3723 3724 // Calculate the string length and lower case all characters. 3725 cptr = String; 3726 while (*cptr++) { 3727 stringLength++; 3728 } 3729 3730 // Calculate the keyword length. 3731 kptr = KeyWord; 3732 while (*kptr++) { 3733 keyWordLength++; 3734 } 3735 3736 if (keyWordLength > stringLength) { 3737 3738 // Can't possibly have a match. 3739 return 0; 3740 } 3741 3742 // Now setup and start the compare. 3743 cptr = String; 3744 3745 ContinueSearch: 3746 3747 // The input string may start with white space. Skip it. 3748 while (*cptr == ' ' || *cptr == '\t') { 3749 cptr++; 3750 } 3751 3752 if (*cptr == '\0') { 3753 // end of string. 3754 return 0; 3755 } 3756 3757 kptr = KeyWord; 3758 while ((*cptr == *kptr) || 3759 (*cptr >= 'A' && *cptr <= 'Z' && *cptr + ('a' - 'A') == *kptr) || 3760 (*cptr >= 'a' && *cptr <= 'z' && *cptr - ('a' - 'A') == *kptr)) { 3761 cptr++; 3762 kptr++; 3763 3764 if (*cptr == '\0') { 3765 // end of string 3766 return 0; 3767 } 3768 } 3769 3770 if (*kptr == '\0') { 3771 3772 // May have a match backup and check for blank or equals. 3773 while (*cptr == ' ' || *cptr == '\t') { 3774 cptr++; 3775 } 3776 3777 // Found a match. Make sure there is an equals. 3778 if (*cptr != '=') { 3779 3780 // Not a match so move to the next semicolon. 3781 while (*cptr) { 3782 if (*cptr++ == ';') { 3783 goto ContinueSearch; 3784 } 3785 } 3786 return 0; 3787 } 3788 // Skip the equals sign. 3789 cptr++; 3790 3791 // Skip white space. 3792 while ((*cptr == ' ') || (*cptr == '\t')) { 3793 cptr++; 3794 } 3795 3796 if (*cptr == '\0') { 3797 // Early end of string, return not found 3798 return 0; 3799 } 3800 3801 if (*cptr == ';') { 3802 // This isn't it either. 3803 cptr++; 3804 goto ContinueSearch; 3805 } 3806 3807 value = 0; 3808 if ((*cptr == '0') && ((*(cptr + 1) == 'x') || (*(cptr + 1) == 'X'))) { 3809 // Value is in Hex. Skip the "0x" 3810 cptr += 2; 3811 for (index = 0; *(cptr + index); index++) { 3812 3813 if (*(cptr + index) == ' ' || 3814 *(cptr + index) == '\t' || 3815 *(cptr + index) == ';') { 3816 break; 3817 } 3818 3819 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) { 3820 value = (16 * value) + (*(cptr + index) - '0'); 3821 } else { 3822 if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) { 3823 value = (16 * value) + (*(cptr + index) - 'a' + 10); 3824 } else if ((*(cptr + index) >= 'A') && (*(cptr + index) <= 'F')) { 3825 value = (16 * value) + (*(cptr + index) - 'A' + 10); 3826 } else { 3827 // Syntax error, return not found. 3828 return 0; 3829 } 3830 } 3831 } 3832 } else { 3833 3834 // Value is in Decimal. 3835 for (index = 0; *(cptr + index); index++) { 3836 3837 if (*(cptr + index) == ' ' || 3838 *(cptr + index) == '\t' || 3839 *(cptr + index) == ';') { 3840 break; 3841 } 3842 3843 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) { 3844 value = (10 * value) + (*(cptr + index) - '0'); 3845 } else { 3846 3847 // Syntax error return not found. 3848 return 0; 3849 } 3850 } 3851 } 3852 3853 return value; 3854 } else { 3855 3856 // Not a match check for ';' to continue search. 3857 while (*cptr) { 3858 if (*cptr++ == ';') { 3859 goto ContinueSearch; 3860 } 3861 } 3862 3863 return 0; 3864 } 3865 } // end AtapiParseArgumentString()_ 3866 3867 /* 3868 Timer callback 3869 */ 3870 VOID 3871 NTAPI 3872 AtapiCallBack__( 3873 IN PVOID HwDeviceExtension, 3874 IN UCHAR lChannel 3875 ) 3876 { 3877 3878 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 3879 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 3880 ULONG c, _c; 3881 3882 PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan); 3883 UCHAR statusByte; 3884 3885 KdPrint2((PRINT_PREFIX "AtapiCallBack:\n")); 3886 // If the last command was DSC restrictive, see if it's set. If so, the device is 3887 // ready for a new request. Otherwise, reset the timer and come back to here later. 3888 3889 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here. 3890 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus, 3891 // we shall have no problem with interrupt handler. 3892 if (!srb || chan->ExpectingInterrupt) { 3893 KdPrint2((PRINT_PREFIX "AtapiCallBack: Calling ISR directly due to BUSY\n")); 3894 chan->DpcState = DPC_STATE_TIMER; 3895 if(!AtapiInterrupt__(HwDeviceExtension, lChannel)) { 3896 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE); 3897 KdPrint2((PRINT_PREFIX "AtapiCallBack: What's fucking this ???\n")); 3898 } 3899 goto ReturnCallback; 3900 } 3901 3902 #ifdef _DEBUG 3903 if (!IS_RDP((srb->Cdb[0]))) { 3904 KdPrint2((PRINT_PREFIX "AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb->Cdb[0])); 3905 } 3906 #endif 3907 if(!(chan->RDP)) { 3908 goto ReturnEnableIntr; 3909 } 3910 GetStatus(chan, statusByte); 3911 if (statusByte & IDE_STATUS_DSC) { 3912 3913 UCHAR PathId = srb->PathId; 3914 UCHAR TargetId = srb->TargetId; 3915 UCHAR Lun = srb->Lun; 3916 3917 KdPrint2((PRINT_PREFIX "AtapiCallBack: Found DSC for RDP - %#x\n", srb->Cdb[0])); 3918 AtapiDmaDBSync(chan, srb); 3919 UniataRemoveRequest(chan, srb); 3920 ScsiPortNotification(RequestComplete, deviceExtension, srb); 3921 // Clear current SRB. 3922 if(!deviceExtension->simplexOnly) { 3923 srb = UniataGetCurRequest(chan); 3924 } else { 3925 srb = NULL; 3926 } 3927 chan->RDP = FALSE; 3928 3929 // Ask for next request. 3930 ScsiPortNotification(NextLuRequest, 3931 deviceExtension, 3932 PathId, 3933 TargetId, 3934 Lun); 3935 ScsiPortNotification(NextRequest, deviceExtension, NULL); 3936 3937 if(srb) { 3938 AtapiStartIo__(HwDeviceExtension, srb, FALSE); 3939 } 3940 3941 } else { 3942 KdPrint2((PRINT_PREFIX "AtapiCallBack: Requesting another timer for Op %#x\n", 3943 srb->Cdb[0])); 3944 3945 AtapiQueueTimerDpc(HwDeviceExtension, lChannel, 3946 AtapiCallBack_X, 3947 1000); 3948 3949 goto ReturnCallback; 3950 } 3951 3952 ReturnEnableIntr: 3953 3954 if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) { 3955 KdPrint2((PRINT_PREFIX "AtapiCallBack: CallDisableInterrupts\n")); 3956 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 3957 #ifdef UNIATA_USE_XXableInterrupts 3958 chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ; 3959 // must be called on DISPATCH_LEVEL 3960 ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension, 3961 AtapiEnableInterrupts__); 3962 #else 3963 AtapiEnableInterrupts(HwDeviceExtension, lChannel); 3964 InterlockedExchange(&(chan->CheckIntr), 3965 CHECK_INTR_IDLE); 3966 // Will raise IRQL to DIRQL 3967 AtapiQueueTimerDpc(HwDeviceExtension, lChannel, 3968 AtapiEnableInterrupts__, 3969 1); 3970 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n")); 3971 #endif // UNIATA_USE_XXableInterrupts 3972 } else { 3973 //ASSERT(!deviceExtension->simplexOnly); 3974 } 3975 3976 ReturnCallback: 3977 3978 // Check other channel 3979 // In simplex mode no interrupts must appear on other channels 3980 for(_c=0; _c<deviceExtension->NumberChannels; _c++) { 3981 c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels; 3982 3983 if(c == lChannel) { 3984 continue; 3985 } 3986 3987 chan = &(deviceExtension->chan[c]); 3988 3989 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr), 3990 CRNT_ILK_TYPE CHECK_INTR_ACTIVE, 3991 CRNT_ILK_TYPE CHECK_INTR_DETECTED) == CHECK_INTR_DETECTED) 3992 { 3993 //ASSERT(!deviceExtension->simplexOnly); 3994 chan->DpcState = DPC_STATE_ISR; 3995 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) { 3996 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE); 3997 } 3998 } 3999 } 4000 KdPrint2((PRINT_PREFIX "AtapiCallBack: return\n")); 4001 return; 4002 4003 } // end AtapiCallBack__() 4004 4005 VOID 4006 NTAPI 4007 AtapiCallBack_X( 4008 IN PVOID HwDeviceExtension 4009 ) 4010 { 4011 AtapiCallBack__(HwDeviceExtension, (UCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->ActiveDpcChan); 4012 } // end AtapiCallBack_X() 4013 4014 #endif //UNIATA_CORE 4015 4016 /*++ 4017 4018 Routine Description: 4019 4020 This is the interrupt service routine for ATAPI IDE miniport driver. 4021 4022 Arguments: 4023 4024 HwDeviceExtension - HBA miniport driver's adapter data storage 4025 4026 Return Value: 4027 4028 TRUE if expecting an interrupt. 4029 4030 --*/ 4031 BOOLEAN 4032 NTAPI 4033 AtapiInterrupt( 4034 IN PVOID HwDeviceExtension 4035 ) 4036 { 4037 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 4038 ULONG c, _c; 4039 BOOLEAN status = FALSE; 4040 ULONG c_state; 4041 ULONG i_res = 0; 4042 ULONG pass; 4043 //BOOLEAN checked[AHCI_MAX_PORT]; 4044 ULONG hIS; 4045 ULONG checked; 4046 4047 KdPrint2((PRINT_PREFIX "Intr: DeviceID+VendorID/Rev %#x/%#x (ex %d)\n", 4048 deviceExtension->DevID, deviceExtension->RevID, deviceExtension->ExpectingInterrupt )); 4049 4050 if(deviceExtension->HwFlags & UNIATA_AHCI) { 4051 // AHCI may generate state change notification, never skip this check 4052 hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS); 4053 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel)); 4054 if(!hIS) { 4055 return FALSE; 4056 } 4057 // assume all non-interrupted ports to be already checked 4058 checked = ~hIS; 4059 // assume all not implemented ports to be already checked 4060 checked |= ~deviceExtension->AHCI_PI; 4061 } else { 4062 checked = 0; // assume all ports are not checked 4063 } 4064 4065 if(!deviceExtension->ExpectingInterrupt) { 4066 // if we do not expect interrupt, exit now, 4067 // but keep in mind that it can be unexpected one 4068 // Note: this is just a hint, not exact counter 4069 KdPrint2((PRINT_PREFIX "unexpected, 1st chance\n")); 4070 //deviceExtension->ExpectingInterrupt++; 4071 //return FALSE; 4072 } 4073 // clear this flag now, it can be set again in sub-calls 4074 deviceExtension->ExpectingInterrupt=0; 4075 4076 4077 // for(_c=0; _c<deviceExtension->NumberChannels; _c++) { 4078 // checked[_c] = (UCHAR)((hIS >> _c) & 0x01); 4079 // } 4080 4081 // fc = 4082 for(pass=0; pass<2; pass++) { 4083 //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass)); 4084 if(status && pass) { 4085 // we catched some expected interrupts now. 4086 // do not touch unexpected until next ISR call 4087 break; 4088 } 4089 for(_c=0; _c<deviceExtension->NumberChannels; _c++) { 4090 4091 c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels; 4092 4093 if((checked>>c) & 0x01) 4094 continue; 4095 4096 // check non-empty and expecting interrupt channels first 4097 if(!pass && !deviceExtension->chan[c].ExpectingInterrupt) 4098 continue; 4099 4100 checked |= (ULONG)1 << c; 4101 4102 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c)); 4103 4104 if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) { 4105 // we get here on idle channels or when ISR is posted to DPC 4106 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): disabled INTR on ch %d\n", c)); 4107 continue; 4108 } 4109 // lock channel. Wait, while 2nd ISR checks interrupt on this channel 4110 do { 4111 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): try lock\n")); 4112 // c_state = deviceExtension->chan[c].CheckIntr; 4113 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) { 4114 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE; 4115 // } 4116 c_state = 4117 (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr), 4118 CRNT_ILK_TYPE CHECK_INTR_ACTIVE, 4119 CRNT_ILK_TYPE CHECK_INTR_DETECTED); 4120 if(c_state == CHECK_INTR_IDLE) { 4121 // c_state = deviceExtension->chan[c].CheckIntr; 4122 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) { 4123 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE 4124 // } 4125 c_state = 4126 (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr), 4127 CRNT_ILK_TYPE CHECK_INTR_ACTIVE, 4128 CRNT_ILK_TYPE CHECK_INTR_IDLE); 4129 } 4130 } while(c_state == CHECK_INTR_CHECK); 4131 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): locked\n")); 4132 // check if already serviced 4133 if(c_state == CHECK_INTR_ACTIVE) { 4134 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): CHECK_INTR_ACTIVE\n")); 4135 continue; 4136 } 4137 4138 if((c_state == CHECK_INTR_DETECTED) || 4139 (i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) { 4140 4141 if(i_res == INTERRUPT_REASON_UNEXPECTED) { 4142 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): Catch unexpected\n")); 4143 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE); 4144 //return TRUE; 4145 status = TRUE; 4146 continue; 4147 } 4148 // disable interrupts on other channel of legacy mode 4149 // ISA-bridged onboard controller 4150 if(deviceExtension->simplexOnly /*|| 4151 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) { 4152 AtapiDisableInterrupts(deviceExtension, !c); 4153 } 4154 4155 deviceExtension->chan[c].DpcState = DPC_STATE_ISR; 4156 if(AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) { 4157 deviceExtension->LastInterruptedChannel = (UCHAR)c; 4158 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): return status TRUE\n")); 4159 status = TRUE; 4160 } else { 4161 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE\n")); 4162 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE); 4163 } 4164 4165 // re-enable interrupts on other channel 4166 if(deviceExtension->simplexOnly /*|| 4167 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) { 4168 AtapiEnableInterrupts(deviceExtension, !c); 4169 } 4170 4171 } else { 4172 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n")); 4173 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE); 4174 } 4175 4176 } 4177 } 4178 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): exit with status %#x\n", status)); 4179 if(status) { 4180 deviceExtension->FirstChannelToCheck++; 4181 if(deviceExtension->FirstChannelToCheck >= deviceExtension->NumberChannels) 4182 deviceExtension->FirstChannelToCheck = 0; 4183 } 4184 return status; 4185 } // end AtapiInterrupt() 4186 4187 //ULONG i2c = 0; 4188 #ifndef UNIATA_CORE 4189 4190 BOOLEAN 4191 NTAPI 4192 AtapiInterrupt2( 4193 IN PKINTERRUPT Interrupt, 4194 IN PVOID Isr2HwDeviceExtension 4195 ) 4196 { 4197 // This ISR is intended to catch interrupts when we are already in other ISR instance 4198 // for the same device. This may happen when we have multiple channels, 4199 // especially on SMP machines 4200 4201 PISR2_DEVICE_EXTENSION Isr2DeviceExtension = (PISR2_DEVICE_EXTENSION)Isr2HwDeviceExtension; 4202 PHW_DEVICE_EXTENSION deviceExtension = Isr2DeviceExtension->HwDeviceExtension; 4203 ULONG c; 4204 BOOLEAN status = FALSE; 4205 ULONG c_count = 0; 4206 ULONG i_res; 4207 ULONG hIS; 4208 ULONG checked; 4209 4210 // we should never get here for ISA/MCA 4211 if(!BMList[deviceExtension->DevIndex].Isr2Enable) { 4212 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension->DevIndex, deviceExtension->Channel)); 4213 return FALSE; 4214 } 4215 4216 if(deviceExtension->HwFlags & UNIATA_AHCI) { 4217 // AHCI may generate state change notification, never skip this check 4218 hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS); 4219 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel)); 4220 if(!hIS) { 4221 return FALSE; 4222 } 4223 // assume all non-interrupted ports to be already checked 4224 checked = ~hIS; 4225 // assume all not implemented ports to be already checked 4226 checked |= ~deviceExtension->AHCI_PI; 4227 4228 } else { 4229 checked = 0; // assume all ports are not checked 4230 } 4231 if(!deviceExtension->ExpectingInterrupt) { 4232 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n")); 4233 deviceExtension->ExpectingInterrupt++; 4234 return FALSE; 4235 } 4236 //deviceExtension->ExpectingInterrupt = 0; 4237 4238 for(c=0; c<deviceExtension->NumberChannels; c++) { 4239 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c)); 4240 4241 if((checked>>c) & 0x01) 4242 continue; 4243 4244 checked |= (ULONG)1 << c; 4245 4246 if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) { 4247 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: disabled INTR\n")); 4248 continue; 4249 } 4250 4251 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr), 4252 CRNT_ILK_TYPE CHECK_INTR_CHECK, 4253 CRNT_ILK_TYPE CHECK_INTR_IDLE) != CHECK_INTR_IDLE) 4254 { 4255 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !CHECK_INTR_IDLE\n")); 4256 // hunt on unexpected intr (Some devices generate double interrupts, 4257 // some controllers (at least CMD649) interrupt twice with small delay. 4258 // If interrupts are disabled, they queue interrupt and re-issue it later, 4259 // when we do not expect it. 4260 continue; 4261 } 4262 4263 c_count++; 4264 if((i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) { 4265 4266 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: intr\n")); 4267 if(i_res == INTERRUPT_REASON_UNEXPECTED) { 4268 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: Catch unexpected\n")); 4269 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE); 4270 return TRUE; 4271 } 4272 4273 status = TRUE; 4274 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_DETECTED); 4275 } else { 4276 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE); 4277 } 4278 } 4279 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: status %d, c_count %d\n", status, c_count)); 4280 if(status && (c_count != deviceExtension->NumberChannels)) { 4281 // there is an active ISR/DPC for one channel, but 4282 // we have an interrupt from another one 4283 // Lets inform current ISR/DPC about new interrupt 4284 InterlockedExchange(&(deviceExtension->ReCheckIntr), CHECK_INTR_DETECTED); 4285 } else { 4286 status = FALSE; 4287 } 4288 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: return %d\n", status)); 4289 return status; 4290 4291 } // end AtapiInterrupt2() 4292 4293 RETTYPE_XXableInterrupts 4294 NTAPI 4295 AtapiInterruptDpc( 4296 IN PVOID HwDeviceExtension 4297 ) 4298 { 4299 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 4300 ULONG c; 4301 4302 for(c=0; c<deviceExtension->NumberChannels; c++) { 4303 KdPrint2((PRINT_PREFIX "AtapiInterruptDpc: %#x\n",c)); 4304 4305 if(!(deviceExtension->chan[c].ChannelCtrlFlags & CTRFLAGS_DPC_REQ)) { 4306 4307 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr), 4308 CRNT_ILK_TYPE CHECK_INTR_ACTIVE, 4309 CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) 4310 { 4311 continue; 4312 } 4313 4314 } else { 4315 deviceExtension->chan[c].ChannelCtrlFlags &= ~CTRFLAGS_DPC_REQ; 4316 } 4317 /* 4318 if(OldReqState != REQ_STATE_DPC_INTR_REQ) { 4319 AtapiDisableInterrupts(deviceExtension, lChannel); 4320 } 4321 */ 4322 deviceExtension->chan[c].DpcState = DPC_STATE_DPC; 4323 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) { 4324 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE); 4325 } 4326 } 4327 return RETVAL_XXableInterrupts; 4328 } // end AtapiInterruptDpc() 4329 4330 4331 RETTYPE_XXableInterrupts 4332 NTAPI 4333 AtapiEnableInterrupts__( 4334 IN PVOID HwDeviceExtension 4335 ) 4336 { 4337 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 4338 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__():\n")); 4339 ULONG c; 4340 PHW_CHANNEL chan = NULL; 4341 4342 for(c=0; c<deviceExtension->NumberChannels; c++) { 4343 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__(2): %#x\n",c)); 4344 chan = &(deviceExtension->chan[c]); 4345 4346 if(chan->ChannelCtrlFlags & CTRFLAGS_ENABLE_INTR_REQ) { 4347 // enable intrs on requested channel 4348 chan->ChannelCtrlFlags &= ~CTRFLAGS_ENABLE_INTR_REQ; 4349 AtapiEnableInterrupts(HwDeviceExtension, c); 4350 InterlockedExchange(&(chan->CheckIntr), 4351 CHECK_INTR_IDLE); 4352 4353 // check if current or other channel(s) interrupted 4354 //AtapiInterrupt(HwDeviceExtension); 4355 4356 if(deviceExtension->simplexOnly) { 4357 break; 4358 } 4359 } else { 4360 // check if other channel(s) interrupted 4361 // must do nothing in simplex mode 4362 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr), 4363 CRNT_ILK_TYPE CHECK_INTR_ACTIVE, 4364 CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) { 4365 continue; 4366 } 4367 //ASSERT(!deviceExtension->simplexOnly); 4368 chan->DpcState = DPC_STATE_ISR; 4369 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) { 4370 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE); 4371 } 4372 } 4373 } 4374 // In simplex mode next command must be sent to device here 4375 if(deviceExtension->simplexOnly && chan) { 4376 PSCSI_REQUEST_BLOCK srb; 4377 chan = UniataGetNextChannel(chan); 4378 if(chan) { 4379 srb = UniataGetCurRequest(chan); 4380 } else { 4381 srb = NULL; 4382 } 4383 if(srb) { 4384 AtapiStartIo__(HwDeviceExtension, srb, FALSE); 4385 } 4386 } 4387 4388 return RETVAL_XXableInterrupts; 4389 4390 } // end AtapiEnableInterrupts__() 4391 4392 #endif //UNIATA_CORE 4393 4394 4395 VOID 4396 NTAPI 4397 AtapiEnableInterrupts( 4398 IN PVOID HwDeviceExtension, 4399 IN ULONG c 4400 ) 4401 { 4402 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 4403 PHW_CHANNEL chan; 4404 //UCHAR statusByte; 4405 4406 if(c >= deviceExtension->NumberChannels) { 4407 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c)); 4408 return; 4409 } 4410 if((deviceExtension->HwFlags & UNIATA_AHCI) && 4411 !UniataAhciChanImplemented(deviceExtension, c)) { 4412 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c)); 4413 return; 4414 } 4415 4416 chan = &(deviceExtension->chan[c]); 4417 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr)); 4418 if(!InterlockedDecrement(&chan->DisableIntr)) { 4419 if(deviceExtension->HwFlags & UNIATA_AHCI) { 4420 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 4421 (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | 4422 ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_INF | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | 4423 ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) | 4424 ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | /* DEBUG */ 4425 ATA_AHCI_P_IX_DI | 4426 ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | 4427 ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR) 4428 ); 4429 } else { 4430 //SelectDrive(chan, 0); 4431 //GetBaseStatus(chan, statusByte); 4432 AtapiWritePort1(chan, IDX_IO2_o_Control, 4433 0 | IDE_DC_A_4BIT ); 4434 //if(chan->NumberLuns) { 4435 // SelectDrive(chan, 1); 4436 // GetBaseStatus(chan, statusByte); 4437 // AtapiWritePort1(chan, IDX_IO2_o_Control, 4438 // IDE_DC_A_4BIT ); 4439 // SelectDrive(chan, chan->cur_cdev); 4440 //} 4441 } 4442 chan->ChannelCtrlFlags &= ~CTRFLAGS_INTR_DISABLED; 4443 } else { 4444 if(deviceExtension->HwFlags & UNIATA_AHCI) { 4445 // keep interrupts disabled 4446 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); 4447 } else { 4448 AtapiWritePort1(chan, IDX_IO2_o_Control, 4449 IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ ); 4450 } 4451 } 4452 return; 4453 } // end AtapiEnableInterrupts() 4454 4455 VOID 4456 NTAPI 4457 AtapiDisableInterrupts( 4458 IN PVOID HwDeviceExtension, 4459 IN ULONG c 4460 ) 4461 { 4462 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 4463 PHW_CHANNEL chan; 4464 if(c >= deviceExtension->NumberChannels) { 4465 KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c)); 4466 return; 4467 } 4468 chan = &(deviceExtension->chan[c]); 4469 KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: %d\n",c, chan->DisableIntr)); 4470 // mark channel as busy 4471 if(InterlockedIncrement(&chan->DisableIntr)) { 4472 if(deviceExtension->HwFlags & UNIATA_AHCI) { 4473 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); 4474 } else { 4475 //SelectDrive(chan, 0); 4476 AtapiWritePort1(chan, IDX_IO2_o_Control, 4477 IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ ); 4478 //if(chan->NumberLuns) { 4479 // SelectDrive(chan, 1); 4480 // AtapiWritePort1(chan, IDX_IO2_o_Control, 4481 // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ ); 4482 // SelectDrive(chan, chan->cur_cdev); 4483 //} 4484 } 4485 chan->ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED; 4486 } 4487 4488 return; 4489 } // end AtapiDisableInterrupts() 4490 4491 VOID 4492 UniataExpectChannelInterrupt( 4493 IN struct _HW_CHANNEL* chan, 4494 IN BOOLEAN Expecting 4495 ) 4496 { 4497 chan->ExpectingInterrupt = Expecting; 4498 if(Expecting) { 4499 chan->DeviceExtension->ExpectingInterrupt++; 4500 } else 4501 if(chan->DeviceExtension->ExpectingInterrupt) { 4502 chan->DeviceExtension->ExpectingInterrupt--; 4503 } 4504 return; 4505 } // end UniataExpectChannelInterrupt() 4506 4507 /* 4508 Check hardware for interrupt state 4509 */ 4510 BOOLEAN 4511 NTAPI 4512 AtapiCheckInterrupt__( 4513 IN PVOID HwDeviceExtension, 4514 IN UCHAR c // logical channel 4515 ) 4516 { 4517 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 4518 PHW_CHANNEL chan = &(deviceExtension->chan[c]); 4519 PHW_LU_EXTENSION LunExt; 4520 4521 ULONG VendorID = deviceExtension->DevID & 0xffff; 4522 ULONG ChipType = deviceExtension->HwFlags & CHIPTYPE_MASK; 4523 4524 ULONG status; 4525 ULONG pr_status = 0; 4526 UCHAR dma_status = 0; 4527 UCHAR reg8 = 0; 4528 ULONG reg32 = 0; 4529 UCHAR statusByte = 0; 4530 ULONG slotNumber = deviceExtension->slotNumber; 4531 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber; 4532 ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK; 4533 UCHAR Channel; 4534 UCHAR lChannel; 4535 BOOLEAN DmaTransfer = FALSE; 4536 BOOLEAN OurInterrupt = FALSE; 4537 BOOLEAN StatusValid = FALSE; 4538 // ULONG k; 4539 UCHAR interruptReason; 4540 BOOLEAN EarlyIntr = FALSE; 4541 BOOLEAN SingleBlockIntr = FALSE; 4542 4543 KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__:\n")); 4544 4545 lChannel = c; 4546 Channel = (UCHAR)(deviceExtension->Channel + lChannel); 4547 LunExt = chan->lun[chan->cur_cdev]; 4548 4549 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan)); 4550 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev)); 4551 4552 if((ChipFlags & UNIATA_AHCI) && 4553 UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 4554 4555 if(!UniataAhciChanImplemented(deviceExtension, lChannel)) { 4556 return OurInterrupt; 4557 } 4558 4559 OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED); 4560 if((OurInterrupt == INTERRUPT_REASON_UNEXPECTED) && 4561 (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) { 4562 UniataAhciWaitCommandReady(chan, 2 /* ms */ ); 4563 statusByte = (UCHAR)UniataAhciWaitReady(chan, 0 /* immediate */); 4564 if(!(statusByte & (IDE_STATUS_BUSY)) ) { 4565 KdPrint2((PRINT_PREFIX "ATAPI special case READY\n")); 4566 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts 4567 OurInterrupt = INTERRUPT_REASON_OUR; 4568 } else 4569 if((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRDY)) == (IDE_STATUS_BUSY | IDE_STATUS_DRDY) ) { 4570 KdPrint2((PRINT_PREFIX "ATAPI special case pre ERR-READY\n")); 4571 OurInterrupt = INTERRUPT_REASON_OUR; 4572 } else 4573 if(statusByte & IDE_STATUS_ERROR) { 4574 KdPrint2((PRINT_PREFIX "ATAPI special case ERR-READY\n")); 4575 OurInterrupt = INTERRUPT_REASON_OUR; 4576 } else { 4577 KdPrint2((PRINT_PREFIX "ATAPI special case ? %x\n", statusByte)); 4578 OurInterrupt = INTERRUPT_REASON_OUR; 4579 } 4580 } 4581 return OurInterrupt; 4582 } 4583 4584 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) { 4585 DmaTransfer = TRUE; 4586 KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension->DevIndex, 4587 deviceExtension->Channel + c, c)); 4588 } else { 4589 KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension->DevIndex, 4590 deviceExtension->Channel + c, c)); 4591 dma_status = GetDmaStatus(deviceExtension, lChannel); 4592 KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status)); 4593 } 4594 4595 // do controller-specific interrupt servicing staff 4596 if(deviceExtension->UnknownDev) { 4597 KdPrint2((PRINT_PREFIX " UnknownDev\n")); 4598 goto check_unknown; 4599 } 4600 4601 // Attention ! 4602 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed 4603 // Such behavior was observed with Intel ICH-xxx chips 4604 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag 4605 4606 switch(VendorID) { 4607 4608 case ATA_PROMISE_ID: { 4609 switch(ChipType) { 4610 case PROLD: 4611 case PRNEW: 4612 status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1c); 4613 if (!DmaTransfer) 4614 break; 4615 if (!(status & 4616 ((Channel) ? 0x00004000 : 0x00000400))) { 4617 KdPrint2((PRINT_PREFIX " Promise old/new unexpected\n")); 4618 return INTERRUPT_REASON_IGNORE; 4619 } 4620 break; 4621 case PRTX: 4622 AtapiWritePort1(chan, IDX_BM_DeviceSpecific0, 0x0b); 4623 status = AtapiReadPort1(chan, IDX_BM_DeviceSpecific1); 4624 if (!DmaTransfer) 4625 break; 4626 if(!(status & 0x20)) { 4627 KdPrint2((PRINT_PREFIX " Promise tx unexpected\n")); 4628 return INTERRUPT_REASON_IGNORE; 4629 } 4630 break; 4631 case PRMIO: { 4632 ULONG stat_reg = (ChipFlags & PRG2) ? 0x60 : 0x6c; 4633 status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40); 4634 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40, status); 4635 4636 if(status & (1 << (Channel+1))) { 4637 // our 4638 } else { 4639 KdPrint2((PRINT_PREFIX " Promise mio unexpected\n")); 4640 return INTERRUPT_REASON_IGNORE; 4641 } 4642 4643 if(!(ChipFlags & UNIATA_SATA)) 4644 break; 4645 4646 pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg); 4647 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg, (pr_status & (0x11 << Channel))); 4648 if(pr_status & (0x11 << Channel)) { 4649 // TODO: reset channel 4650 KdPrint2((PRINT_PREFIX " Promise mio unexpected + reset req\n")); 4651 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0); 4652 } 4653 if(!(status & (0x01 << Channel))) { 4654 // Connect event 4655 KdPrint2((PRINT_PREFIX " Promise mio unexpected attach\n")); 4656 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0); 4657 } 4658 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) { 4659 OurInterrupt = INTERRUPT_REASON_UNEXPECTED; 4660 } else { 4661 return INTERRUPT_REASON_IGNORE; 4662 } 4663 4664 AtapiWritePort4(chan, IDX_BM_DeviceSpecific0, 0x00000001); 4665 break; } 4666 } 4667 break; } 4668 case ATA_NVIDIA_ID: { 4669 if(!(ChipFlags & UNIATA_SATA) || (ChipFlags & NVGEN)) 4670 break; 4671 4672 KdPrint2((PRINT_PREFIX "NVIDIA\n")); 4673 4674 ULONG offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010; 4675 ULONG shift = Channel * ((ChipFlags & NVQ) ? 4 : 16); 4676 4677 /* get and clear interrupt status */ 4678 if(ChipFlags & NVQ) { 4679 pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs); 4680 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0fUL << shift) | 0x00f000f0); 4681 } else { 4682 pr_status = AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs); 4683 AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0f << shift)); 4684 } 4685 KdPrint2((PRINT_PREFIX " pr_status %x, shift %x\n", pr_status, shift)); 4686 4687 /* check for and handle connect events */ 4688 if(((pr_status & (0x0cUL << shift)) == (0x04UL << shift)) ) { 4689 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0); 4690 } 4691 /* check for and handle disconnect events */ 4692 if((pr_status & (0x08UL << shift)) && 4693 !((pr_status & (0x04UL << shift) && 4694 UniataSataReadPort4(chan, IDX_SATA_SStatus, 0))) ) { 4695 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0); 4696 } 4697 /* do we have any device action ? */ 4698 if(!(pr_status & (0x01UL << shift))) { 4699 KdPrint2((PRINT_PREFIX " nVidia unexpected\n")); 4700 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) { 4701 OurInterrupt = INTERRUPT_REASON_UNEXPECTED; 4702 } else { 4703 return INTERRUPT_REASON_IGNORE; 4704 } 4705 } 4706 4707 break; } 4708 case ATA_ATI_ID: 4709 KdPrint2((PRINT_PREFIX "ATI\n")); 4710 if(ChipType == SIIMIO) { 4711 // fall to SiI 4712 } else { 4713 break; 4714 } 4715 case ATA_SILICON_IMAGE_ID: 4716 4717 if(ChipType == SIIMIO) { 4718 4719 reg32 = AtapiReadPort4(chan, IDX_BM_DeviceSpecific0); 4720 KdPrint2((PRINT_PREFIX " Sii DS0 %x\n", reg32)); 4721 if(reg32 == 0xffffffff) { 4722 KdPrint2((PRINT_PREFIX " Sii mio unexpected\n")); 4723 return INTERRUPT_REASON_IGNORE; 4724 } 4725 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))) { 4726 KdPrint2((PRINT_PREFIX " Sii mio unexpected (2)\n")); 4727 return INTERRUPT_REASON_IGNORE; 4728 } 4729 4730 if(ChipFlags & UNIATA_SATA) { 4731 if(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_IRQ)) { 4732 4733 /* SIEN doesn't mask SATA IRQs on some 3112s. Those 4734 * controllers continue to assert IRQ as long as 4735 * SError bits are pending. Clear SError immediately. 4736 */ 4737 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) { 4738 OurInterrupt = INTERRUPT_REASON_UNEXPECTED; 4739 } 4740 } 4741 } 4742 4743 if (!DmaTransfer) 4744 break; 4745 if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) { 4746 KdPrint2((PRINT_PREFIX " Sii mio unexpected (3)\n")); 4747 return OurInterrupt; 4748 } 4749 AtapiWritePort1(chan, IDX_BM_Status, dma_status & ~BM_STATUS_ERR); 4750 goto skip_dma_stat_check; 4751 4752 } else { 4753 if(!(deviceExtension->HwFlags & SIIINTR)) 4754 break; 4755 GetPciConfig1(0x71, reg8); 4756 KdPrint2((PRINT_PREFIX " 0x71 = %#x\n", reg8)); 4757 if (!(reg8 & 4758 (Channel ? 0x08 : 0x04))) { 4759 return INTERRUPT_REASON_IGNORE; 4760 } 4761 if (!DmaTransfer) { 4762 KdPrint2((PRINT_PREFIX " cmd our\n")); 4763 OurInterrupt = INTERRUPT_REASON_UNEXPECTED; 4764 } 4765 SetPciConfig1(0x71, (Channel ? 0x08 : 0x04)); 4766 } 4767 break; 4768 4769 case ATA_ACARD_ID: 4770 if (!DmaTransfer) 4771 break; 4772 //dma_status = GetDmaStatus(deviceExtension, lChannel); 4773 if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) { 4774 KdPrint2((PRINT_PREFIX " Acard unexpected\n")); 4775 return INTERRUPT_REASON_IGNORE; 4776 } 4777 AtapiWritePort1(chan, IDX_BM_Status, dma_status | BM_STATUS_INTR); 4778 AtapiStallExecution(1); 4779 AtapiWritePort1(chan, IDX_BM_Command, 4780 AtapiReadPort1(chan, IDX_BM_Command) & ~BM_COMMAND_START_STOP); 4781 goto skip_dma_stat_check; 4782 case ATA_INTEL_ID: 4783 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 4784 if(ChipFlags & UNIATA_AHCI) { 4785 // Do nothing here 4786 } else 4787 if(ChipFlags & UNIATA_SATA) { 4788 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) { 4789 OurInterrupt = INTERRUPT_REASON_UNEXPECTED; 4790 } 4791 if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) { 4792 if(UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1)) { 4793 OurInterrupt = INTERRUPT_REASON_UNEXPECTED; 4794 } 4795 } 4796 } 4797 } 4798 break; 4799 default: 4800 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 4801 if(ChipFlags & UNIATA_AHCI) { 4802 // Do nothing here 4803 } else 4804 if(ChipFlags & UNIATA_SATA) { 4805 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) { 4806 OurInterrupt = INTERRUPT_REASON_UNEXPECTED; 4807 } 4808 } 4809 } 4810 } 4811 check_unknown: 4812 KdPrint2((PRINT_PREFIX " perform generic check\n")); 4813 if (DmaTransfer) { 4814 if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) { 4815 KdPrint2((PRINT_PREFIX " DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status)); 4816 if(dma_status & BM_STATUS_ERR) { 4817 KdPrint2((PRINT_PREFIX " DmaTransfer + BM_STATUS_ERR -> our\n")); 4818 OurInterrupt = INTERRUPT_REASON_UNEXPECTED; 4819 } else { 4820 KdPrint2((PRINT_PREFIX " getting status...\n")); 4821 GetStatus(chan, statusByte); 4822 StatusValid = 1; 4823 KdPrint2((PRINT_PREFIX " status %#x\n", statusByte)); 4824 if(statusByte & IDE_STATUS_ERROR) { 4825 KdPrint2((PRINT_PREFIX " IDE_STATUS_ERROR -> our\n", statusByte)); 4826 OurInterrupt = INTERRUPT_REASON_UNEXPECTED; 4827 } else 4828 if ((statusByte & IDE_STATUS_DSC) && 4829 (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) && 4830 (dma_status == BM_STATUS_ACTIVE)) { 4831 KdPrint2((PRINT_PREFIX " special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte)); 4832 // some devices interrupts on each block transfer even in DMA mode 4833 if(LunExt->TransferMode >= ATA_SDMA && LunExt->TransferMode <= ATA_WDMA2) { 4834 KdPrint2((PRINT_PREFIX " wait for completion\n")); 4835 ///* clear interrupt and get status */ 4836 //GetBaseStatus(chan, statusByte); 4837 //return INTERRUPT_REASON_IGNORE; 4838 SingleBlockIntr = TRUE; 4839 } 4840 } else { 4841 return INTERRUPT_REASON_IGNORE; 4842 } 4843 } 4844 } 4845 } else { 4846 if(dma_status & BM_STATUS_INTR) { 4847 // bullshit, we have DMA interrupt, but had never initiate DMA operation 4848 KdPrint2((PRINT_PREFIX " clear unexpected DMA intr\n")); 4849 AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL); 4850 // catch it ! 4851 OurInterrupt = INTERRUPT_REASON_UNEXPECTED; 4852 } 4853 } 4854 skip_dma_stat_check: 4855 if(!(ChipFlags & UNIATA_SATA) && chan->ExpectingInterrupt) { 4856 AtapiStallExecution(1); 4857 } 4858 4859 /* if drive is busy it didn't interrupt */ 4860 /* the exception is DCS + BSY state of ATAPI devices */ 4861 if(!StatusValid) { 4862 KdPrint2((PRINT_PREFIX " getting status...\n")); 4863 GetStatus(chan, statusByte); 4864 } 4865 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { 4866 KdPrint3((PRINT_PREFIX " ATAPI status %#x\n", statusByte)); 4867 } else { 4868 KdPrint2((PRINT_PREFIX " IDE status %#x\n", statusByte)); 4869 } 4870 if (statusByte == IDE_STATUS_WRONG) { 4871 // interrupt from empty controller ? 4872 } else 4873 if (statusByte & IDE_STATUS_BUSY) { 4874 if(!chan->ExpectingInterrupt) { 4875 KdPrint3((PRINT_PREFIX " unexpected intr + BUSY\n")); 4876 return OurInterrupt; 4877 } 4878 4879 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { 4880 KdPrint2((PRINT_PREFIX " ATAPI additional check\n")); 4881 } else { 4882 KdPrint2((PRINT_PREFIX " expecting intr + BUSY (3), non ATAPI\n")); 4883 return INTERRUPT_REASON_IGNORE; 4884 } 4885 if((statusByte & ~(IDE_STATUS_DRQ | IDE_STATUS_INDEX)) != 4886 (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) { 4887 KdPrint3((PRINT_PREFIX " unexpected status, seems it is not our\n")); 4888 return INTERRUPT_REASON_IGNORE; 4889 } 4890 if(!(LunExt->DeviceFlags & DFLAGS_INT_DRQ) && (statusByte & IDE_STATUS_DRQ)) { 4891 KdPrint3((PRINT_PREFIX " unexpected DRQ, seems it is not our\n")); 4892 return INTERRUPT_REASON_IGNORE; 4893 } 4894 4895 EarlyIntr = TRUE; 4896 4897 if(dma_status & BM_STATUS_INTR) { 4898 KdPrint3((PRINT_PREFIX " our interrupt with BSY set, try wait in ISR or post to DPC\n")); 4899 /* clear interrupt and get status */ 4900 GetBaseStatus(chan, statusByte); 4901 if(!(dma_status & BM_STATUS_ACTIVE)) { 4902 AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL); 4903 } 4904 KdPrint3((PRINT_PREFIX " base status %#x (+BM_STATUS_INTR)\n", statusByte)); 4905 return INTERRUPT_REASON_OUR; 4906 } 4907 4908 if(g_WaitBusyInISR) { 4909 GetStatus(chan, statusByte); 4910 KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte)); 4911 reg8 = AtapiReadPort1(chan, IDX_IO1_i_Error); 4912 KdPrint2((PRINT_PREFIX " Error reg (%#x)\n", reg8)); 4913 if (!(statusByte & IDE_STATUS_BUSY)) { 4914 KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n")); 4915 } 4916 if (statusByte & IDE_STATUS_BUSY) { 4917 KdPrint2((PRINT_PREFIX " still BUSY, seems it is not our\n")); 4918 return INTERRUPT_REASON_IGNORE; 4919 } 4920 } 4921 4922 } 4923 4924 /* clear interrupt and get status */ 4925 GetBaseStatus(chan, statusByte); 4926 KdPrint2((PRINT_PREFIX " base status %#x\n", statusByte)); 4927 if (statusByte == IDE_STATUS_WRONG) { 4928 // interrupt from empty controller ? 4929 } else 4930 if(!(statusByte & (IDE_STATUS_DRQ | IDE_STATUS_DRDY))) { 4931 KdPrint2((PRINT_PREFIX " no DRQ/DRDY set\n")); 4932 return OurInterrupt; 4933 } 4934 4935 #ifndef UNIATA_PIO_ONLY 4936 if(DmaTransfer) { 4937 if(!SingleBlockIntr && (!EarlyIntr || g_WaitBusyInISR)) { 4938 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/); 4939 } else { 4940 PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan); 4941 PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL; 4942 4943 //ASSERT(AtaReq); 4944 4945 if(SingleBlockIntr) { 4946 KdPrint2((PRINT_PREFIX " set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n")); 4947 } else { 4948 KdPrint2((PRINT_PREFIX " set REQ_STATE_EARLY_INTR.\n")); 4949 } 4950 if(AtaReq) { 4951 AtaReq->ReqState = SingleBlockIntr ? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2 : REQ_STATE_EARLY_INTR; 4952 } 4953 } 4954 } 4955 #endif // 4956 4957 if (!(chan->ExpectingInterrupt)) { 4958 4959 KdPrint2((PRINT_PREFIX " Unexpected interrupt.\n")); 4960 4961 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { 4962 KdPrint2((PRINT_PREFIX " ATAPI additional check\n")); 4963 } else { 4964 KdPrint2((PRINT_PREFIX " OurInterrupt = %d\n", OurInterrupt)); 4965 return OurInterrupt; 4966 } 4967 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); 4968 KdPrint3((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason)); 4969 return OurInterrupt; 4970 } 4971 //ASSERT(!chan->queue_depth || chan->cur_req); 4972 4973 KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__: exit with TRUE\n")); 4974 return INTERRUPT_REASON_OUR; 4975 4976 } // end AtapiCheckInterrupt__() 4977 4978 4979 BOOLEAN 4980 NTAPI 4981 AtapiInterrupt__( 4982 IN PVOID HwDeviceExtension, 4983 IN UCHAR c 4984 ) 4985 { 4986 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 4987 PHW_CHANNEL chan = &(deviceExtension->chan[c]); 4988 // Get current Srb 4989 PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan); 4990 PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL; 4991 4992 ULONG wordCount = 0, wordsThisInterrupt = DEV_BSIZE/2; 4993 ULONG status = SRB_STATUS_SUCCESS; 4994 UCHAR dma_status = 0; 4995 ULONG i; 4996 ULONG k; 4997 UCHAR statusByte = 0,interruptReason; 4998 4999 BOOLEAN atapiDev = FALSE; 5000 5001 #ifdef _DEBUG 5002 UCHAR Channel; 5003 #endif //_DEBUG 5004 UCHAR lChannel; 5005 UCHAR DeviceNumber; 5006 BOOLEAN DmaTransfer = FALSE; 5007 UCHAR error = 0; 5008 ULONG TimerValue = 1000; 5009 ULONG TotalTimerValue = 0; 5010 #ifdef UNIATA_USE_XXableInterrupts 5011 BOOLEAN InDpc = (KeGetCurrentIrql() == DISPATCH_LEVEL); 5012 #else 5013 BOOLEAN InDpc = (chan->DpcState != DPC_STATE_ISR); 5014 #endif // UNIATA_USE_XXableInterrupts 5015 BOOLEAN UseDpc = deviceExtension->UseDpc; 5016 // BOOLEAN RestoreUseDpc = FALSE; 5017 BOOLEAN DataOverrun = FALSE; 5018 BOOLEAN NoStartIo = TRUE; 5019 BOOLEAN NoRetry = FALSE; 5020 5021 KdPrint2((PRINT_PREFIX "AtapiInterrupt:\n")); 5022 if(InDpc) { 5023 KdPrint2((PRINT_PREFIX " InDpc = TRUE\n")); 5024 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED)); 5025 } 5026 5027 UCHAR PathId; 5028 UCHAR TargetId; 5029 UCHAR Lun; 5030 UCHAR OldReqState = REQ_STATE_NONE; 5031 //ULONG ldev; 5032 PHW_LU_EXTENSION LunExt; 5033 5034 lChannel = c; 5035 5036 #ifdef _DEBUG 5037 Channel = (UCHAR)(deviceExtension->Channel + lChannel); 5038 5039 KdPrint2((PRINT_PREFIX " cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c)); 5040 #endif //_DEBUG 5041 5042 if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) || 5043 (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) || 5044 (deviceExtension->HwFlags & UNIATA_AHCI)) { 5045 DmaTransfer = TRUE; 5046 KdPrint2((PRINT_PREFIX " DmaTransfer = TRUE\n")); 5047 } 5048 5049 if (srb) { 5050 PathId = srb->PathId; 5051 TargetId = srb->TargetId; 5052 Lun = srb->Lun; 5053 } else { 5054 PathId = (UCHAR)c; 5055 TargetId = 5056 Lun = 0; 5057 goto enqueue_next_req; 5058 } 5059 5060 //ldev = GET_LDEV2(PathId, TargetId, Lun); 5061 DeviceNumber = (UCHAR)(TargetId); 5062 LunExt = chan->lun[DeviceNumber]; 5063 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE; 5064 KdPrint2((PRINT_PREFIX " dev_type %s\n", atapiDev ? "ATAPI" : "IDE")); 5065 5066 // check if we are in ISR DPC 5067 if(InDpc) { 5068 KdPrint2((PRINT_PREFIX " InDpc -> CTRFLAGS_INTR_DISABLED\n")); 5069 goto ServiceInterrupt; 5070 } 5071 5072 if (DmaTransfer) { 5073 dma_status = GetDmaStatus(deviceExtension, lChannel); 5074 } 5075 5076 if (!(chan->ExpectingInterrupt)) { 5077 5078 KdPrint2((PRINT_PREFIX " Unexpected interrupt for this channel.\n")); 5079 return FALSE; 5080 } 5081 5082 // change request state 5083 if(AtaReq) { 5084 OldReqState = AtaReq->ReqState; 5085 AtaReq->ReqState = REQ_STATE_PROCESSING_INTR; 5086 KdPrint2((PRINT_PREFIX " OldReqState = %x\n", OldReqState)); 5087 } 5088 5089 // We don't want using DPC for fast operations, like 5090 // DMA completion, sending CDB, short ATAPI transfers, etc. 5091 // !!!! BUT !!!! 5092 // We MUST use DPC, because of interprocessor synchronization 5093 // on multiprocessor platforms 5094 5095 if(DmaTransfer) 5096 goto ServiceInterrupt; 5097 5098 switch(OldReqState) { 5099 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR: 5100 KdPrint3((PRINT_PREFIX " EXPECTING_CMD_INTR\n")); 5101 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR: 5102 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2: 5103 case REQ_STATE_DPC_WAIT_BUSY0: 5104 case REQ_STATE_DPC_WAIT_BUSY1: 5105 KdPrint2((PRINT_PREFIX " continue service interrupt\n")); 5106 goto ServiceInterrupt; 5107 case REQ_STATE_ATAPI_DO_NOTHING_INTR: 5108 KdPrint2((PRINT_PREFIX " do nothing on interrupt\n")); 5109 return TRUE; 5110 } 5111 5112 if((!DmaTransfer && !atapiDev) || deviceExtension->DriverMustPoll) { 5113 KdPrint2((PRINT_PREFIX " service PIO HDD\n")); 5114 UseDpc = FALSE; 5115 } 5116 5117 #ifndef UNIATA_CORE 5118 5119 if(!UseDpc) 5120 goto ServiceInterrupt; 5121 5122 #ifdef UNIATA_USE_XXableInterrupts 5123 if(InDpc) { 5124 KdPrint2((PRINT_PREFIX " Unexpected InDpc\n")); 5125 ASSERT(FALSE); 5126 // shall never get here 5127 TimerValue = 1; 5128 goto CallTimerDpc; 5129 } 5130 5131 KdPrint2((PRINT_PREFIX " this is direct DPC call on DRQL\n")); 5132 if(AtaReq) { 5133 AtaReq->ReqState = REQ_STATE_DPC_INTR_REQ; 5134 KdPrint2((PRINT_PREFIX " ReqState -> REQ_STATE_DPC_INTR_REQ\n")); 5135 } else { 5136 KdPrint2((PRINT_PREFIX " DPC without AtaReq!!!\n")); 5137 } 5138 #else 5139 KdPrint2((PRINT_PREFIX "call service interrupt\n")); 5140 goto ServiceInterrupt; 5141 #endif // UNIATA_USE_XXableInterrupts 5142 5143 PostToDpc: 5144 5145 // Attention !!! 5146 // AtapiInterruptDpc() is called on DISPATCH_LEVEL 5147 // We always get here when are called from timer callback, which is invoked on DRQL. 5148 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release 5149 5150 KdPrint2((PRINT_PREFIX "AtapiInterrupt: start DPC init...\n")); 5151 // disable interrupts for this channel, 5152 // but avoid recursion and double-disable 5153 if(OldReqState != REQ_STATE_DPC_WAIT_BUSY1) { 5154 UniataExpectChannelInterrupt(chan, FALSE); 5155 AtapiDisableInterrupts(deviceExtension, lChannel); 5156 } 5157 // go to ISR DPC 5158 chan->ChannelCtrlFlags |= CTRFLAGS_DPC_REQ; 5159 5160 #ifdef UNIATA_USE_XXableInterrupts 5161 // Will lower IRQL to DISPATCH_LEVEL 5162 ScsiPortNotification(CallEnableInterrupts, HwDeviceExtension, 5163 /*c ?*/ AtapiInterruptDpc/*_1 : AtapiInterruptDpc_0*/); 5164 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DPC inited\n")); 5165 #else 5166 // Will raise IRQL to DIRQL 5167 AtapiQueueTimerDpc(HwDeviceExtension, c, 5168 AtapiInterruptDpc, 5169 TimerValue); 5170 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n")); 5171 #endif // UNIATA_USE_XXableInterrupts 5172 return TRUE; 5173 5174 #ifndef UNIATA_CORE 5175 CallTimerDpc: 5176 AtaReq->ReqState = REQ_STATE_PROCESSING_INTR; 5177 CallTimerDpc2: 5178 if(!InDpc && OldReqState != REQ_STATE_DPC_WAIT_BUSY1) { 5179 // we must block interrupts from this channel 5180 // If device generate new interrupt before we get to DPC, 5181 // ISR will assume, that it is NOT our interrupt 5182 AtapiDisableInterrupts(deviceExtension, lChannel); 5183 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC 5184 } 5185 // Will raise IRQL to DIRQL 5186 AtapiQueueTimerDpc(HwDeviceExtension, c, 5187 AtapiCallBack_X, 5188 TimerValue); 5189 return TRUE; 5190 #endif //UNIATA_CORE 5191 5192 ServiceInterrupt: 5193 5194 if(AtaReq && InDpc) { 5195 switch(AtaReq->ReqState) { 5196 case REQ_STATE_DPC_WAIT_DRQ0: 5197 goto PIO_wait_DRQ0; 5198 case REQ_STATE_DPC_WAIT_BUSY: 5199 goto PIO_wait_busy; 5200 case REQ_STATE_DPC_WAIT_DRQ: 5201 goto PIO_wait_DRQ; 5202 case REQ_STATE_DPC_WAIT_DRQ_ERR: 5203 goto continue_err; 5204 case REQ_STATE_DPC_WAIT_BUSY0: 5205 case REQ_STATE_DPC_WAIT_BUSY1: 5206 // continue normal execution 5207 break; 5208 } 5209 } 5210 #else 5211 ServiceInterrupt: 5212 #endif //UNIATA_CORE 5213 /* 5214 // make additional delay for old devices (if we are not in DPC) 5215 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4)) 5216 && 5217 !InDpc && 5218 !atapiDev && 5219 !(deviceExtension->HwFlags & UNIATA_SATA) 5220 ) { 5221 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n")); 5222 AtapiStallExecution(10); 5223 } 5224 */ 5225 5226 /* clear interrupt and get status */ 5227 if(deviceExtension->HwFlags & UNIATA_AHCI) { 5228 UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, srb); 5229 statusByte = (UCHAR)(AtaReq->ahci.in_status & IDE_STATUS_MASK); 5230 5231 if(chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB)) { 5232 KdPrint3((PRINT_PREFIX "Err intr (%#x), SE (%#x)\n", 5233 chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB), 5234 chan->AhciLastSError)); 5235 if(chan->AhciLastIS & ~ATA_AHCI_P_IX_OF) { 5236 5237 if((chan->AhciLastIS == ATA_AHCI_P_IX_INF) && 5238 !(statusByte & IDE_STATUS_ERROR) && 5239 !chan->AhciLastSError && 5240 srb && (srb->SrbFlags & SRB_FLAGS_DATA_IN) 5241 ) { 5242 KdPrint3((PRINT_PREFIX "ATA_AHCI_P_IX_INF on READ, assume underflow\n")); 5243 // continue processing in regular way 5244 } else { 5245 5246 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF)); 5247 // We have some other error except Overflow 5248 // Just signal ERROR, operation will be aborted in ERROR branch. 5249 statusByte |= IDE_STATUS_ERROR; 5250 AtaReq->ahci.in_serror = chan->AhciLastSError; 5251 if(chan->AhciLastSError & (ATA_SE_HANDSHAKE_ERR | ATA_SE_LINKSEQ_ERR | ATA_SE_TRANSPORT_ERR | ATA_SE_UNKNOWN_FIS)) { 5252 KdPrint2((PRINT_PREFIX "Unrecoverable\n")); 5253 NoRetry = TRUE; 5254 } 5255 } 5256 } else { 5257 // We have only Overflow. Abort operation and continue 5258 #ifdef _DEBUG 5259 UniataDumpAhciPortRegs(chan); 5260 #endif 5261 if(!UniataAhciAbortOperation(chan)) { 5262 KdPrint2((PRINT_PREFIX "need UniataAhciReset\n")); 5263 } 5264 #ifdef _DEBUG 5265 UniataDumpAhciPortRegs(chan); 5266 #endif 5267 UniataAhciWaitCommandReady(chan, 10); 5268 } 5269 } 5270 5271 } else { 5272 GetBaseStatus(chan, statusByte); 5273 } 5274 if(atapiDev) { 5275 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte)); 5276 } else { 5277 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Entered with status (%#x)\n", statusByte)); 5278 } 5279 5280 if(!UseDpc) { 5281 KdPrint2((PRINT_PREFIX " operate like in DPC\n")); 5282 InDpc = TRUE; 5283 } 5284 5285 if (!atapiDev) { 5286 // IDE 5287 if(deviceExtension->HwFlags & UNIATA_AHCI) { 5288 KdPrint3((PRINT_PREFIX " AHCI branch (IDE)\n")); 5289 } else 5290 if (statusByte & IDE_STATUS_BUSY) { 5291 if (deviceExtension->DriverMustPoll) { 5292 // Crashdump is polling and we got caught with busy asserted. 5293 // Just go away, and we will be polled again shortly. 5294 KdPrint2((PRINT_PREFIX " Hit BUSY while polling during crashdump.\n")); 5295 goto ReturnEnableIntr; 5296 } 5297 try_dpc_wait: 5298 // Ensure BUSY is non-asserted. 5299 // make a very small idle before falling to DPC 5300 k = (InDpc && UseDpc) ? 1000 : 2; 5301 5302 for (i = 0; i < k; i++) { 5303 5304 GetBaseStatus(chan, statusByte); 5305 if (!(statusByte & IDE_STATUS_BUSY)) { 5306 break; 5307 } 5308 AtapiStallExecution(10); 5309 } 5310 5311 if (!InDpc && UseDpc && i == 2) { 5312 5313 KdPrint2((PRINT_PREFIX " BUSY on entry. Status %#x, Base IO %#x\n", statusByte)); 5314 5315 TimerValue = 50; 5316 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0; 5317 5318 #ifndef UNIATA_CORE 5319 goto PostToDpc; 5320 #else //UNIATA_CORE 5321 AtapiStallExecution(TimerValue); 5322 goto ServiceInterrupt; 5323 #endif //UNIATA_CORE 5324 } else 5325 if (InDpc && i == k) { 5326 // reset the controller. 5327 KdPrint2((PRINT_PREFIX 5328 " Resetting due to BUSY on entry - %#x.\n", 5329 statusByte)); 5330 goto IntrPrepareResetController; 5331 } 5332 } 5333 } else { 5334 // ATAPI 5335 if(!LunExt->IdentifyData.MajorRevision && 5336 InDpc && 5337 /*!atapiDev &&*/ 5338 !(deviceExtension->HwFlags & UNIATA_SATA) 5339 ) { 5340 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n")); 5341 //AtapiStallExecution(10); 5342 } 5343 if(deviceExtension->HwFlags & UNIATA_AHCI) { 5344 KdPrint3((PRINT_PREFIX " AHCI branch (ATAPI)\n")); 5345 } else { 5346 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); 5347 KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason)); 5348 } 5349 5350 if (statusByte & IDE_STATUS_BUSY) { 5351 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {} 5352 /* 5353 #ifndef UNIATA_CORE 5354 // This is just workaround 5355 // We should DISABLE interrupts before entering WAIT state 5356 UniataExpectChannelInterrupt(chan, TRUE); 5357 #endif //UNIATA_CORE 5358 */ 5359 KdPrint3((PRINT_PREFIX " BUSY on ATAPI device, waiting %d us\n", LunExt->AtapiReadyWaitDelay)); 5360 #ifndef UNIATA_CORE 5361 if(LunExt->AtapiReadyWaitDelay && (LunExt->AtapiReadyWaitDelay > g_opt_MaxIsrWait) && !InDpc && UseDpc) { 5362 TimerValue = LunExt->AtapiReadyWaitDelay; 5363 KdPrint2((PRINT_PREFIX " too long wait: ISR -> DPC (0)\n")); 5364 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0; 5365 goto CallTimerDpc2; 5366 } 5367 #endif //UNIATA_CORE 5368 TimerValue = 10; 5369 for(k=20; k; k--) { 5370 GetBaseStatus(chan, statusByte); 5371 KdPrint3((PRINT_PREFIX " status re-check %#x\n", statusByte)); 5372 KdPrint3((PRINT_PREFIX " Error reg (%#x)\n", 5373 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Error))); 5374 if (!(statusByte & IDE_STATUS_BUSY)) { 5375 KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n")); 5376 break; 5377 } 5378 TotalTimerValue += TimerValue; 5379 if(k <= 1) { 5380 KdPrint3((PRINT_PREFIX " too long wait -> DPC\n")); 5381 if(!InDpc) { 5382 KdPrint2((PRINT_PREFIX " too long wait: ISR -> DPC\n")); 5383 TimerValue = 100; 5384 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0; 5385 } else { 5386 KdPrint2((PRINT_PREFIX " too long wait: DPC -> DPC\n")); 5387 TimerValue = 1000; 5388 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY1; 5389 } 5390 #ifndef UNIATA_CORE 5391 if(UseDpc) { 5392 if(!LunExt->AtapiReadyWaitDelay) { 5393 LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3; 5394 } 5395 goto CallTimerDpc2; 5396 } 5397 #endif //UNIATA_CORE 5398 } 5399 5400 AtapiStallExecution(TimerValue); 5401 TimerValue += 10; 5402 } 5403 if(!LunExt->AtapiReadyWaitDelay) { 5404 LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3; 5405 KdPrint2((PRINT_PREFIX " store AtapiReadyWaitDelay: %d\n", LunExt->AtapiReadyWaitDelay)); 5406 } 5407 if (statusByte & IDE_STATUS_BUSY) { 5408 KdPrint3((PRINT_PREFIX " expecting intr + BUSY (2), try DPC wait\n")); 5409 goto try_dpc_wait; 5410 } 5411 } 5412 } 5413 5414 if(AtaReq && DmaTransfer && !(deviceExtension->HwFlags & UNIATA_AHCI)) { 5415 switch(OldReqState) { 5416 case REQ_STATE_EARLY_INTR: 5417 case REQ_STATE_DPC_WAIT_BUSY0: 5418 5419 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) { 5420 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DMA still active\n")); 5421 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/); 5422 } 5423 break; 5424 } 5425 } 5426 5427 //retry_check: 5428 // Check for error conditions. 5429 if ((statusByte & IDE_STATUS_ERROR) || 5430 (dma_status & BM_STATUS_ERR)) { 5431 5432 if(deviceExtension->HwFlags & UNIATA_AHCI) { 5433 error = AtaReq->ahci.in_error; 5434 // wait ready 5435 #ifdef _DEBUG 5436 UniataDumpAhciPortRegs(chan); 5437 #endif 5438 if(!UniataAhciAbortOperation(chan)) { 5439 KdPrint2((PRINT_PREFIX "need UniataAhciReset\n")); 5440 } 5441 // clear interrupts again 5442 UniataAhciWaitCommandReady(chan, 10); 5443 #ifdef _DEBUG 5444 UniataDumpAhciPortRegs(chan); 5445 #endif 5446 UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED); 5447 if(NoRetry) { 5448 AtaReq->retry += MAX_RETRIES; 5449 if(!error && (statusByte & IDE_STATUS_ERROR)) { 5450 KdPrint2((PRINT_PREFIX "AtapiInterrupt: force error status\n")); 5451 error |= IDE_STATUS_ERROR; 5452 } 5453 } 5454 #ifdef _DEBUG 5455 UniataDumpAhciPortRegs(chan); 5456 #endif 5457 } else { 5458 error = AtapiReadPort1(chan, IDX_IO1_i_Error); 5459 } 5460 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Error %#x\n", error)); 5461 /* 5462 if(error & IDE_STATUS_CORRECTED_ERROR) { 5463 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n")); 5464 statusByte &= ~IDE_STATUS_ERROR; 5465 goto retry_check; 5466 } 5467 */ 5468 if(AtaReq) { 5469 KdPrint2((PRINT_PREFIX " Bad Lba %#I64x\n", AtaReq->lba)); 5470 } else { 5471 KdPrint2((PRINT_PREFIX " Bad Lba unknown\n")); 5472 } 5473 5474 if(deviceExtension->HwFlags & UNIATA_AHCI) { 5475 KdPrint2((PRINT_PREFIX " no wait ready after error\n")); 5476 } else 5477 if(!atapiDev) { 5478 KdPrint2((PRINT_PREFIX " wait 100 ready after IDE error\n")); 5479 AtapiStallExecution(100); 5480 } else { 5481 KdPrint2((PRINT_PREFIX " wait 10 ready after ATAPI error\n")); 5482 AtapiStallExecution(10); 5483 } 5484 continue_err: 5485 5486 KdPrint3((PRINT_PREFIX " Intr on DRQ %x\n", 5487 LunExt->DeviceFlags & DFLAGS_INT_DRQ)); 5488 5489 for (k = atapiDev ? 0 : 200; k; k--) { 5490 GetBaseStatus(chan, statusByte); 5491 if (!(statusByte & IDE_STATUS_DRQ)) { 5492 AtapiStallExecution(50); 5493 } else { 5494 break; 5495 } 5496 } 5497 5498 if (!atapiDev) { 5499 /* if this is a UDMA CRC error, reinject request */ 5500 5501 AtaReq->retry++; 5502 if(AtaReq->retry < MAX_RETRIES) { 5503 #ifdef IO_STATISTICS 5504 chan->lun[DeviceNumber]->ModeErrorCount[AtaReq->retry]++; 5505 #endif //IO_STATISTICS 5506 if(DmaTransfer /*&& 5507 (error & IDE_ERROR_ICRC)*/) { 5508 KdPrint2((PRINT_PREFIX "Errors in DMA mode\n")); 5509 if(AtaReq->retry < MAX_RETRIES) { 5510 //fallback_pio: 5511 if(!(deviceExtension->HwFlags & UNIATA_AHCI)) { 5512 //AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 5513 // Downrate will happen in AtapiDmaReinit(), try UDMA-2 for HDD only 5514 AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE; 5515 } 5516 AtaReq->ReqState = REQ_STATE_QUEUED; 5517 goto reenqueue_req; 5518 } 5519 } else { 5520 if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) { 5521 AtaReq->retry++; 5522 } 5523 KdPrint2((PRINT_PREFIX "Errors in PIO mode\n")); 5524 } 5525 } 5526 } else { 5527 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); 5528 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason)); 5529 5530 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 5531 if(deviceExtension->HwFlags & UNIATA_AHCI) { 5532 // Do nothing here 5533 } else 5534 if(deviceExtension->HwFlags & UNIATA_SATA) { 5535 UniataSataClearErr(HwDeviceExtension, lChannel, UNIATA_SATA_IGNORE_CONNECT, 0); 5536 } 5537 } 5538 5539 if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) && 5540 ((error >> 4) == SCSI_SENSE_HARDWARE_ERROR)) { 5541 if(AtaReq->retry < MAX_RETRIES) { 5542 //fallback_pio: 5543 // Downrate will happen in AtapiDmaReinit(), use PIO immediately for ATAPI 5544 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 5545 AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE; 5546 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE; 5547 AtaReq->ReqState = REQ_STATE_QUEUED; 5548 goto reenqueue_req; 5549 } 5550 } else { 5551 if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) { 5552 AtaReq->retry++; 5553 } 5554 KdPrint3((PRINT_PREFIX "Errors in PIO mode\n")); 5555 } 5556 } 5557 5558 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error\n")); 5559 if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) { 5560 // Fail this request. 5561 status = SRB_STATUS_ERROR; 5562 goto CompleteRequest; 5563 } else { 5564 KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n")); 5565 } 5566 } else 5567 if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE_LBA48) { 5568 KdPrint2((PRINT_PREFIX "DMA doesn't work right with LBA48\n")); 5569 deviceExtension->HbaCtrlFlags |= HBAFLAGS_DMA_DISABLED_LBA48; 5570 } else 5571 if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE) { 5572 #ifdef IO_STATISTICS 5573 KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n")); 5574 KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n", 5575 AtaReq->retry, 5576 LunExt->RecoverCount[AtaReq->retry], 5577 LunExt->BlockIoCount 5578 )); 5579 LunExt->RecoverCount[AtaReq->retry]++; 5580 if(LunExt->RecoverCount[AtaReq->retry] >= LunExt->BlockIoCount/3 || 5581 (deviceExtension->HwFlags & UNIATA_NO80CHK) 5582 ) { 5583 #else 5584 if(deviceExtension->HwFlags & UNIATA_NO80CHK) { 5585 #endif //IO_STATISTICS 5586 KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", LunExt->TransferMode)); 5587 LunExt->LimitedTransferMode = 5588 LunExt->TransferMode; 5589 } 5590 } 5591 #ifdef IO_STATISTICS 5592 if(AtaReq->bcount) { 5593 // we need stats for Read/Write operations 5594 LunExt->BlockIoCount++; 5595 } 5596 LunExt->IoCount++; 5597 #endif //IO_STATISTICS 5598 5599 continue_PIO: 5600 5601 // check reason for this interrupt. 5602 if (atapiDev) { 5603 5604 KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI branch\n")); 5605 // ATAPI branch 5606 5607 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); 5608 KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason)); 5609 if(DmaTransfer) { 5610 wordsThisInterrupt = DEV_BSIZE/2*512; 5611 } else { 5612 wordsThisInterrupt = DEV_BSIZE/2; 5613 } 5614 5615 } else { 5616 5617 // ATA branch 5618 5619 if(DmaTransfer) { 5620 // simulate DRQ for DMA transfers 5621 statusByte |= IDE_STATUS_DRQ; 5622 } 5623 if (statusByte & IDE_STATUS_DRQ) { 5624 5625 if(DmaTransfer) { 5626 wordsThisInterrupt = DEV_BSIZE/2*512; 5627 } else 5628 if (LunExt->MaximumBlockXfer) { 5629 wordsThisInterrupt = DEV_BSIZE/2 * LunExt->MaximumBlockXfer; 5630 } 5631 5632 if (srb->SrbFlags & SRB_FLAGS_DATA_IN) { 5633 5634 interruptReason = ATAPI_IR_IO_toHost; 5635 5636 } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) { 5637 interruptReason = ATAPI_IR_IO_toDev; 5638 5639 } else { 5640 status = SRB_STATUS_ERROR; 5641 goto CompleteRequest; 5642 } 5643 5644 } else if (statusByte & IDE_STATUS_BUSY) { 5645 5646 //AtapiEnableInterrupts(deviceExtension, lChannel); 5647 KdPrint2((PRINT_PREFIX "AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n")); 5648 return FALSE; 5649 5650 } else { 5651 5652 KdPrint2((PRINT_PREFIX "AtapiInterrupt: !DRQ, !BUSY, WordsLeft %#x\n", AtaReq->WordsLeft)); 5653 if (AtaReq->WordsLeft) { 5654 5655 // Funky behaviour seen with PCI IDE (not all, just one). 5656 PIO_wait_DRQ0: 5657 // The ISR hits with DRQ low, but comes up later. 5658 for (k = 0; k < 5000; k++) { 5659 GetBaseStatus(chan, statusByte); 5660 if (statusByte & IDE_STATUS_DRQ) { 5661 break; 5662 } 5663 if(!InDpc) { 5664 // goto DPC 5665 AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ0; 5666 TimerValue = 100; 5667 KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq0)\n")); 5668 #ifndef UNIATA_CORE 5669 goto PostToDpc; 5670 #else //UNIATA_CORE 5671 AtapiStallExecution(TimerValue); 5672 goto ServiceInterrupt; 5673 #endif //UNIATA_CORE 5674 } 5675 AtapiStallExecution(100); 5676 } 5677 if (k == 5000) { 5678 // reset the controller. 5679 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n", 5680 statusByte)); 5681 IntrPrepareResetController: 5682 AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_CURRENT); 5683 goto ReturnEnableIntr; 5684 5685 } else { 5686 interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? ATAPI_IR_IO_toHost : ATAPI_IR_IO_toDev; 5687 } 5688 5689 } else { 5690 // Command complete - verify, write, or the SMART enable/disable. 5691 // Also get_media_status 5692 interruptReason = ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd; 5693 } 5694 } 5695 } 5696 5697 KdPrint2((PRINT_PREFIX "AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason, statusByte)); 5698 if(deviceExtension->HwFlags & UNIATA_AHCI) { 5699 KdPrint2((PRINT_PREFIX " AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq->WordsTransfered, AtaReq->WordsLeft)); 5700 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) { 5701 //status = SRB_STATUS_DATA_OVERRUN; 5702 DataOverrun = TRUE; 5703 } else { 5704 status = SRB_STATUS_SUCCESS; 5705 }*/ 5706 if(AtaReq->WordsTransfered >= AtaReq->WordsLeft) { 5707 AtaReq->WordsLeft = 0; 5708 } else { 5709 AtaReq->WordsLeft -= AtaReq->WordsTransfered; 5710 } 5711 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) { 5712 // status = SRB_STATUS_DATA_OVERRUN; 5713 //} 5714 status = SRB_STATUS_SUCCESS; 5715 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; 5716 goto CompleteRequest; 5717 } else 5718 if ((interruptReason == ATAPI_IR_COD_Cmd) && (statusByte & IDE_STATUS_DRQ)) { 5719 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) { 5720 AtapiDmaDBPreSync(HwDeviceExtension, chan, srb); 5721 } 5722 // Write the packet. 5723 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n")); 5724 // Send CDB to device. 5725 WriteBuffer(chan, (PUSHORT)srb->Cdb, 5726 LunExt->IdentifyData.AtapiCmdSize ? 8 : 6, 5727 /*0*/ PIO0_TIMING); 5728 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR; 5729 5730 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) { 5731 KdPrint2((PRINT_PREFIX "AtapiInterrupt: AtapiDmaStart().\n")); 5732 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, srb); 5733 } 5734 5735 goto ReturnEnableIntr; 5736 5737 } else if ((interruptReason == ATAPI_IR_IO_toDev) && (statusByte & IDE_STATUS_DRQ)) { 5738 5739 // Write the data. 5740 if (atapiDev) { 5741 5742 // Pick up bytes to transfer and convert to words. 5743 wordCount = 5744 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow); 5745 5746 wordCount |= 5747 (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8; 5748 5749 // Covert bytes to words. 5750 wordCount >>= 1; 5751 KdPrint2((PRINT_PREFIX "AtapiInterrupt: get W wordCount %#x\n", wordCount)); 5752 5753 if (wordCount != AtaReq->WordsLeft) { 5754 KdPrint2((PRINT_PREFIX 5755 "AtapiInterrupt: %d words requested; %d words xferred\n", 5756 AtaReq->WordsLeft, 5757 wordCount)); 5758 } 5759 5760 // Verify this makes sense. 5761 if (wordCount > AtaReq->WordsLeft) { 5762 wordCount = AtaReq->WordsLeft; 5763 KdPrint2((PRINT_PREFIX 5764 "AtapiInterrupt: Write underrun\n")); 5765 DataOverrun = TRUE; 5766 } 5767 5768 } else { 5769 5770 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256. 5771 if (AtaReq->WordsLeft < wordsThisInterrupt) { 5772 // Transfer only words requested. 5773 wordCount = AtaReq->WordsLeft; 5774 } else { 5775 // Transfer next block. 5776 wordCount = wordsThisInterrupt; 5777 } 5778 } 5779 5780 if (DmaTransfer && 5781 (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) { 5782 //ASSERT(AtaReq->WordsLeft == wordCount); 5783 if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) { 5784 KdPrint2((PRINT_PREFIX 5785 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount)); 5786 if(AtaReq->WordsLeft > wordCount) { 5787 AtaReq->WordsLeft -= wordCount; 5788 AtaReq->WordsTransfered += wordCount; 5789 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR; 5790 goto ReturnEnableIntr; 5791 } 5792 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/); 5793 } 5794 AtaReq->WordsTransfered = AtaReq->WordsLeft; 5795 AtaReq->WordsLeft = 0; 5796 status = SRB_STATUS_SUCCESS; 5797 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; 5798 goto CompleteRequest; 5799 } 5800 5801 // Ensure that this is a write command. 5802 if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) { 5803 5804 KdPrint2((PRINT_PREFIX 5805 "AtapiInterrupt: Write interrupt\n")); 5806 5807 statusByte = WaitOnBusy(chan); 5808 5809 if (/*atapiDev || */ !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/ 5810 || (wordCount & 1)) { 5811 5812 WriteBuffer(chan, 5813 AtaReq->DataBuffer, 5814 wordCount, 5815 UniataGetPioTiming(LunExt)); 5816 } else { 5817 5818 WriteBuffer2(chan, 5819 (PULONG)(AtaReq->DataBuffer), 5820 wordCount / 2, 5821 UniataGetPioTiming(LunExt)); 5822 } 5823 } else { 5824 5825 KdPrint3((PRINT_PREFIX 5826 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n", 5827 interruptReason, 5828 srb)); 5829 5830 // Fail this request. 5831 status = SRB_STATUS_ERROR; 5832 if(!wordCount && atapiDev && (srb->Cdb[0] != SCSIOP_REQUEST_SENSE)) { 5833 // some devices feel bad after incorrect commands and may need reset 5834 KdPrint2((PRINT_PREFIX 5835 "AtapiInterrupt: Try ATAPI reset\n")); 5836 5837 AtapiDisableInterrupts(deviceExtension, lChannel); 5838 AtapiSoftReset(chan, DeviceNumber); 5839 AtapiEnableInterrupts(deviceExtension, lChannel); 5840 status = SRB_STATUS_BUS_RESET; 5841 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 5842 5843 // goto IntrPrepareResetController; 5844 } 5845 goto CompleteRequest; 5846 } 5847 // Advance data buffer pointer and bytes left. 5848 AtaReq->DataBuffer += wordCount; 5849 AtaReq->WordsLeft -= wordCount; 5850 AtaReq->WordsTransfered += wordCount; 5851 5852 if (atapiDev) { 5853 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR; 5854 } 5855 5856 goto ReturnEnableIntr; 5857 5858 } else if (interruptReason == ATAPI_IR_IO_toHost && (statusByte & IDE_STATUS_DRQ)) { 5859 5860 continue_read_drq: 5861 5862 if (atapiDev) { 5863 5864 // Pick up bytes to transfer and convert to words. 5865 wordCount = 5866 (ULONG)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow) | 5867 ((ULONG)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8); 5868 5869 // Convert bytes to words. 5870 KdPrint2((PRINT_PREFIX "AtapiInterrupt: get R byteCount %#x\n", wordCount)); 5871 wordCount >>= 1; 5872 /* 5873 When ATAPI 64k PIO read is requested we may have 0xfffe byte 5874 count reported for 0x10000 bytes in single interrupt. 5875 It is not allowed to read entire 64k block with DwordIo intead of 5876 wait for last word. 5877 */ 5878 if (wordCount != AtaReq->WordsLeft) { 5879 KdPrint2((PRINT_PREFIX 5880 "AtapiInterrupt: %d words requested; %d words xferred\n", 5881 AtaReq->WordsLeft, 5882 wordCount)); 5883 } 5884 5885 // Verify this makes sense. 5886 if (wordCount > AtaReq->WordsLeft) { 5887 wordCount = AtaReq->WordsLeft; 5888 DataOverrun = TRUE; 5889 } 5890 5891 } else { 5892 5893 // Check if words left is at least 256. 5894 if (AtaReq->WordsLeft < wordsThisInterrupt) { 5895 // Transfer only words requested. 5896 wordCount = AtaReq->WordsLeft; 5897 } else { 5898 // Transfer next block. 5899 wordCount = wordsThisInterrupt; 5900 } 5901 } 5902 5903 if(DmaTransfer && 5904 (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) { 5905 if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) { 5906 KdPrint2((PRINT_PREFIX 5907 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount)); 5908 if(AtaReq->WordsLeft > wordCount) { 5909 AtaReq->WordsLeft -= wordCount; 5910 AtaReq->WordsTransfered += wordCount; 5911 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR; 5912 goto ReturnEnableIntr; 5913 } 5914 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/); 5915 } 5916 //ASSERT(AtaReq->WordsLeft == wordCount); 5917 AtaReq->WordsTransfered = AtaReq->WordsLeft; 5918 AtaReq->WordsLeft = 0; 5919 status = SRB_STATUS_SUCCESS; 5920 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; 5921 goto CompleteRequest; 5922 } 5923 // Ensure that this is a read command. 5924 if (srb->SrbFlags & SRB_FLAGS_DATA_IN) { 5925 5926 /* KdPrint2(( 5927 "AtapiInterrupt: Read interrupt\n"));*/ 5928 5929 statusByte = WaitOnBusy(chan); 5930 5931 if(wordCount&1 && atapiDev && (g_opt_VirtualMachine == VM_BOCHS)) { 5932 KdPrint2((PRINT_PREFIX 5933 "IdeIntr: unaligned ATAPI %#x Words\n", wordCount)); 5934 } else 5935 if(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) { 5936 KdPrint2((PRINT_PREFIX 5937 "IdeIntr: pre-Read %#x Dwords\n", wordCount/2)); 5938 5939 ReadBuffer2(chan, 5940 (PULONG)(AtaReq->DataBuffer), 5941 wordCount / 2, 5942 UniataGetPioTiming(LunExt)); 5943 // Advance data buffer pointer and bytes left. 5944 AtaReq->DataBuffer += wordCount & ~1; 5945 AtaReq->WordsLeft -= wordCount & ~1; 5946 AtaReq->WordsTransfered += wordCount & ~1; 5947 wordCount &= 1; 5948 } 5949 if (wordCount) { 5950 KdPrint2((PRINT_PREFIX 5951 "IdeIntr: Read %#x words\n", wordCount)); 5952 5953 ReadBuffer(chan, 5954 AtaReq->DataBuffer, 5955 wordCount, 5956 UniataGetPioTiming(LunExt)); 5957 } 5958 5959 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)-1) )); 5960 //KdDump(AtaReq->DataBuffer, wordCount*2); 5961 if(srb && atapiDev && srb->Cdb[0] == SCSIOP_REQUEST_SENSE) { 5962 KdDump(AtaReq->DataBuffer, wordCount*2); 5963 } 5964 5965 GetBaseStatus(chan, statusByte); 5966 KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte)); 5967 5968 if(DataOverrun) { 5969 KdPrint2((PRINT_PREFIX " DataOverrun\n")); 5970 AtapiSuckPort2(chan); 5971 GetBaseStatus(chan, statusByte); 5972 } 5973 5974 if(statusByte & IDE_STATUS_BUSY) { 5975 for (i = 0; i < 2; i++) { 5976 AtapiStallExecution(10); 5977 GetBaseStatus(chan, statusByte); 5978 if (!(statusByte & IDE_STATUS_BUSY)) { 5979 break; 5980 } 5981 } 5982 } 5983 5984 } else { 5985 5986 KdPrint3((PRINT_PREFIX 5987 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n", 5988 interruptReason, 5989 srb)); 5990 5991 // Fail this request. 5992 status = SRB_STATUS_ERROR; 5993 goto CompleteRequest; 5994 } 5995 //continue_atapi_pio_read: 5996 // Advance data buffer pointer and bytes left. 5997 AtaReq->DataBuffer += wordCount; 5998 AtaReq->WordsLeft -= wordCount; 5999 AtaReq->WordsTransfered += wordCount; 6000 6001 // Check for read command complete. 6002 if (AtaReq->WordsLeft == 0) { 6003 6004 KdPrint2((PRINT_PREFIX "AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n")); 6005 if (atapiDev) { 6006 6007 if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM) { 6008 6009 // Work around to make many atapi devices return correct sector size 6010 // of 2048. Also certain devices will have sector count == 0x00, check 6011 // for that also. 6012 if (srb->Cdb[0] == SCSIOP_READ_CAPACITY) { 6013 6014 AtaReq->DataBuffer -= AtaReq->WordsTransfered; 6015 if (AtaReq->DataBuffer[0] == 0x00) { 6016 *((ULONG *) &(AtaReq->DataBuffer[0])) = 0xFFFFFF7F; 6017 } 6018 6019 *((ULONG *) &(AtaReq->DataBuffer[2])) = 0x00080000; 6020 AtaReq->DataBuffer += AtaReq->WordsTransfered; 6021 } 6022 #ifndef UNIATA_INIT_CHANGERS 6023 else 6024 if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) { 6025 6026 KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status)); 6027 // Bingo!! 6028 AtapiHwInitializeChanger (HwDeviceExtension, 6029 srb, 6030 (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer); 6031 LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED; 6032 KdPrint2((PRINT_PREFIX " set DFLAGS_CHANGER_INITED\n")); 6033 } 6034 #endif // UNIATA_INIT_CHANGERS 6035 } 6036 GetStatus(chan, statusByte); 6037 if(!(statusByte & IDE_STATUS_BUSY)) { 6038 // Assume command is completed if BUSY is cleared 6039 // and all data read 6040 // Optionally, we may receive COMPLETE interrupt later and 6041 // treat it as unexpected 6042 KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete ? status %x\n", statusByte)); 6043 6044 status = SRB_STATUS_SUCCESS; 6045 goto CompleteRequest; 6046 } 6047 6048 } else { 6049 6050 /* 6051 // Completion for IDE drives. 6052 if (AtaReq->WordsLeft) { 6053 status = SRB_STATUS_DATA_OVERRUN; 6054 } else { 6055 status = SRB_STATUS_SUCCESS; 6056 } 6057 6058 goto CompleteRequest; 6059 */ 6060 status = SRB_STATUS_SUCCESS; 6061 goto CompleteRequest; 6062 6063 } 6064 } else { 6065 if (atapiDev) { 6066 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR; 6067 GetStatus(chan, statusByte); 6068 if(!(statusByte & IDE_STATUS_BUSY)) { 6069 // Assume command is completed if BUSY is cleared 6070 // even if NOT all data read 6071 // Optionally, we may receive COMPLETE interrupt later and 6072 // treat it as unexpected 6073 KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete + underrun ? status %x\n", statusByte)); 6074 6075 status = SRB_STATUS_SUCCESS; 6076 goto CompleteRequest; 6077 } 6078 } else { 6079 if(!atapiDev && !DataOverrun && (srb->SrbFlags & SRB_FLAGS_DATA_IN) && 6080 ((statusByte & ~IDE_STATUS_INDEX) == (IDE_STATUS_IDLE | IDE_STATUS_DRQ))) { 6081 KdPrint2((PRINT_PREFIX " HDD read data ready \n")); 6082 goto continue_read_drq; 6083 } 6084 } 6085 } 6086 6087 goto ReturnEnableIntr; 6088 6089 } else if (interruptReason == (ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd) && !(statusByte & IDE_STATUS_DRQ)) { 6090 6091 KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n")); 6092 // Command complete. We exactly know this because of IReason. 6093 6094 if(DmaTransfer) { 6095 KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n")); 6096 AtaReq->WordsTransfered += AtaReq->WordsLeft; 6097 AtaReq->WordsLeft = 0; 6098 } else { 6099 KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was PIO\n")); 6100 6101 wordCount = AtaReq->WordsLeft; 6102 // Advance data buffer pointer and bytes left. 6103 AtaReq->DataBuffer += wordCount; 6104 AtaReq->WordsLeft -= wordCount; 6105 AtaReq->WordsTransfered += wordCount; 6106 6107 KdPrint2((PRINT_PREFIX "AtapiInterrupt: wordCount %#x, WordsTransfered %#x\n", wordCount, AtaReq->WordsTransfered)); 6108 6109 } 6110 //if (AtaReq->WordsLeft) { 6111 // status = SRB_STATUS_DATA_OVERRUN; 6112 //} else { 6113 status = SRB_STATUS_SUCCESS; 6114 //} 6115 6116 #ifdef UNIATA_DUMP_ATAPI 6117 if(srb && 6118 srb->SrbFlags & SRB_FLAGS_DATA_IN) { 6119 UCHAR ScsiCommand; 6120 PCDB Cdb; 6121 PCHAR CdbData; 6122 PCHAR ModeSelectData; 6123 ULONG CdbDataLen; 6124 PSCSI_REQUEST_BLOCK Srb = srb; 6125 6126 Cdb = (PCDB)(Srb->Cdb); 6127 ScsiCommand = Cdb->CDB6.OperationCode; 6128 CdbData = (PCHAR)(Srb->DataBuffer); 6129 CdbDataLen = Srb->DataTransferLength; 6130 6131 if(CdbDataLen > 0x1000) { 6132 CdbDataLen = 0x1000; 6133 } 6134 6135 KdPrint(("--\n")); 6136 KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID)); 6137 KdPrint2(("P:T:D=%d:%d:%d\n", 6138 Srb->PathId, 6139 Srb->TargetId, 6140 Srb->Lun)); 6141 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand)); 6142 KdDump(Cdb, 16); 6143 6144 if(ScsiCommand == SCSIOP_MODE_SENSE) { 6145 KdPrint(("ModeSense 6\n")); 6146 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData; 6147 ModeSelectData = CdbData+4; 6148 KdDump(CdbData, CdbDataLen); 6149 } else 6150 if(ScsiCommand == SCSIOP_MODE_SENSE10) { 6151 KdPrint(("ModeSense 10\n")); 6152 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData; 6153 ModeSelectData = CdbData+8; 6154 KdDump(CdbData, CdbDataLen); 6155 } else { 6156 if(srb->SrbFlags & SRB_FLAGS_DATA_IN) { 6157 KdPrint(("Read buffer from device:\n")); 6158 KdDump(CdbData, CdbDataLen); 6159 } 6160 } 6161 KdPrint(("--\n")); 6162 } 6163 #endif //UNIATA_DUMP_ATAPI 6164 6165 CompleteRequest: 6166 6167 KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, srbstatus %x\n", status)); 6168 // Check and see if we are processing our secret (mechanism status/request sense) srb 6169 6170 if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) { 6171 KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq->WordsLeft)); 6172 status = SRB_STATUS_DATA_OVERRUN; 6173 } 6174 6175 if (AtaReq->OriginalSrb) { 6176 6177 ULONG srbStatus; 6178 6179 KdPrint2((PRINT_PREFIX "AtapiInterrupt: OriginalSrb != NULL\n")); 6180 if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) { 6181 #ifdef UNIATA_INIT_CHANGERS 6182 // We can get here only when UNIATA_INIT_CHANGERS is defined 6183 KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status)); 6184 if (status == SRB_STATUS_SUCCESS) { 6185 // Bingo!! 6186 AtapiHwInitializeChanger (HwDeviceExtension, 6187 srb, 6188 (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer); 6189 6190 // Get ready to issue the original srb 6191 srb = AtaReq->Srb = AtaReq->OriginalSrb; 6192 AtaReq->OriginalSrb = NULL; 6193 6194 } else { 6195 // failed! Get the sense key and maybe try again 6196 srb = AtaReq->Srb = BuildRequestSenseSrb ( 6197 HwDeviceExtension, 6198 AtaReq->OriginalSrb); 6199 } 6200 /* 6201 // do not enable interrupts in DPC, do not waste time, do it now! 6202 if(UseDpc && chan->DisableIntr) { 6203 AtapiEnableInterrupts(HwDeviceExtension, c); 6204 UseDpc = FALSE; 6205 RestoreUseDpc = TRUE; 6206 } 6207 */ 6208 srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL); 6209 6210 KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt)); 6211 6212 if (srbStatus == SRB_STATUS_PENDING) { 6213 KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n")); 6214 goto ReturnEnableIntr; 6215 } 6216 /* 6217 if(RestoreUseDpc) { 6218 // restore state on error 6219 UseDpc = TRUE; 6220 AtapiDisableInterrupts(HwDeviceExtension, c); 6221 } 6222 */ 6223 #else 6224 KdPrint((PRINT_PREFIX "AtapiInterrupt: ERROR: internal SCSIOP_MECHANISM_STATUS !!!!\n")); 6225 ASSERT(FALSE); 6226 #endif // UNIATA_INIT_CHANGERS 6227 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE) 6228 6229 PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer; 6230 #ifdef __REACTOS__ 6231 (void)senseData; 6232 #endif 6233 6234 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI command status %#x\n", status)); 6235 if (status == SRB_STATUS_DATA_OVERRUN) { 6236 // Check to see if we at least get mininum number of bytes 6237 if ((srb->DataTransferLength - AtaReq->WordsLeft) > 6238 (FIELD_OFFSET (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) { 6239 status = SRB_STATUS_SUCCESS; 6240 } 6241 } 6242 6243 if (status == SRB_STATUS_SUCCESS) { 6244 #ifndef UNIATA_CORE 6245 #ifdef UNIATA_INIT_CHANGERS 6246 if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) && 6247 FALSE && 6248 chan->MechStatusRetryCount) { 6249 6250 KdPrint3((PRINT_PREFIX "AtapiInterrupt: MechStatusRetryCount %#x\n", chan->MechStatusRetryCount)); 6251 // The sense key doesn't say the last request is illegal, so try again 6252 chan->MechStatusRetryCount--; 6253 srb = AtaReq->Srb = BuildMechanismStatusSrb ( 6254 HwDeviceExtension, 6255 AtaReq->OriginalSrb); 6256 } else 6257 #endif // UNIATA_INIT_CHANGERS 6258 { 6259 // Get ready to issue the original srb 6260 srb = AtaReq->Srb = AtaReq->OriginalSrb; 6261 AtaReq->OriginalSrb = NULL; 6262 } 6263 #endif //UNIATA_CORE 6264 /* 6265 // do not enable interrupts in DPC, do not waste time, do it now! 6266 if(UseDpc && chan->DisableIntr) { 6267 AtapiEnableInterrupts(HwDeviceExtension, c); 6268 UseDpc = FALSE; 6269 RestoreUseDpc = TRUE; 6270 } 6271 */ 6272 srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL); 6273 6274 KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan->ExpectingInterrupt)); 6275 6276 if (srbStatus == SRB_STATUS_PENDING) { 6277 KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n")); 6278 goto ReturnEnableIntr; 6279 } 6280 /* 6281 if(RestoreUseDpc) { 6282 // restore state on error 6283 UseDpc = TRUE; 6284 AtapiDisableInterrupts(HwDeviceExtension, c); 6285 } 6286 */ 6287 } 6288 } 6289 6290 // If we get here, it means AtapiSendCommand() has failed 6291 // Can't recover. Pretend the original srb has failed and complete it. 6292 6293 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. complete OriginalSrb\n")); 6294 6295 if (AtaReq->OriginalSrb) { 6296 srb = AtaReq->Srb = AtaReq->OriginalSrb; 6297 AtaReq->OriginalSrb = NULL; 6298 } 6299 6300 KdPrint2((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan->ExpectingInterrupt)); 6301 6302 // fake an error and read no data 6303 status = SRB_STATUS_ERROR; 6304 srb->ScsiStatus = 0; 6305 AtaReq->DataBuffer = (PUSHORT)(srb->DataBuffer); 6306 AtaReq->WordsLeft = srb->DataTransferLength; 6307 chan->RDP = FALSE; 6308 6309 } else if (status == SRB_STATUS_ERROR) { 6310 6311 // Map error to specific SRB status and handle request sense. 6312 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. Begin mapping...\n")); 6313 status = MapError(deviceExtension, 6314 srb); 6315 6316 chan->RDP = FALSE; 6317 6318 } else if(!DmaTransfer) { 6319 6320 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion\n")); 6321 // Command complete. 6322 PIO_wait_busy: 6323 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion, wait BUSY\n")); 6324 // Wait for busy to drop. 6325 for (i = 0; i < 5*30; i++) { 6326 GetBaseStatus(chan, statusByte); 6327 if (!(statusByte & IDE_STATUS_BUSY)) { 6328 break; 6329 } 6330 if(!InDpc) { 6331 // goto DPC 6332 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY; 6333 TimerValue = 200; 6334 KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (busy)\n")); 6335 #ifndef UNIATA_CORE 6336 goto PostToDpc; 6337 #else //UNIATA_CORE 6338 AtapiStallExecution(TimerValue); 6339 goto ServiceInterrupt; 6340 #endif //UNIATA_CORE 6341 } 6342 AtapiStallExecution(100); 6343 } 6344 6345 if (i == 5*30) { 6346 6347 // reset the controller. 6348 KdPrint2((PRINT_PREFIX 6349 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n", 6350 statusByte)); 6351 goto IntrPrepareResetController; 6352 } 6353 // Check to see if DRQ is still up. 6354 if(statusByte & IDE_STATUS_DRQ) { 6355 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DRQ...\n")); 6356 if(srb) { 6357 if(srb->SrbFlags & SRB_FLAGS_DATA_IN) { 6358 KdPrint2((PRINT_PREFIX "srb %x data in\n", srb)); 6359 } else { 6360 KdPrint2((PRINT_PREFIX "srb %x data out\n", srb)); 6361 } 6362 } else { 6363 KdPrint2((PRINT_PREFIX "srb NULL\n")); 6364 } 6365 if(AtaReq) { 6366 KdPrint2((PRINT_PREFIX "AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq, AtaReq->WordsLeft)); 6367 } else { 6368 KdPrint2((PRINT_PREFIX "AtaReq NULL\n")); 6369 } 6370 if(AtaReq && AtaReq->WordsLeft /*&& 6371 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) { 6372 KdPrint2((PRINT_PREFIX "DRQ+AtaReq->WordsLeft -> next portion\n")); 6373 goto continue_PIO; 6374 } 6375 } 6376 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {} 6377 //if ((statusByte & IDE_STATUS_DRQ)) {} 6378 if((statusByte & IDE_STATUS_DRQ) && 6379 (LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED)) ) { 6380 6381 PIO_wait_DRQ: 6382 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO_wait_DRQ\n")); 6383 for (i = 0; i < 200; i++) { 6384 GetBaseStatus(chan, statusByte); 6385 if (!(statusByte & IDE_STATUS_DRQ)) { 6386 break; 6387 } 6388 if(!InDpc) { 6389 // goto DPC 6390 KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq)\n")); 6391 AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ; 6392 TimerValue = 100; 6393 #ifndef UNIATA_CORE 6394 goto PostToDpc; 6395 #else //UNIATA_CORE 6396 AtapiStallExecution(TimerValue); 6397 goto ServiceInterrupt; 6398 #endif //UNIATA_CORE 6399 } 6400 AtapiStallExecution(100); 6401 } 6402 6403 if (i == 200) { 6404 // reset the controller. 6405 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ still up - %#x\n", 6406 statusByte)); 6407 goto IntrPrepareResetController; 6408 } 6409 } 6410 if(atapiDev) { 6411 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n", 6412 AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)(-1)), srb->DataTransferLength )); 6413 //KdDump(srb->DataBuffer, srb->DataTransferLength); 6414 } 6415 if(!AtapiDmaPioSync(HwDeviceExtension, srb, (PUCHAR)(srb->DataBuffer), srb->DataTransferLength)) { 6416 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n")); 6417 } 6418 } 6419 6420 // Clear interrupt expecting flag. 6421 UniataExpectChannelInterrupt(chan, FALSE); 6422 // clear this flag now, it can be set again in sub-calls 6423 InterlockedExchange(&(chan->CheckIntr), 6424 CHECK_INTR_IDLE); 6425 6426 // Sanity check that there is a current request. 6427 if(srb != NULL) { 6428 // Set status in SRB. 6429 srb->SrbStatus = (UCHAR)status; 6430 6431 // Check for underflow. 6432 if(AtaReq->WordsLeft) { 6433 6434 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq->WordsLeft)); 6435 // Subtract out residual words and update if filemark hit, 6436 // setmark hit , end of data, end of media... 6437 if (!(LunExt->DeviceFlags & DFLAGS_TAPE_DEVICE)) { 6438 if (status == SRB_STATUS_DATA_OVERRUN) { 6439 srb->DataTransferLength -= AtaReq->WordsLeft*2; 6440 } else { 6441 srb->DataTransferLength = 0; 6442 } 6443 } else { 6444 srb->DataTransferLength -= AtaReq->WordsLeft*2; 6445 } 6446 } 6447 if(status == SRB_STATUS_SUCCESS) { 6448 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) { 6449 // // This should be set in UniataAhciEndTransaction() for AHCI 6450 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2; 6451 //} 6452 if(!atapiDev && 6453 AtaReq->WordsTransfered*2 < AtaReq->TransferLength) { 6454 KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n", 6455 AtaReq->WordsTransfered*2, AtaReq->TransferLength)); 6456 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 6457 AtaReq->ReqState = REQ_STATE_PREPARE_TO_NEXT; 6458 goto reenqueue_req; 6459 } else { 6460 KdPrint2((PRINT_PREFIX " Transfered %x, full size %x\n", 6461 AtaReq->WordsTransfered*2, AtaReq->TransferLength)); 6462 } 6463 } 6464 6465 if (srb->Function != SRB_FUNCTION_IO_CONTROL) { 6466 6467 CompleteRDP: 6468 // Indicate command complete. 6469 if (!(chan->RDP)) { 6470 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete\n")); 6471 IntrCompleteReq: 6472 6473 if (status == SRB_STATUS_SUCCESS && 6474 srb->SenseInfoBuffer && 6475 srb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) { 6476 6477 PSENSE_DATA senseBuffer = (PSENSE_DATA)srb->SenseInfoBuffer; 6478 6479 KdPrint2((PRINT_PREFIX "AtapiInterrupt: set AutoSense\n")); 6480 senseBuffer->ErrorCode = 0; 6481 senseBuffer->Valid = 1; 6482 senseBuffer->AdditionalSenseLength = 0xb; 6483 senseBuffer->SenseKey = 0; 6484 senseBuffer->AdditionalSenseCode = 0; 6485 senseBuffer->AdditionalSenseCodeQualifier = 0; 6486 6487 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; 6488 } 6489 AtapiDmaDBSync(chan, srb); 6490 KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove srb %#x, status %x\n", srb, status)); 6491 UniataRemoveRequest(chan, srb); 6492 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete, srb %#x\n", srb)); 6493 ScsiPortNotification(RequestComplete, 6494 deviceExtension, 6495 srb); 6496 } 6497 } else { 6498 6499 KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n")); 6500 6501 if (status != SRB_STATUS_SUCCESS) { 6502 error = AtapiReadPort1(chan, IDX_IO1_i_Error); 6503 KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error)); 6504 } 6505 6506 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) { 6507 6508 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 6509 // Build the SMART status block depending upon the completion status. 6510 cmdOutParameters->cBufferSize = wordCount; 6511 cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0; 6512 cmdOutParameters->DriverStatus.bIDEError = error; 6513 6514 // If the sub-command is return smart status, jam the value from cylinder low and high, into the 6515 // data buffer. 6516 if (chan->SmartCommand == RETURN_SMART_STATUS) { 6517 PIDEREGS_EX regs = (PIDEREGS_EX)&(cmdOutParameters->bBuffer); 6518 6519 regs->bOpFlags = 0; 6520 UniataSnapAtaRegs(chan, 0, regs); 6521 6522 regs->bCommandReg = SMART_CMD; 6523 regs->bFeaturesReg = RETURN_SMART_STATUS; 6524 6525 cmdOutParameters->cBufferSize = 8; 6526 } 6527 chan->SmartCommand = 0; // cleanup after execution 6528 } 6529 // Indicate command complete. 6530 goto IntrCompleteReq; 6531 } 6532 6533 } else { 6534 6535 KdPrint2((PRINT_PREFIX "AtapiInterrupt: No SRB!\n")); 6536 } 6537 6538 if (chan->RDP) { 6539 // Check DSC 6540 for (i = 0; i < 5; i++) { 6541 GetBaseStatus(chan, statusByte); 6542 if(!(statusByte & IDE_STATUS_BUSY)) { 6543 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RDP + cleared BUSY\n")); 6544 chan->RDP = FALSE; 6545 goto CompleteRDP; 6546 } else 6547 if (statusByte & IDE_STATUS_DSC) { 6548 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Clear RDP\n")); 6549 chan->RDP = FALSE; 6550 goto CompleteRDP; 6551 } 6552 AtapiStallExecution(50); 6553 } 6554 } 6555 // RDP can be cleared since previous check 6556 if (chan->RDP) { 6557 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestTimerCall 2000\n")); 6558 6559 TimerValue = 2000; 6560 #ifndef UNIATA_CORE 6561 goto CallTimerDpc; 6562 #else //UNIATA_CORE 6563 AtapiStallExecution(TimerValue); 6564 goto ServiceInterrupt; 6565 #endif //UNIATA_CORE 6566 } 6567 6568 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 6569 enqueue_next_req: 6570 // Get next request 6571 srb = UniataGetCurRequest(chan); 6572 6573 reenqueue_req: 6574 6575 #ifndef UNIATA_CORE 6576 KdPrint2((PRINT_PREFIX "AtapiInterrupt: NextRequest, srb=%#x\n",srb)); 6577 if(!srb) { 6578 ScsiPortNotification(NextRequest, 6579 deviceExtension, 6580 NULL); 6581 } else { 6582 ScsiPortNotification(NextLuRequest, 6583 deviceExtension, 6584 PathId, 6585 TargetId, 6586 Lun); 6587 // in simplex mode next command must NOT be sent here 6588 if(!deviceExtension->simplexOnly) { 6589 AtapiStartIo__(HwDeviceExtension, srb, FALSE); 6590 } 6591 } 6592 // Try to get SRB fron any non-empty queue (later) 6593 if(deviceExtension->simplexOnly) { 6594 NoStartIo = FALSE; 6595 } 6596 #endif //UNIATA_CORE 6597 6598 goto ReturnEnableIntr; 6599 6600 } else { 6601 6602 // Unexpected int. Catch it 6603 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n", 6604 interruptReason, 6605 statusByte)); 6606 6607 if(g_opt_VirtualMachine == VM_QEMU) { 6608 if(interruptReason == ATAPI_IR_IO_toDev && !(statusByte & IDE_STATUS_DRQ) && !DmaTransfer) { 6609 statusByte = WaitForDrq(chan); 6610 if(statusByte & IDE_STATUS_DRQ) { 6611 goto continue_PIO; 6612 } 6613 } 6614 } 6615 6616 if(OldReqState == REQ_STATE_DPC_WAIT_BUSY0 && 6617 AtaReq->WordsLeft == 0) { 6618 KdPrint2((PRINT_PREFIX "AtapiInterrupt: pending WAIT_BUSY0. Complete.\n")); 6619 status = SRB_STATUS_SUCCESS; 6620 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; 6621 goto CompleteRequest; 6622 } 6623 } 6624 6625 ReturnEnableIntr: 6626 6627 KdPrint2((PRINT_PREFIX "AtapiInterrupt: ReturnEnableIntr\n",srb)); 6628 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt 6629 deviceExtension->ExpectingInterrupt = TRUE; 6630 if(UseDpc) { 6631 if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) { 6632 KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiEnableInterrupts__()\n")); 6633 #ifdef UNIATA_USE_XXableInterrupts 6634 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 6635 chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ; 6636 // must be called on DISPATCH_LEVEL 6637 ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension, 6638 AtapiEnableInterrupts__); 6639 #else 6640 AtapiEnableInterrupts(HwDeviceExtension, c); 6641 InterlockedExchange(&(chan->CheckIntr), 6642 CHECK_INTR_IDLE); 6643 // Will raise IRQL to DIRQL 6644 #ifndef UNIATA_CORE 6645 AtapiQueueTimerDpc(HwDeviceExtension, lChannel, 6646 AtapiEnableInterrupts__, 6647 1); 6648 #endif // UNIATA_CORE 6649 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n")); 6650 #endif // UNIATA_USE_XXableInterrupts 6651 } 6652 } 6653 6654 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE); 6655 // in simplex mode next command must be sent here if 6656 // DPC is not used 6657 KdPrint2((PRINT_PREFIX "AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc, NoStartIo)); 6658 6659 #ifndef UNIATA_CORE 6660 if(!UseDpc && /*deviceExtension->simplexOnly &&*/ !NoStartIo) { 6661 chan = UniataGetNextChannel(chan); 6662 if(chan) { 6663 srb = UniataGetCurRequest(chan); 6664 } else { 6665 srb = NULL; 6666 } 6667 KdPrint2((PRINT_PREFIX "AtapiInterrupt: run srb %x\n", srb)); 6668 if(srb) { 6669 AtapiStartIo__(HwDeviceExtension, srb, FALSE); 6670 } 6671 } 6672 #endif //UNIATA_CORE 6673 return TRUE; 6674 6675 } // end AtapiInterrupt__() 6676 6677 #ifndef UNIATA_CORE 6678 6679 /*++ 6680 6681 Routine Description: 6682 6683 This routine handles SMART enable, disable, read attributes and threshold commands. 6684 6685 Arguments: 6686 6687 HwDeviceExtension - HBA miniport driver's adapter data storage 6688 Srb - IO request packet 6689 6690 Return Value: 6691 6692 SRB status 6693 6694 --*/ 6695 ULONG 6696 NTAPI 6697 IdeSendSmartCommand( 6698 IN PVOID HwDeviceExtension, 6699 IN PSCSI_REQUEST_BLOCK Srb, 6700 IN ULONG targetId // assume it is always valid 6701 ) 6702 { 6703 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 6704 ULONG c ; // = GET_CHANNEL(Srb); may be invalid 6705 PHW_CHANNEL chan ; // = &(deviceExtension->chan[c]); 6706 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 6707 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 6708 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 6709 PIDEREGS regs = &cmdInParameters.irDriveRegs; 6710 // ULONG i; 6711 UCHAR statusByte; 6712 ULONG DeviceNumber; 6713 6714 if (regs->bCommandReg != SMART_CMD) { 6715 KdPrint2((PRINT_PREFIX 6716 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n")); 6717 return SRB_STATUS_INVALID_REQUEST; 6718 } 6719 6720 c = targetId / deviceExtension->NumberLuns; 6721 DeviceNumber = targetId % deviceExtension->NumberLuns; 6722 KdPrint2((PRINT_PREFIX " c %d, dev %d\n", c, DeviceNumber)); 6723 6724 chan = &(deviceExtension->chan[c]); 6725 6726 chan->SmartCommand = regs->bFeaturesReg; 6727 6728 // Determine which of the commands to carry out. 6729 switch(regs->bFeaturesReg) { 6730 case READ_ATTRIBUTES: 6731 case READ_THRESHOLDS: 6732 case READ_LOG_SECTOR: 6733 case WRITE_LOG_SECTOR: 6734 6735 if(Srb->DataTransferLength < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1) { 6736 KdPrint2((PRINT_PREFIX 6737 "IdeSendSmartCommand: wrong buffer size\n")); 6738 return SRB_STATUS_DATA_OVERRUN; 6739 } 6740 6741 statusByte = WaitOnBusy(chan); 6742 6743 if (statusByte & IDE_STATUS_BUSY) { 6744 KdPrint2((PRINT_PREFIX 6745 "IdeSendSmartCommand: Returning BUSY status\n")); 6746 return SRB_STATUS_BUSY; 6747 } 6748 6749 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same). 6750 RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1); 6751 6752 // Set data buffer pointer and words left. 6753 AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer; 6754 AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2; 6755 6756 statusByte = AtaCommand(deviceExtension, DeviceNumber, c, 6757 regs->bCommandReg, 6758 (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8), 6759 0, 6760 regs->bSectorNumberReg, 6761 regs->bSectorCountReg, 6762 regs->bFeaturesReg, 6763 ATA_IMMEDIATE); 6764 6765 if(!(statusByte & IDE_STATUS_ERROR)) { 6766 // Wait for interrupt. 6767 return SRB_STATUS_PENDING; 6768 } 6769 return SRB_STATUS_ERROR; 6770 6771 case ENABLE_SMART: 6772 case DISABLE_SMART: 6773 case RETURN_SMART_STATUS: 6774 case ENABLE_DISABLE_AUTOSAVE: 6775 case EXECUTE_OFFLINE_DIAGS: 6776 case SAVE_ATTRIBUTE_VALUES: 6777 case AUTO_OFFLINE: 6778 6779 statusByte = WaitOnBusy(chan); 6780 6781 if (statusByte & IDE_STATUS_BUSY) { 6782 KdPrint2((PRINT_PREFIX 6783 "IdeSendSmartCommand: Returning BUSY status\n")); 6784 return SRB_STATUS_BUSY; 6785 } 6786 6787 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same). 6788 RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) - 1); 6789 6790 // Set data buffer pointer and indicate no data transfer. 6791 AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer; 6792 AtaReq->WordsLeft = 0; 6793 6794 statusByte = AtaCommand(deviceExtension, DeviceNumber, c, 6795 regs->bCommandReg, 6796 (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8), 6797 0, 6798 regs->bSectorNumberReg, 6799 regs->bSectorCountReg, 6800 regs->bFeaturesReg, 6801 ATA_IMMEDIATE); 6802 6803 if(!(statusByte & IDE_STATUS_ERROR)) { 6804 // Wait for interrupt. 6805 UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt 6806 return SRB_STATUS_PENDING; 6807 } 6808 return SRB_STATUS_ERROR; 6809 } // end switch(regs->bFeaturesReg) 6810 6811 return SRB_STATUS_INVALID_REQUEST; 6812 6813 } // end IdeSendSmartCommand() 6814 6815 #endif //UNIATA_CORE 6816 6817 ULONGLONG 6818 NTAPI 6819 UniAtaCalculateLBARegs( 6820 PHW_LU_EXTENSION LunExt, 6821 ULONGLONG startingSector, 6822 PULONG max_bcount 6823 ) 6824 { 6825 UCHAR drvSelect,sectorNumber; 6826 USHORT cylinder; 6827 ULONG tmp; 6828 6829 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) { 6830 (*max_bcount) = 0; 6831 if(LunExt->LimitedTransferMode >= ATA_DMA) { 6832 if(LunExt->DeviceExtension) { 6833 (*max_bcount) = LunExt->DeviceExtension->MaximumDmaTransferLength / DEV_BSIZE; 6834 } 6835 } 6836 return startingSector; 6837 } 6838 tmp = LunExt->IdentifyData.SectorsPerTrack * 6839 LunExt->IdentifyData.NumberOfHeads; 6840 if(!tmp) { 6841 KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: 0-sized\n")); 6842 cylinder = 0; 6843 drvSelect = 0; 6844 sectorNumber = 1; 6845 (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack; 6846 } else { 6847 cylinder = (USHORT)(startingSector / tmp); 6848 drvSelect = (UCHAR)((startingSector % tmp) / LunExt->IdentifyData.SectorsPerTrack); 6849 sectorNumber = (UCHAR)(startingSector % LunExt->IdentifyData.SectorsPerTrack) + 1; 6850 (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack - sectorNumber + 1; 6851 KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n", 6852 cylinder, drvSelect, sectorNumber, (*max_bcount))); 6853 } 6854 6855 return (ULONG)(sectorNumber&0xff) | (((ULONG)cylinder&0xffff)<<8) | (((ULONG)drvSelect&0xf)<<24); 6856 } // end UniAtaCalculateLBARegs() 6857 6858 ULONGLONG 6859 NTAPI 6860 UniAtaCalculateLBARegsBack( 6861 PHW_LU_EXTENSION LunExt, 6862 ULONGLONG lba 6863 ) 6864 { 6865 ULONG drvSelect,sectorNumber; 6866 ULONG cylinder; 6867 ULONG tmp; 6868 6869 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) { 6870 return lba; 6871 } 6872 tmp = LunExt->IdentifyData.SectorsPerTrack * 6873 LunExt->IdentifyData.NumberOfHeads; 6874 6875 cylinder = (USHORT)((lba >> 8) & 0xffff); 6876 drvSelect = (UCHAR)((lba >> 24) & 0xf); 6877 sectorNumber = (UCHAR)(lba & 0xff); 6878 6879 lba = sectorNumber-1 + 6880 (drvSelect*LunExt->IdentifyData.SectorsPerTrack) + 6881 (cylinder*tmp); 6882 6883 return lba; 6884 } // end UniAtaCalculateLBARegsBack() 6885 6886 6887 /*++ 6888 6889 Routine Description: 6890 6891 This routine handles IDE read and writes. 6892 6893 Arguments: 6894 6895 HwDeviceExtension - HBA miniport driver's adapter data storage 6896 Srb - IO request packet 6897 6898 Return Value: 6899 6900 SRB status 6901 6902 --*/ 6903 ULONG 6904 NTAPI 6905 IdeReadWrite( 6906 IN PVOID HwDeviceExtension, 6907 IN PSCSI_REQUEST_BLOCK Srb, 6908 IN ULONG CmdAction 6909 ) 6910 { 6911 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 6912 UCHAR lChannel = GET_CHANNEL(Srb); 6913 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 6914 PHW_LU_EXTENSION LunExt; 6915 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 6916 //ULONG ldev = GET_LDEV(Srb); 6917 UCHAR DeviceNumber = GET_CDEV(Srb);; 6918 ULONGLONG startingSector=0; 6919 ULONG max_bcount = 0; 6920 ULONG wordCount = 0; 6921 UCHAR statusByte,statusByte2; 6922 UCHAR cmd; 6923 ULONGLONG lba; 6924 BOOLEAN use_dma = FALSE; 6925 ULONG fis_size; 6926 6927 AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD; 6928 LunExt = chan->lun[DeviceNumber]; 6929 6930 if((CmdAction & CMD_ACTION_PREPARE) && 6931 (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) { 6932 6933 if(LunExt->opt_ReadOnly && 6934 (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) { 6935 if(LunExt->opt_ReadOnly == 1) { 6936 KdPrint2((PRINT_PREFIX "Abort WRITE (Soft R/O)\n")); 6937 return SRB_STATUS_ERROR; 6938 } else { 6939 KdPrint2((PRINT_PREFIX "Ignore WRITE (Soft R/O)\n")); 6940 return SRB_STATUS_SUCCESS; 6941 } 6942 } 6943 6944 // Set data buffer pointer and words left. 6945 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 6946 6947 if(AtaReq->WordsTransfered) { 6948 AtaReq->DataBuffer = ((PUSHORT)(Srb->DataBuffer)) + AtaReq->WordsTransfered; 6949 startingSector = (UniAtaCalculateLBARegsBack(LunExt, AtaReq->lba)) /* latest lba */ + AtaReq->bcount /* previous bcount */; 6950 AtaReq->bcount = (AtaReq->TransferLength - AtaReq->WordsTransfered*2 + DEV_BSIZE-1) / DEV_BSIZE; 6951 KdPrint2((PRINT_PREFIX "IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n", 6952 startingSector, 6953 AtaReq->TransferLength/2, 6954 AtaReq->WordsTransfered, 6955 AtaReq->bcount)); 6956 } else { 6957 AtaReq->DataBuffer = (PUSHORT)(Srb->DataBuffer); 6958 AtaReq->TransferLength = Srb->DataTransferLength; 6959 // Set up 1st block. 6960 switch(Srb->Cdb[0]) { 6961 case SCSIOP_WRITE: 6962 if(LunExt->DeviceFlags & DFLAGS_LBA32plus) { 6963 KdPrint2((PRINT_PREFIX "Attention: SCSIOP_WRITE on 2TB\n")); 6964 //return SRB_STATUS_ERROR; 6965 } 6966 // FALLTHROUGH 6967 case SCSIOP_READ: 6968 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA); 6969 MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks); 6970 break; 6971 case SCSIOP_WRITE12: 6972 if(LunExt->DeviceFlags & DFLAGS_LBA32plus) { 6973 KdPrint2((PRINT_PREFIX "Attention: SCSIOP_WRITE12 on 2TB\n")); 6974 //return SRB_STATUS_ERROR; 6975 } 6976 // FALLTHROUGH 6977 case SCSIOP_READ12: 6978 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA); 6979 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks); 6980 break; 6981 case SCSIOP_READ16: 6982 case SCSIOP_WRITE16: 6983 MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA); 6984 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks); 6985 break; 6986 } 6987 KdPrint2((PRINT_PREFIX "IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n", 6988 startingSector, 6989 AtaReq->TransferLength/2, 6990 AtaReq->bcount)); 6991 } 6992 lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount); 6993 6994 if(max_bcount) { 6995 AtaReq->bcount = min(AtaReq->bcount, max_bcount); 6996 } 6997 AtaReq->WordsLeft = min(AtaReq->TransferLength - AtaReq->WordsTransfered*2, 6998 AtaReq->bcount * DEV_BSIZE) / 2; 6999 7000 KdPrint2((PRINT_PREFIX "IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n", 7001 startingSector, 7002 AtaReq->WordsLeft, 7003 AtaReq->bcount)); 7004 7005 AtaReq->lba = lba; 7006 if(LunExt->errRetry && 7007 lba == LunExt->errLastLba && 7008 /* AtaReq->bcount && */ // errRetry can be set only for non-zero bcount 7009 AtaReq->bcount == LunExt->errBCount) { 7010 KdPrint3((PRINT_PREFIX "IdeReadWrite: Retry after BUS_RESET %d @%#I64x (%#x)\n", 7011 LunExt->errRetry, LunExt->errLastLba, LunExt->errBCount)); 7012 if(AtaReq->retry < MAX_RETRIES) { 7013 AtaReq->retry = LunExt->errRetry; 7014 AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE; 7015 } 7016 LunExt->errRetry = 0; 7017 } 7018 7019 // assume best case here 7020 // we cannot reinit Dma until previous request is completed 7021 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7022 UniataAhciSetupCmdPtr(AtaReq); 7023 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 7024 (PUCHAR)(AtaReq->DataBuffer), 7025 AtaReq->bcount * DEV_BSIZE)) { 7026 KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !DMA\n")); 7027 return SRB_STATUS_ERROR; 7028 } 7029 } else 7030 if ((LunExt->LimitedTransferMode >= ATA_DMA)) { 7031 use_dma = TRUE; 7032 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success 7033 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 7034 (PUCHAR)(AtaReq->DataBuffer), 7035 AtaReq->bcount * DEV_BSIZE)) { 7036 use_dma = FALSE; 7037 } 7038 } 7039 7040 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7041 KdPrint2((PRINT_PREFIX "IdeReadWrite: setup AHCI FIS\n")); 7042 RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis)); 7043 7044 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel, 7045 &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]), 7046 (AtaReq->Flags & REQ_FLAG_READ) ? IDE_COMMAND_READ_DMA : IDE_COMMAND_WRITE_DMA, 7047 lba, 7048 (USHORT)(AtaReq->bcount), 7049 0 7050 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/ 7051 ); 7052 7053 if(!fis_size) { 7054 KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !FIS\n")); 7055 return SRB_STATUS_ERROR; 7056 } 7057 7058 AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0, (AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE, fis_size, DeviceNumber); 7059 KdPrint2((PRINT_PREFIX "IdeReadWrite ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags)); 7060 } 7061 7062 AtaReq->ReqState = REQ_STATE_READY_TO_TRANSFER; 7063 7064 } else { // exec_only 7065 KdPrint2((PRINT_PREFIX "IdeReadWrite (ExecOnly): \n")); 7066 lba = AtaReq->lba; 7067 7068 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) { 7069 use_dma = TRUE; 7070 } 7071 } 7072 if(!(CmdAction & CMD_ACTION_EXEC)) { 7073 7074 return SRB_STATUS_PENDING; 7075 } 7076 7077 // if this is queued request, reinit DMA and check 7078 // if DMA mode is still available 7079 AtapiDmaReinit(deviceExtension, LunExt, AtaReq); 7080 if (/*EnableDma &&*/ 7081 (LunExt->TransferMode >= ATA_DMA)) { 7082 use_dma = TRUE; 7083 } else { 7084 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7085 use_dma = FALSE; 7086 } 7087 7088 // Check if write request. 7089 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 7090 7091 // Prepare read command. 7092 if(use_dma) { 7093 cmd = IDE_COMMAND_READ_DMA; 7094 } else 7095 if(LunExt->MaximumBlockXfer) { 7096 cmd = IDE_COMMAND_READ_MULTIPLE; 7097 } else { 7098 cmd = IDE_COMMAND_READ; 7099 } 7100 } else { 7101 7102 // Prepare write command. 7103 if (use_dma) { 7104 wordCount = AtaReq->bcount*DEV_BSIZE/2; 7105 cmd = IDE_COMMAND_WRITE_DMA; 7106 } else 7107 if (LunExt->MaximumBlockXfer) { 7108 wordCount = DEV_BSIZE/2 * LunExt->MaximumBlockXfer; 7109 7110 if (AtaReq->WordsLeft < wordCount) { 7111 // Transfer only words requested. 7112 wordCount = AtaReq->WordsLeft; 7113 } 7114 cmd = IDE_COMMAND_WRITE_MULTIPLE; 7115 7116 } else { 7117 wordCount = DEV_BSIZE/2; 7118 cmd = IDE_COMMAND_WRITE; 7119 } 7120 } 7121 7122 // Send IO command. 7123 KdPrint2((PRINT_PREFIX "IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba, ((Srb->DataTransferLength + 0x1FF) / 0x200), 7124 ((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE))); 7125 if(use_dma) { 7126 chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION; 7127 } else { 7128 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; 7129 } 7130 7131 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7132 // AHCI doesn't distinguish DMA and PIO 7133 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); 7134 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 7135 UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt 7136 InterlockedExchange(&(chan->CheckIntr), 7137 CHECK_INTR_IDLE); 7138 return SRB_STATUS_PENDING; 7139 } 7140 7141 if ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) || 7142 use_dma) { 7143 if(use_dma) { 7144 AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb); 7145 if(g_opt_BochsDmaReadWorkaround && 7146 (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) { 7147 KdPrint2((PRINT_PREFIX "CTRFLAGS_DMA_BEFORE_R on BOCHS\n")); 7148 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); 7149 } 7150 } 7151 statusByte2 = AtaCommand48(deviceExtension, DeviceNumber, lChannel, 7152 cmd, lba, 7153 (USHORT)(AtaReq->bcount), 7154 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE), 7155 0, ATA_IMMEDIATE); 7156 /* if(statusByte2 != IDE_STATUS_WRONG) { 7157 GetStatus(chan, statusByte2); 7158 }*/ 7159 if(statusByte2 & IDE_STATUS_ERROR) { 7160 // Unfortunately, we cannot handle errors in such a way in real life (except known bad blocks). 7161 // Because some devices doesn't reset ERR from previous command immediately after getting new one. 7162 // On the other hand we cannot wait here because of possible timeout condition 7163 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 7164 KdPrint2((PRINT_PREFIX "IdeReadWrite: status %#x, error %#x\n", statusByte2, statusByte)); 7165 return SRB_STATUS_ERROR; 7166 } 7167 if(use_dma) { 7168 if(!g_opt_BochsDmaReadWorkaround || 7169 !(Srb->SrbFlags & SRB_FLAGS_DATA_IN)) { 7170 //GetStatus(chan, statusByte2); 7171 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); 7172 } 7173 } 7174 return SRB_STATUS_PENDING; 7175 } 7176 7177 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel, 7178 cmd, lba, 7179 (USHORT)(AtaReq->bcount), 7180 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE), 7181 0, ATA_WAIT_INTR); 7182 7183 if (!(statusByte & IDE_STATUS_DRQ) || 7184 statusByte == IDE_STATUS_WRONG) { 7185 7186 if(statusByte == IDE_STATUS_WRONG) { 7187 KdPrint2((PRINT_PREFIX 7188 "IdeReadWrite: error sending command (%#x)\n", 7189 statusByte)); 7190 } else { 7191 KdPrint2((PRINT_PREFIX 7192 "IdeReadWrite: DRQ never asserted (%#x)\n", 7193 statusByte)); 7194 } 7195 7196 AtaReq->WordsLeft = 0; 7197 7198 // Clear interrupt expecting flag. 7199 UniataExpectChannelInterrupt(chan, FALSE); 7200 InterlockedExchange(&(chan->CheckIntr), 7201 CHECK_INTR_IDLE); 7202 7203 // Clear current SRB. 7204 UniataRemoveRequest(chan, Srb); 7205 7206 return (statusByte == IDE_STATUS_WRONG) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT; 7207 } 7208 7209 UniataExpectChannelInterrupt(chan, TRUE); 7210 InterlockedExchange(&(chan->CheckIntr), 7211 CHECK_INTR_IDLE); 7212 7213 // Write next DEV_BSIZE/2*N words. 7214 if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) || (wordCount & 1)) { 7215 KdPrint2((PRINT_PREFIX 7216 "IdeReadWrite: Write %#x words\n", wordCount)); 7217 7218 WriteBuffer(chan, 7219 AtaReq->DataBuffer, 7220 wordCount, 7221 UniataGetPioTiming(LunExt)); 7222 7223 } else { 7224 7225 KdPrint2((PRINT_PREFIX 7226 "IdeReadWrite: Write %#x Dwords\n", wordCount/2)); 7227 7228 WriteBuffer2(chan, 7229 (PULONG)(AtaReq->DataBuffer), 7230 wordCount / 2, 7231 UniataGetPioTiming(LunExt)); 7232 } 7233 7234 // Adjust buffer address and words left count. 7235 AtaReq->WordsLeft -= wordCount; 7236 AtaReq->DataBuffer += wordCount; 7237 AtaReq->WordsTransfered += wordCount; 7238 7239 // Wait for interrupt. 7240 return SRB_STATUS_PENDING; 7241 7242 } // end IdeReadWrite() 7243 7244 #ifndef UNIATA_CORE 7245 7246 /*++ 7247 7248 Routine Description: 7249 This routine handles IDE Verify. 7250 7251 Arguments: 7252 HwDeviceExtension - HBA miniport driver's adapter data storage 7253 Srb - IO request packet 7254 ` 7255 Return Value: 7256 SRB status 7257 7258 --*/ 7259 ULONG 7260 NTAPI 7261 IdeVerify( 7262 IN PVOID HwDeviceExtension, 7263 IN PSCSI_REQUEST_BLOCK Srb 7264 ) 7265 { 7266 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 7267 UCHAR lChannel = GET_CHANNEL(Srb); 7268 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 7269 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 7270 PHW_LU_EXTENSION LunExt; 7271 //ULONG ldev = GET_LDEV(Srb); 7272 ULONG DeviceNumber = GET_CDEV(Srb); 7273 UCHAR statusByte; 7274 ULONGLONG startingSector=0; 7275 ULONG max_bcount; 7276 ULONGLONG sectors; 7277 ULONGLONG endSector; 7278 ULONG sectorCount=0; 7279 ULONGLONG lba; 7280 7281 LunExt = chan->lun[DeviceNumber]; 7282 // Drive has these number sectors. 7283 if(!(sectors = (ULONG)(LunExt->NumOfSectors))) { 7284 sectors = LunExt->IdentifyData.SectorsPerTrack * 7285 LunExt->IdentifyData.NumberOfHeads * 7286 LunExt->IdentifyData.NumberOfCylinders; 7287 } 7288 7289 KdPrint2((PRINT_PREFIX 7290 "IdeVerify: Total sectors %#I64x\n", 7291 sectors)); 7292 7293 // Get starting sector number from CDB. 7294 switch(Srb->Cdb[0]) { 7295 case SCSIOP_VERIFY: 7296 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA); 7297 MOV_SWP_DW2DD(sectorCount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks); 7298 break; 7299 case SCSIOP_VERIFY12: 7300 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA); 7301 MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks); 7302 break; 7303 case SCSIOP_VERIFY16: 7304 MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA); 7305 MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks); 7306 break; 7307 } 7308 7309 KdPrint2((PRINT_PREFIX 7310 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n", 7311 startingSector, 7312 sectorCount)); 7313 7314 endSector = startingSector + sectorCount; 7315 7316 KdPrint2((PRINT_PREFIX 7317 "IdeVerify: Ending sector %#I64x\n", 7318 endSector)); 7319 7320 if (endSector > sectors) { 7321 7322 // Too big, round down. 7323 KdPrint2((PRINT_PREFIX 7324 "IdeVerify: Truncating request to %#x blocks\n", 7325 sectors - startingSector - 1)); 7326 7327 sectorCount = (ULONG)(sectors - startingSector - 1); 7328 7329 } else { 7330 7331 // Set up sector count register. Round up to next block. 7332 if (sectorCount > 0xFF) { 7333 sectorCount = (USHORT)0xFF; 7334 } 7335 } 7336 7337 // Set data buffer pointer and words left. 7338 AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer; 7339 AtaReq->WordsLeft = Srb->DataTransferLength / 2; 7340 7341 // Indicate expecting an interrupt. 7342 InterlockedExchange(&(chan->CheckIntr), 7343 CHECK_INTR_IDLE); 7344 7345 lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount); 7346 7347 statusByte = AtaCommand48(deviceExtension, LunExt->Lun, GET_CHANNEL(Srb), 7348 IDE_COMMAND_VERIFY, lba, 7349 (USHORT)sectorCount, 7350 0, ATA_IMMEDIATE); 7351 7352 if(!(statusByte & IDE_STATUS_ERROR)) { 7353 // Wait for interrupt. 7354 UniataExpectChannelInterrupt(chan, TRUE); 7355 return SRB_STATUS_PENDING; 7356 } 7357 return SRB_STATUS_ERROR; 7358 7359 } // end IdeVerify() 7360 7361 #endif //UNIATA_CORE 7362 7363 /*++ 7364 7365 Routine Description: 7366 Send ATAPI packet command to device. 7367 7368 Arguments: 7369 HwDeviceExtension - HBA miniport driver's adapter data storage 7370 Srb - IO request packet 7371 7372 Return Value: 7373 7374 --*/ 7375 ULONG 7376 NTAPI 7377 AtapiSendCommand( 7378 IN PVOID HwDeviceExtension, 7379 IN PSCSI_REQUEST_BLOCK Srb, 7380 IN ULONG CmdAction 7381 ) 7382 { 7383 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 7384 UCHAR lChannel = GET_CHANNEL(Srb); 7385 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 7386 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 7387 PHW_LU_EXTENSION LunExt; 7388 //ULONG ldev = GET_LDEV(Srb); 7389 ULONG DeviceNumber = GET_CDEV(Srb); 7390 ULONG flags; 7391 UCHAR statusByte,statusByte0,byteCountLow,byteCountHigh; 7392 UCHAR interruptReason; 7393 BOOLEAN use_dma = FALSE; 7394 BOOLEAN dma_reinited = FALSE; 7395 BOOLEAN retried = FALSE; 7396 ULONG fis_size, i; 7397 UCHAR FeatureReg=0; 7398 7399 LunExt = chan->lun[DeviceNumber]; 7400 7401 KdPrint3((PRINT_PREFIX "AtapiSendCommand: req state %#x, Action %x\n", AtaReq->ReqState, CmdAction)); 7402 if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER) 7403 AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER; 7404 7405 7406 #ifdef UNIATA_DUMP_ATAPI 7407 if(CmdAction & CMD_ACTION_PREPARE) { 7408 UCHAR ScsiCommand; 7409 PCDB Cdb; 7410 PCHAR CdbData; 7411 PCHAR ModeSelectData; 7412 ULONG CdbDataLen; 7413 7414 Cdb = (PCDB)(Srb->Cdb); 7415 ScsiCommand = Cdb->CDB6.OperationCode; 7416 CdbData = (PCHAR)(Srb->DataBuffer); 7417 CdbDataLen = Srb->DataTransferLength; 7418 7419 if(CdbDataLen > 0x1000) { 7420 CdbDataLen = 0x1000; 7421 } 7422 7423 KdPrint(("--\n")); 7424 KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID)); 7425 KdPrint2(("P:T:D=%d:%d:%d\n", 7426 Srb->PathId, 7427 Srb->TargetId, 7428 Srb->Lun)); 7429 KdPrint(("SCSI Command %2.2x\n", ScsiCommand)); 7430 KdDump(Cdb, 16); 7431 7432 if(ScsiCommand == SCSIOP_WRITE_CD) { 7433 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n", 7434 Cdb->WRITE_CD.LBA[0], 7435 Cdb->WRITE_CD.LBA[1], 7436 Cdb->WRITE_CD.LBA[2], 7437 Cdb->WRITE_CD.LBA[3] 7438 )); 7439 } else 7440 if(ScsiCommand == SCSIOP_WRITE12) { 7441 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n", 7442 Cdb->CDB12READWRITE.LBA[0], 7443 Cdb->CDB12READWRITE.LBA[1], 7444 Cdb->CDB12READWRITE.LBA[2], 7445 Cdb->CDB12READWRITE.LBA[3] 7446 )); 7447 } else 7448 if(ScsiCommand == SCSIOP_WRITE16) { 7449 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", 7450 Cdb->CDB16READWRITE.LBA[0], 7451 Cdb->CDB16READWRITE.LBA[1], 7452 Cdb->CDB16READWRITE.LBA[2], 7453 Cdb->CDB16READWRITE.LBA[3], 7454 Cdb->CDB16READWRITE.LBA[4], 7455 Cdb->CDB16READWRITE.LBA[5], 7456 Cdb->CDB16READWRITE.LBA[6], 7457 Cdb->CDB16READWRITE.LBA[7] 7458 )); 7459 } else 7460 if(ScsiCommand == SCSIOP_MODE_SELECT) { 7461 KdPrint(("ModeSelect 6\n")); 7462 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData; 7463 ModeSelectData = CdbData+4; 7464 KdDump(CdbData, CdbDataLen); 7465 } else 7466 if(ScsiCommand == SCSIOP_MODE_SELECT10) { 7467 KdPrint(("ModeSelect 10\n")); 7468 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData; 7469 ModeSelectData = CdbData+8; 7470 KdDump(CdbData, CdbDataLen); 7471 } else { 7472 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { 7473 KdPrint(("Send buffer to device:\n")); 7474 KdDump(CdbData, CdbDataLen); 7475 } 7476 } 7477 KdPrint(("--\n")); 7478 } 7479 #endif //UNIATA_DUMP_ATAPI 7480 7481 7482 if(CmdAction == CMD_ACTION_PREPARE) { 7483 KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb->Cdb))); 7484 7485 switch (Srb->Cdb[0]) { 7486 case SCSIOP_RECEIVE: 7487 case SCSIOP_SEND: 7488 case SCSIOP_READ: 7489 case SCSIOP_WRITE: 7490 case SCSIOP_READ12: 7491 case SCSIOP_WRITE12: 7492 case SCSIOP_READ16: 7493 case SCSIOP_WRITE16: 7494 // all right 7495 break; 7496 case SCSIOP_READ_CD: 7497 case SCSIOP_READ_CD_MSF: 7498 if(deviceExtension->opt_AtapiDmaRawRead) { 7499 // all right 7500 break; 7501 } 7502 /* FALL THROUGH */ 7503 default: 7504 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY\n")); 7505 return SRB_STATUS_BUSY; 7506 } 7507 // 7508 #ifdef UNIATA_INIT_CHANGERS 7509 if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) && 7510 !AtaReq->OriginalSrb) { 7511 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY (2)\n")); 7512 return SRB_STATUS_BUSY; 7513 } 7514 #endif // UNIATA_INIT_CHANGERS 7515 } 7516 7517 #ifndef UNIATA_CORE 7518 // standard atapi.sys claims: 7519 7520 // We need to know how many platters our atapi cd-rom device might have. 7521 // Before anyone tries to send a srb to our target for the first time, 7522 // we must "secretly" send down a separate mechanism status srb in order to 7523 // initialize our device extension changer data. That's how we know how 7524 // many platters our target has. 7525 7526 // BUT! 7527 // some devices freeze (sometimes) forever on this command 7528 // Let CD-ROM driver send this command itself, if it find it necessary 7529 // We shall just parse output (if any) 7530 7531 #ifdef UNIATA_INIT_CHANGERS 7532 if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) && 7533 !AtaReq->OriginalSrb) { 7534 7535 ULONG srbStatus; 7536 7537 KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n")); 7538 // Set this flag now. If the device hangs on the mech. status 7539 // command, we will not have the chance to set it. 7540 LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED; 7541 7542 chan->MechStatusRetryCount = 3; 7543 AtaReq->OriginalSrb = Srb; 7544 AtaReq->Srb = BuildMechanismStatusSrb ( 7545 HwDeviceExtension, 7546 Srb); 7547 7548 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n")); 7549 srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL); 7550 if (srbStatus == SRB_STATUS_PENDING) { 7551 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n")); 7552 return srbStatus; 7553 } else { 7554 7555 // failed! Get the sense key and maybe try again 7556 AtaReq->Srb = BuildRequestSenseSrb ( HwDeviceExtension, 7557 AtaReq->OriginalSrb); 7558 7559 srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL); 7560 7561 KdPrint3((PRINT_PREFIX "AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt)); 7562 7563 if (srbStatus == SRB_STATUS_PENDING) { 7564 KdPrint2((PRINT_PREFIX "AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n")); 7565 return srbStatus; 7566 } 7567 7568 // failed again ? should not get here 7569 AtaReq->Srb = AtaReq->OriginalSrb; 7570 AtaReq->OriginalSrb = NULL; 7571 // fall out 7572 } 7573 } 7574 #endif // UNIATA_INIT_CHANGERS 7575 #endif //UNIATA_CORE 7576 7577 if((CmdAction & CMD_ACTION_PREPARE) && 7578 (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) { 7579 7580 KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb->Cdb[0], &(Srb->Cdb))); 7581 7582 if(!LunExt->IdentifyData.AtapiCmdSize && 7583 (Srb->CdbLength > 12)) { 7584 KdPrint2((PRINT_PREFIX "Cdb16 not supported\n")); 7585 return SRB_STATUS_INVALID_REQUEST; 7586 } 7587 7588 // Set data buffer pointer and words left. 7589 AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer; 7590 AtaReq->WordsLeft = Srb->DataTransferLength / 2; 7591 AtaReq->TransferLength = Srb->DataTransferLength; 7592 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7593 // reset this to force PRD init. May be already setup by recursive SRB 7594 AtaReq->dma_entries = 0; 7595 7596 // check if reorderable 7597 switch(Srb->Cdb[0]) { 7598 case SCSIOP_READ16: 7599 case SCSIOP_WRITE16: 7600 7601 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks); 7602 MOV_QD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA); 7603 goto GetLba2; 7604 7605 case SCSIOP_READ12: 7606 case SCSIOP_WRITE12: 7607 7608 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks); 7609 goto GetLba; 7610 7611 case SCSIOP_READ: 7612 case SCSIOP_WRITE: 7613 7614 MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks); 7615 GetLba: 7616 MOV_DD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB10.LBA); 7617 GetLba2: 7618 AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD; 7619 AtaReq->Flags &= ~REQ_FLAG_RW_MASK; 7620 AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE || 7621 Srb->Cdb[0] == SCSIOP_WRITE12 || 7622 Srb->Cdb[0] == SCSIOP_WRITE16) ? 7623 REQ_FLAG_WRITE : REQ_FLAG_READ; 7624 break; 7625 default: 7626 AtaReq->Flags &= ~REQ_FLAG_RW_MASK; 7627 if(!AtaReq->TransferLength) { 7628 KdPrint((" assume 0-transfer\n")); 7629 } else 7630 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { 7631 KdPrint((" assume OUT\n")); 7632 AtaReq->Flags |= REQ_FLAG_WRITE; 7633 } else 7634 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 7635 KdPrint((" assume IN\n")); 7636 AtaReq->Flags |= REQ_FLAG_READ; 7637 } 7638 break; 7639 } 7640 7641 // check if DMA read/write 7642 if(g_opt_AtapiNoDma) { 7643 KdPrint2((PRINT_PREFIX "AtapiSendCommand: CTRFLAGS_DMA_BEFORE_R => no dma\n")); 7644 use_dma = FALSE; 7645 } else 7646 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7647 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (ahci)\n")); 7648 use_dma = TRUE; 7649 goto setup_dma; 7650 } else 7651 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) { 7652 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n")); 7653 use_dma = TRUE; 7654 goto setup_dma; 7655 } else*/ 7656 if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) { 7657 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n")); 7658 } else 7659 if(AtaReq->TransferLength && !(AtaReq->TransferLength & 0x0f)) { 7660 KdPrint2((PRINT_PREFIX "AtapiSendCommand: try DMA setup\n")); 7661 // try use DMA if TransferLength is 16-byte aligned 7662 switch(Srb->Cdb[0]) { 7663 case SCSIOP_WRITE: 7664 case SCSIOP_WRITE12: 7665 case SCSIOP_WRITE16: 7666 case SCSIOP_SEND: 7667 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) 7668 break; 7669 /* FALLTHROUGH */ 7670 case SCSIOP_RECEIVE: 7671 case SCSIOP_READ: 7672 case SCSIOP_READ12: 7673 case SCSIOP_READ16: 7674 7675 if(deviceExtension->opt_AtapiDmaReadWrite) { 7676 call_dma_setup: 7677 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7678 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n")); 7679 use_dma = TRUE; 7680 } else 7681 if(AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 7682 (PUCHAR)(AtaReq->DataBuffer), 7683 Srb->DataTransferLength 7684 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/ 7685 )) { 7686 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n")); 7687 use_dma = TRUE; 7688 } 7689 } 7690 break; 7691 case SCSIOP_READ_CD: 7692 case SCSIOP_READ_CD_MSF: 7693 if(deviceExtension->opt_AtapiDmaRawRead) 7694 goto call_dma_setup; 7695 break; 7696 default: 7697 7698 if(deviceExtension->opt_AtapiDmaControlCmd) { 7699 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 7700 // read operation 7701 use_dma = TRUE; 7702 } else { 7703 // write operation 7704 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) { 7705 KdPrint2((PRINT_PREFIX "dma RO\n")); 7706 use_dma = FALSE; 7707 } else { 7708 use_dma = TRUE; 7709 } 7710 } 7711 } 7712 break; 7713 } 7714 // try setup DMA 7715 setup_dma: 7716 if(use_dma) { 7717 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7718 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n")); 7719 //use_dma = TRUE; 7720 } else 7721 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 7722 (PUCHAR)(AtaReq->DataBuffer), 7723 Srb->DataTransferLength)) { 7724 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma\n")); 7725 use_dma = FALSE; 7726 } else { 7727 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n")); 7728 } 7729 } 7730 } else { 7731 KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero/unaligned transfer %x, no DMA setup\n", AtaReq->TransferLength)); 7732 } 7733 7734 7735 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7736 7737 UniataAhciSetupCmdPtr(AtaReq); 7738 7739 if(!Srb->DataTransferLength) { 7740 KdPrint2((PRINT_PREFIX "zero-transfer\n")); 7741 use_dma = FALSE; 7742 } else 7743 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 7744 (PUCHAR)(AtaReq->DataBuffer), 7745 Srb->DataTransferLength)) { 7746 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no AHCI dma!\n")); 7747 return SRB_STATUS_ERROR; 7748 } 7749 if(!use_dma) { 7750 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7751 } else { 7752 FeatureReg |= ATA_F_DMA; 7753 if(LunExt->IdentifyData.AtapiDMA.DMADirRequired) { 7754 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 7755 KdPrint2((PRINT_PREFIX "Set DMADir.\n")); 7756 FeatureReg |= ATA_F_DMAREAD; 7757 } 7758 } 7759 } 7760 7761 KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n")); 7762 // this is done in UniataAhciSetupFIS_H2D() 7763 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis)); 7764 RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, Srb->CdbLength); 7765 7766 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel, 7767 &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]), 7768 IDE_COMMAND_ATAPI_PACKET /* command */, 7769 0 /* lba */, 7770 (Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength), 7771 FeatureReg/* feature */ 7772 ); 7773 7774 if(!fis_size) { 7775 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n")); 7776 return SRB_STATUS_ERROR; 7777 } 7778 7779 AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0, 7780 ((Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) ? ATA_AHCI_CMD_WRITE : 0) | 7781 (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH), 7782 fis_size, DeviceNumber); 7783 7784 KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags)); 7785 } 7786 7787 } else { 7788 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) { 7789 // if this is queued request, reinit DMA and check 7790 // if DMA mode is still available 7791 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() (1)\n")); 7792 AtapiDmaReinit(deviceExtension, LunExt, AtaReq); 7793 if (/*EnableDma &&*/ 7794 (LunExt->TransferMode >= ATA_DMA)) { 7795 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (2)\n")); 7796 use_dma = TRUE; 7797 } else { 7798 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7799 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma (2)\n")); 7800 use_dma = FALSE; 7801 } 7802 dma_reinited = TRUE; 7803 } 7804 } 7805 7806 if(!(CmdAction & CMD_ACTION_EXEC)) { 7807 KdPrint2((PRINT_PREFIX "AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n")); 7808 return SRB_STATUS_PENDING; 7809 } 7810 KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma, Srb->Cdb[0])); 7811 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) { 7812 KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n")); 7813 } 7814 7815 if((Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) && !(deviceExtension->HwFlags & UNIATA_SATA)) { 7816 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n")); 7817 use_dma = FALSE; 7818 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7819 AtapiDmaReinit(deviceExtension, LunExt, AtaReq); 7820 } if(AtaReq->TransferLength) { 7821 if(!dma_reinited) { 7822 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()\n")); 7823 AtapiDmaReinit(deviceExtension, LunExt, AtaReq); 7824 if (/*EnableDma &&*/ 7825 (LunExt->TransferMode >= ATA_DMA)) { 7826 use_dma = TRUE; 7827 } else { 7828 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7829 use_dma = FALSE; 7830 } 7831 } 7832 } else { 7833 KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer\n")); 7834 use_dma = FALSE; 7835 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7836 if(!deviceExtension->opt_AtapiDmaZeroTransfer && !(deviceExtension->HwFlags & UNIATA_SATA)) { 7837 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() to PIO\n")); 7838 AtapiDmaReinit(deviceExtension, LunExt, AtaReq); 7839 } 7840 } 7841 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma)); 7842 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) { 7843 KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n")); 7844 } 7845 7846 KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_EXEC\n")); 7847 7848 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n", 7849 &(Srb->Cdb), Srb->Cdb[0], Srb->TargetId, Srb->Lun)); 7850 7851 // Make sure command is to ATAPI device. 7852 flags = LunExt->DeviceFlags; 7853 if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) { 7854 if((Srb->Lun) > (LunExt->DiscsPresent - 1)) { 7855 7856 // Indicate no device found at this address. 7857 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7858 return SRB_STATUS_SELECTION_TIMEOUT; 7859 } 7860 } else if(Srb->Lun > 0) { 7861 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7862 return SRB_STATUS_SELECTION_TIMEOUT; 7863 } 7864 7865 if(!(flags & DFLAGS_ATAPI_DEVICE)) { 7866 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7867 return SRB_STATUS_SELECTION_TIMEOUT; 7868 } 7869 retry: 7870 // Select device 0 or 1. Or more for PM 7871 SelectDrive(chan, DeviceNumber); 7872 7873 // Verify that controller is ready for next command. 7874 GetStatus(chan, statusByte); 7875 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte)); 7876 7877 if(statusByte == IDE_STATUS_WRONG) { 7878 KdPrint2((PRINT_PREFIX "AtapiSendCommand: bad status 0xff on entry\n")); 7879 goto make_reset; 7880 } 7881 if(statusByte & IDE_STATUS_BUSY) { 7882 if(statusByte & IDE_STATUS_DSC) { 7883 KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte)); 7884 } else { 7885 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte)); 7886 // We have to make reset here, since we are expecting device to be available 7887 //return SRB_STATUS_BUSY; // this cause queue freeze 7888 goto make_reset; 7889 } 7890 } 7891 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7892 ULONG CI; 7893 // Check if command list is free 7894 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI); 7895 if(CI) { 7896 // controller is busy, however we expect it to be free 7897 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI)); 7898 goto make_reset; 7899 } 7900 } 7901 if(statusByte & IDE_STATUS_ERROR) { 7902 if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) { 7903 7904 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on entry: (%#x)\n", statusByte)); 7905 // Read the error reg. to clear it and fail this request. 7906 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7907 return MapError(deviceExtension, Srb); 7908 } else { 7909 KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n", statusByte)); 7910 } 7911 } 7912 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send 7913 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157. 7914 if((!(statusByte & IDE_STATUS_DSC)) && 7915 (flags & (DFLAGS_TAPE_DEVICE | DFLAGS_ATAPI_DEVICE)) && chan->RDP) { 7916 7917 AtapiStallExecution(200); 7918 KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte)); 7919 AtaReq->ReqState = REQ_STATE_QUEUED; 7920 return SRB_STATUS_PENDING; 7921 } 7922 7923 if(IS_RDP(Srb->Cdb[0])) { 7924 chan->RDP = TRUE; 7925 KdPrint2((PRINT_PREFIX "AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb->Cdb[0])); 7926 } else { 7927 chan->RDP = FALSE; 7928 } 7929 if(statusByte & IDE_STATUS_DRQ) { 7930 7931 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n", 7932 statusByte)); 7933 // Try to drain the data that one preliminary device thinks that it has 7934 // to transfer. Hopefully this random assertion of DRQ will not be present 7935 // in production devices. 7936 statusByte = AtapiSuckPort2(chan); 7937 /* 7938 for (i = 0; i < 0x10000; i++) { 7939 GetStatus(chan, statusByte); 7940 if(statusByte & IDE_STATUS_DRQ) { 7941 AtapiReadPort2(chan, IDX_IO1_i_Data); 7942 } else { 7943 break; 7944 } 7945 } 7946 */ 7947 if (statusByte & IDE_STATUS_DRQ) { 7948 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted. Status (%#x)\n", statusByte)); 7949 make_reset: 7950 AtapiDisableInterrupts(deviceExtension, lChannel); 7951 7952 AtapiSoftReset(chan, DeviceNumber); 7953 7954 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Issued soft reset to Atapi device. \n")); 7955 // Re-initialize Atapi device. 7956 CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), DeviceNumber, TRUE); 7957 /* 7958 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb), 7959 IDE_COMMAND_ATAPI_IDENTIFY, FALSE); 7960 */ 7961 // Inform the port driver that the bus has been reset. 7962 ScsiPortNotification(ResetDetected, HwDeviceExtension, 0); 7963 // Clean up device extension fields that AtapiStartIo won't. 7964 UniataExpectChannelInterrupt(chan, FALSE); 7965 chan->RDP = FALSE; 7966 InterlockedExchange(&(deviceExtension->chan[GET_CHANNEL(Srb)].CheckIntr), 7967 CHECK_INTR_IDLE); 7968 7969 AtapiEnableInterrupts(deviceExtension, lChannel); 7970 /* 7971 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7972 return SRB_STATUS_BUS_RESET; 7973 */ 7974 if(!retried) { 7975 KdPrint3((PRINT_PREFIX "AtapiSendCommand: retry after reset.\n")); 7976 retried = TRUE; 7977 goto retry; 7978 } 7979 KdPrint3((PRINT_PREFIX "AtapiSendCommand: selection timeout.\n")); 7980 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7981 return SRB_STATUS_SELECTION_TIMEOUT; 7982 } 7983 } 7984 7985 if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) { 7986 // As the cdrom driver sets the LUN field in the cdb, it must be removed. 7987 Srb->Cdb[1] &= ~0xE0; 7988 if((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) { 7989 // Torisan changer. TUR's are overloaded to be platter switches. 7990 Srb->Cdb[7] = Srb->Lun; 7991 } 7992 } 7993 7994 // SETUP DMA !!!!! 7995 7996 if(use_dma) { 7997 chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION; 7998 } else { 7999 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; 8000 } 8001 8002 if(deviceExtension->HwFlags & UNIATA_AHCI) { 8003 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n")); 8004 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling 8005 UniataExpectChannelInterrupt(chan, TRUE); 8006 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 8007 return SRB_STATUS_PENDING; 8008 } 8009 8010 statusByte = WaitOnBusy(chan); 8011 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n", 8012 statusByte)); 8013 8014 if(use_dma) { 8015 FeatureReg |= ATA_F_DMA; 8016 if(LunExt->IdentifyData.AtapiDMA.DMADirRequired) { 8017 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 8018 FeatureReg |= ATA_F_DMAREAD; 8019 } 8020 } 8021 } 8022 8023 // Write transfer byte count to registers. 8024 if (Srb->DataTransferLength >= 0x10000) { 8025 byteCountLow = byteCountHigh = 0xFF; 8026 } else { 8027 byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF); 8028 byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8); 8029 } 8030 8031 KdPrint3((PRINT_PREFIX "AtapiSendCommand: F:%#x, CntHL:%#x:%#x.\n", FeatureReg, byteCountHigh, byteCountLow)); 8032 8033 if (flags & DFLAGS_INT_DRQ) { 8034 // This device interrupts when ready to receive the packet. 8035 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n", 8036 statusByte)); 8037 8038 UniataExpectChannelInterrupt(chan, TRUE); 8039 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR; 8040 InterlockedExchange(&(chan->CheckIntr), 8041 CHECK_INTR_IDLE); 8042 // inform driver that packet command must be sent in ISR 8043 flags |= DFLAGS_INT_DRQ; 8044 } else { 8045 // This device quickly sets DRQ when ready to receive the packet. 8046 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n", 8047 statusByte)); 8048 8049 UniataExpectChannelInterrupt(chan, TRUE); 8050 AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR; 8051 InterlockedExchange(&(chan->CheckIntr), 8052 CHECK_INTR_IDLE); 8053 8054 if(g_opt_AtapiSendDisableIntr) { 8055 AtapiDisableInterrupts(deviceExtension, lChannel); 8056 } 8057 // remember status. Later we may check if error appeared after cmd packet 8058 statusByte0 = statusByte; 8059 } 8060 8061 // must be already selected, experimental for ROS BUG-9119 8062 //AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) ); 8063 AtapiWritePort1(chan, IDX_IO2_o_Control , 0); 8064 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Feature /*IDX_IO1_o_Feature*/, FeatureReg); 8065 //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused0, 0); // experimental for ROS BUG-9119 8066 //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused1, 0); // experimental for ROS BUG-9119 8067 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow); 8068 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh); 8069 // Write ATAPI packet command. 8070 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Command /*IDX_IO1_o_Command*/, IDE_COMMAND_ATAPI_PACKET); 8071 8072 if (flags & DFLAGS_INT_DRQ) { 8073 // Wait for interrupt and send PACKET there 8074 KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n")); 8075 return SRB_STATUS_PENDING; 8076 } 8077 8078 WaitOnBusy(chan); 8079 /* 8080 // Wait for DRQ. 8081 statusByte = WaitForDrq(chan); 8082 8083 // Need to read status register and clear interrupt (if any) 8084 GetBaseStatus(chan, statusByte); 8085 8086 if (!(statusByte & IDE_STATUS_DRQ)) { 8087 if(g_opt_AtapiSendDisableIntr) { 8088 AtapiEnableInterrupts(deviceExtension, lChannel); 8089 } 8090 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte)); 8091 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 8092 return SRB_STATUS_ERROR; 8093 } 8094 */ 8095 GetStatus(chan, statusByte); 8096 KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte)); 8097 8098 //statusByte = WaitOnBaseBusy(chan); 8099 8100 // Indicate expecting an interrupt and wait for it. 8101 UniataExpectChannelInterrupt(chan, TRUE); 8102 8103 for(i=0; i<5000; i++) { 8104 if(g_opt_AtapiSendDisableIntr) { 8105 GetStatus(chan, statusByte); 8106 } else { 8107 GetBaseStatus(chan, statusByte); 8108 } 8109 interruptReason = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason); 8110 //KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i)); 8111 if(((interruptReason & ATAPI_IR_COD) == ATAPI_IR_COD_Cmd) && 8112 (((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) == IDE_STATUS_DRQ))) { 8113 break; 8114 } 8115 AtapiStallExecution(g_opt_WaitDrqDelay*2); 8116 #ifdef _DEBUG 8117 // KdPrint3((PRINT_PREFIX "AtapiSendCommand: wait CoD, status (%#x)\n", interruptReason)); 8118 #endif // _DEBUG 8119 } 8120 if(((interruptReason & ATAPI_IR_COD) != ATAPI_IR_COD_Cmd) || 8121 (((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) != IDE_STATUS_DRQ)) ) { 8122 KdPrint3((PRINT_PREFIX "AtapiSendCommand: no CoD raised, abort cmd\n")); 8123 KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i)); 8124 KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte)); 8125 if(g_opt_AtapiSendDisableIntr) { 8126 AtapiEnableInterrupts(deviceExtension, lChannel); 8127 } 8128 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ+CoD never asserted\n")); 8129 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 8130 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte)); 8131 if(statusByte >> 4) { 8132 GetBaseStatus(chan, statusByte); 8133 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 8134 return MapError(deviceExtension, Srb); 8135 } 8136 goto make_reset; 8137 // AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 8138 // return SRB_STATUS_ERROR; 8139 } else { 8140 KdPrint3((PRINT_PREFIX "AtapiSendCommand: ready for packet, status %#x, i=%d\n", interruptReason, i)); 8141 } 8142 // clear interrupt 8143 GetBaseStatus(chan, statusByte); 8144 8145 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) { 8146 AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb); 8147 } 8148 if(g_opt_AtapiSendDisableIntr) { 8149 AtapiEnableInterrupts(deviceExtension, lChannel); 8150 } 8151 8152 // Send CDB to device. 8153 WriteBuffer(chan, 8154 (PUSHORT)Srb->Cdb, 8155 LunExt->IdentifyData.AtapiCmdSize ? 8 : 6, 8156 /*0*/ PIO0_TIMING); 8157 8158 GetStatus(chan, statusByte); 8159 KdPrint3((PRINT_PREFIX "AtapiSendCommand: cmd status (%#x)\n", statusByte)); 8160 8161 // When we operate in DMA mode, we should not start transfer when there is an error on entry 8162 // Interrupt may never come in such case. 8163 if(statusByte & IDE_STATUS_ERROR) { 8164 8165 GetBaseStatus(chan, statusByte); 8166 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on cmd: (%#x)\n", statusByte)); 8167 8168 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); 8169 KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x\n", interruptReason)); 8170 8171 // TODO: we should check interruptReason and decide what to do now 8172 8173 // Read the error reg. to clear it and fail this request. 8174 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 8175 return MapError(deviceExtension, Srb); 8176 } 8177 if(statusByte & IDE_STATUS_DRQ) { 8178 // Some devices require this. If error condition is not checked in such a way, 8179 // device may not operate correctly and would be treated as failed 8180 // (and finally invisible for OS) 8181 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ on cmd: (%#x)\n", statusByte)); 8182 // Read the error reg. to clear it and fail this request. 8183 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 8184 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte)); 8185 if(statusByte >> 4) { 8186 GetBaseStatus(chan, statusByte); 8187 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 8188 return MapError(deviceExtension, Srb); 8189 } 8190 } 8191 8192 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) { 8193 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); 8194 } 8195 8196 InterlockedExchange(&(chan->CheckIntr), 8197 CHECK_INTR_IDLE); 8198 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR; 8199 8200 KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt)); 8201 8202 KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (3)\n")); 8203 return SRB_STATUS_PENDING; 8204 8205 } // end AtapiSendCommand() 8206 8207 8208 #ifndef UNIATA_CORE 8209 8210 /*++ 8211 8212 Routine Description: 8213 Program ATA registers for IDE disk transfer. 8214 8215 Arguments: 8216 HwDeviceExtension - ATAPI driver storage. 8217 Srb - System request block. 8218 8219 Return Value: 8220 SRB status (pending if all goes well). 8221 8222 --*/ 8223 8224 #ifdef _DEBUG 8225 ULONG check_point = 0; 8226 #define SetCheckPoint(cp) { check_point = (cp) ; } 8227 #else 8228 #define SetCheckPoint(cp) 8229 #endif 8230 8231 ULONG 8232 NTAPI 8233 IdeSendCommand( 8234 IN PVOID HwDeviceExtension, 8235 IN PSCSI_REQUEST_BLOCK Srb, 8236 IN ULONG CmdAction 8237 ) 8238 { 8239 SetCheckPoint(1); 8240 KdPrint2((PRINT_PREFIX "** Ide: Command: entryway\n")); 8241 SetCheckPoint(2); 8242 8243 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 8244 SetCheckPoint(3); 8245 UCHAR lChannel; 8246 PHW_CHANNEL chan; 8247 PCDB cdb; 8248 PHW_LU_EXTENSION LunExt; 8249 8250 SetCheckPoint(4); 8251 8252 UCHAR statusByte,errorByte; 8253 ULONG status = SRB_STATUS_INVALID_REQUEST; 8254 ULONG i; 8255 ULONGLONG lba; 8256 PMODE_PARAMETER_HEADER modeData; 8257 //ULONG ldev; 8258 ULONG DeviceNumber; 8259 PATA_REQ AtaReq; 8260 UCHAR command; 8261 8262 SetCheckPoint(5); 8263 //ULONG __ebp__ = 0; 8264 8265 SetCheckPoint(0x20); 8266 KdPrint2((PRINT_PREFIX "** Ide: Command:\n\n")); 8267 /* __asm { 8268 mov eax,ebp 8269 mov __ebp__, eax 8270 }*/ 8271 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n", 8272 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0])); 8273 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n", 8274 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : "")); 8275 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n", 8276 Srb)); 8277 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n", 8278 Srb->SrbExtension)); 8279 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n", 8280 Srb->TargetId));*/ 8281 8282 SetCheckPoint(0x30); 8283 AtaReq = (PATA_REQ)(Srb->SrbExtension); 8284 8285 KdPrint2((PRINT_PREFIX "** Ide: Command &AtaReq %#x\n", 8286 &AtaReq)); 8287 KdPrint2((PRINT_PREFIX "** Ide: Command AtaReq %#x\n", 8288 AtaReq)); 8289 KdPrint2((PRINT_PREFIX "** --- **\n")); 8290 8291 lChannel = GET_CHANNEL(Srb); 8292 chan = &(deviceExtension->chan[lChannel]); 8293 //ldev = GET_LDEV(Srb); 8294 DeviceNumber = GET_CDEV(Srb); 8295 LunExt = chan->lun[DeviceNumber]; 8296 8297 SetCheckPoint(0x40); 8298 if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER) 8299 AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER; 8300 8301 cdb = (PCDB)(Srb->Cdb); 8302 8303 if(CmdAction == CMD_ACTION_PREPARE) { 8304 switch (Srb->Cdb[0]) { 8305 case SCSIOP_SERVICE_ACTION16: 8306 if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) { 8307 // ok 8308 } else { 8309 goto default_no_prep; 8310 } 8311 #ifdef NAVO_TEST 8312 case SCSIOP_INQUIRY: // now it requires device access 8313 #endif //NAVO_TEST 8314 case SCSIOP_READ_CAPACITY: 8315 case SCSIOP_READ: 8316 case SCSIOP_WRITE: 8317 case SCSIOP_READ12: 8318 case SCSIOP_WRITE12: 8319 case SCSIOP_READ16: 8320 case SCSIOP_WRITE16: 8321 case SCSIOP_REQUEST_SENSE: 8322 // all right 8323 KdPrint2((PRINT_PREFIX "** Ide: Command continue prep\n")); 8324 SetCheckPoint(50); 8325 break; 8326 default: 8327 default_no_prep: 8328 SetCheckPoint(0); 8329 KdPrint2((PRINT_PREFIX "** Ide: Command break prep\n")); 8330 return SRB_STATUS_BUSY; 8331 } 8332 } 8333 8334 SetCheckPoint(0x100 | Srb->Cdb[0]); 8335 switch (Srb->Cdb[0]) { 8336 case SCSIOP_INQUIRY: 8337 8338 KdPrint2((PRINT_PREFIX 8339 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n", 8340 Srb->PathId, Srb->Lun, Srb->TargetId)); 8341 // Filter out wrong TIDs. 8342 if ((Srb->Lun != 0) || 8343 (Srb->PathId >= deviceExtension->NumberChannels) || 8344 (Srb->TargetId >= deviceExtension->NumberLuns)) { 8345 8346 KdPrint2((PRINT_PREFIX 8347 "IdeSendCommand: SCSIOP_INQUIRY rejected\n")); 8348 // Indicate no device found at this address. 8349 status = SRB_STATUS_SELECTION_TIMEOUT; 8350 break; 8351 8352 } else { 8353 8354 KdPrint2((PRINT_PREFIX 8355 "IdeSendCommand: SCSIOP_INQUIRY ok\n")); 8356 PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer); 8357 PIDENTIFY_DATA2 identifyData = &(LunExt->IdentifyData); 8358 8359 if (!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 8360 8361 if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) { 8362 KdPrint2((PRINT_PREFIX 8363 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n")); 8364 // Indicate no device found at this address. 8365 #ifndef NAVO_TEST 8366 status = SRB_STATUS_SELECTION_TIMEOUT; 8367 break; 8368 } 8369 } else { 8370 if(!UniataAnybodyHome(HwDeviceExtension, lChannel, DeviceNumber)) { 8371 KdPrint2((PRINT_PREFIX 8372 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n")); 8373 // Indicate no device found at this address. 8374 UniataForgetDevice(chan->lun[DeviceNumber]); 8375 #endif //NAVO_TEST 8376 status = SRB_STATUS_SELECTION_TIMEOUT; 8377 break; 8378 } 8379 } 8380 8381 // Zero INQUIRY data structure. 8382 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength); 8383 8384 // Standard IDE interface only supports disks. 8385 inquiryData->DeviceType = DIRECT_ACCESS_DEVICE; 8386 8387 // Set the removable bit, if applicable. 8388 if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) { 8389 KdPrint2((PRINT_PREFIX 8390 "RemovableMedia\n")); 8391 inquiryData->RemovableMedia = 1; 8392 } 8393 // Set the Relative Addressing (LBA) bit, if applicable. 8394 if (LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) { 8395 inquiryData->RelativeAddressing = 1; 8396 KdPrint2((PRINT_PREFIX 8397 "RelativeAddressing\n")); 8398 } 8399 // Set the CommandQueue bit 8400 inquiryData->CommandQueue = 1; 8401 8402 // Fill in vendor identification fields. 8403 #ifdef __REACTOS__ 8404 FillDeviceIdentificationString(inquiryData, identifyData); 8405 #else 8406 for (i = 0; i < 24; i += 2) { 8407 MOV_DW_SWP(inquiryData->DeviceIdentificationString[i], ((PUCHAR)identifyData->ModelNumber)[i]); 8408 } 8409 #endif 8410 /* 8411 // Initialize unused portion of product id. 8412 for (i = 0; i < 4; i++) { 8413 inquiryData->ProductId[12+i] = ' '; 8414 } 8415 */ 8416 // Move firmware revision from IDENTIFY data to 8417 // product revision in INQUIRY data. 8418 for (i = 0; i < 4; i += 2) { 8419 MOV_DW_SWP(inquiryData->ProductRevisionLevel[i], ((PUCHAR)identifyData->FirmwareRevision)[i]); 8420 } 8421 8422 status = SRB_STATUS_SUCCESS; 8423 } 8424 8425 break; 8426 8427 case SCSIOP_REPORT_LUNS: { 8428 8429 ULONG alen; 8430 PREPORT_LUNS_INFO_HDR LunInfo; 8431 8432 KdPrint2((PRINT_PREFIX 8433 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n", 8434 Srb->PathId, Srb->Lun, Srb->TargetId)); 8435 8436 MOV_DD_SWP(alen, cdb->REPORT_LUNS.AllocationLength); 8437 8438 if(alen < 16) { 8439 goto invalid_cdb; 8440 } 8441 alen = 8; 8442 8443 LunInfo = (PREPORT_LUNS_INFO_HDR)(Srb->DataBuffer); 8444 RtlZeroMemory(LunInfo, 16); 8445 8446 MOV_DD_SWP( LunInfo->ListLength, alen ); 8447 Srb->DataTransferLength = 16; 8448 status = SRB_STATUS_SUCCESS; 8449 8450 break; } 8451 8452 case SCSIOP_MODE_SENSE: 8453 8454 KdPrint2((PRINT_PREFIX 8455 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n", 8456 Srb->PathId, Srb->Lun, Srb->TargetId)); 8457 8458 if(cdb->MODE_SENSE.PageCode == MODE_PAGE_POWER_CONDITION) { 8459 PMODE_POWER_CONDITION_PAGE modeData; 8460 8461 KdPrint2((PRINT_PREFIX "MODE_PAGE_POWER_CONDITION\n")); 8462 modeData = (PMODE_POWER_CONDITION_PAGE)(Srb->DataBuffer); 8463 if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_POWER_CONDITION_PAGE)) { 8464 status = SRB_STATUS_DATA_OVERRUN; 8465 } else { 8466 RtlZeroMemory(modeData, sizeof(MODE_POWER_CONDITION_PAGE)); 8467 modeData->PageCode = MODE_PAGE_POWER_CONDITION; 8468 #ifdef __REACTOS__ 8469 modeData->PageLength = sizeof(MODE_POWER_CONDITION_PAGE)-sizeof(MODE_PARAMETER_HEADER); 8470 #else 8471 modeData->PageLength = sizeof(MODE_PAGE_POWER_CONDITION)-sizeof(MODE_PARAMETER_HEADER); 8472 #endif 8473 modeData->Byte3.Fields.Idle = LunExt->PowerState <= StartStop_Power_Idle; 8474 modeData->Byte3.Fields.Standby = LunExt->PowerState == StartStop_Power_Standby; 8475 Srb->DataTransferLength = sizeof(MODE_POWER_CONDITION_PAGE); 8476 status = SRB_STATUS_SUCCESS; 8477 } 8478 } else 8479 if(cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) { 8480 PMODE_CACHING_PAGE modeData; 8481 8482 KdPrint2((PRINT_PREFIX "MODE_PAGE_CACHING\n")); 8483 modeData = (PMODE_CACHING_PAGE)(Srb->DataBuffer); 8484 if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) { 8485 status = SRB_STATUS_DATA_OVERRUN; 8486 } else { 8487 RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE)); 8488 modeData->PageCode = MODE_PAGE_CACHING; 8489 modeData->PageLength = sizeof(MODE_CACHING_PAGE)-sizeof(MODE_PARAMETER_HEADER); 8490 modeData->ReadDisableCache = (LunExt->DeviceFlags & DFLAGS_RCACHE_ENABLED) ? 0 : 1; 8491 modeData->WriteCacheEnable = (LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) ? 1 : 0; 8492 Srb->DataTransferLength = sizeof(MODE_CACHING_PAGE); 8493 status = SRB_STATUS_SUCCESS; 8494 } 8495 } else 8496 if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { 8497 8498 // This is used to determine if the media is write-protected. 8499 // Since IDE does not support mode sense then we will modify just the portion we need 8500 // so the higher level driver can determine if media is protected. 8501 8502 //SelectDrive(chan, DeviceNumber); 8503 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS); 8504 //statusByte = WaitOnBusy(chan); 8505 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY); 8506 8507 if (!(statusByte & IDE_STATUS_ERROR)) { 8508 8509 // no error occured return success, media is not protected 8510 UniataExpectChannelInterrupt(chan, FALSE); 8511 InterlockedExchange(&(chan->CheckIntr), 8512 CHECK_INTR_IDLE); 8513 status = SRB_STATUS_SUCCESS; 8514 8515 } else { 8516 8517 // error occured, handle it locally, clear interrupt 8518 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 8519 8520 GetBaseStatus(chan, statusByte); 8521 UniataExpectChannelInterrupt(chan, FALSE); 8522 InterlockedExchange(&(chan->CheckIntr), 8523 CHECK_INTR_IDLE); 8524 status = SRB_STATUS_SUCCESS; 8525 8526 if (errorByte & IDE_ERROR_DATA_ERROR) { 8527 8528 //media is write-protected, set bit in mode sense buffer 8529 modeData = (PMODE_PARAMETER_HEADER)Srb->DataBuffer; 8530 8531 Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER); 8532 modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; 8533 } 8534 } 8535 status = SRB_STATUS_SUCCESS; 8536 } else { 8537 status = SRB_STATUS_INVALID_REQUEST; 8538 } 8539 break; 8540 8541 case SCSIOP_TEST_UNIT_READY: 8542 8543 KdPrint2((PRINT_PREFIX 8544 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n", 8545 Srb->PathId, Srb->Lun, Srb->TargetId)); 8546 if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { 8547 8548 // Select device 0 or 1. 8549 //SelectDrive(chan, DeviceNumber); 8550 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS); 8551 // Wait for busy. If media has not changed, return success 8552 //statusByte = WaitOnBusy(chan); 8553 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY); 8554 8555 if (!(statusByte & IDE_STATUS_ERROR)){ 8556 UniataExpectChannelInterrupt(chan, FALSE); 8557 InterlockedExchange(&(chan->CheckIntr), 8558 CHECK_INTR_IDLE); 8559 status = SRB_STATUS_SUCCESS; 8560 } else { 8561 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 8562 if (errorByte == IDE_ERROR_DATA_ERROR){ 8563 8564 // Special case: If current media is write-protected, 8565 // the 0xDA command will always fail since the write-protect bit 8566 // is sticky,so we can ignore this error 8567 GetBaseStatus(chan, statusByte); 8568 UniataExpectChannelInterrupt(chan, FALSE); 8569 InterlockedExchange(&(chan->CheckIntr), 8570 CHECK_INTR_IDLE); 8571 status = SRB_STATUS_SUCCESS; 8572 8573 } else { 8574 8575 // Request sense buffer to be build 8576 UniataExpectChannelInterrupt(chan, TRUE); 8577 InterlockedExchange(&(chan->CheckIntr), 8578 CHECK_INTR_IDLE); 8579 status = SRB_STATUS_PENDING; 8580 } 8581 } 8582 } else { 8583 status = SRB_STATUS_SUCCESS; 8584 } 8585 8586 break; 8587 8588 case SCSIOP_READ_CAPACITY: 8589 8590 KdPrint2((PRINT_PREFIX 8591 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n", 8592 Srb->PathId, Srb->Lun, Srb->TargetId)); 8593 // Claim 512 byte blocks (big-endian). 8594 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000; 8595 i = DEV_BSIZE; 8596 RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY_DATA)); 8597 MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i ); 8598 8599 // Calculate last sector. 8600 if(!(i = (ULONG)LunExt->NumOfSectors)) { 8601 i = LunExt->IdentifyData.SectorsPerTrack * 8602 LunExt->IdentifyData.NumberOfHeads * 8603 LunExt->IdentifyData.NumberOfCylinders; 8604 } 8605 i--; 8606 8607 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress = 8608 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) | 8609 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3]; 8610 8611 MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress, i ); 8612 8613 KdPrint2((PRINT_PREFIX 8614 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n", 8615 Srb->TargetId, 8616 LunExt->IdentifyData.SectorsPerTrack, 8617 LunExt->IdentifyData.NumberOfHeads, 8618 LunExt->IdentifyData.NumberOfCylinders)); 8619 8620 8621 status = SRB_STATUS_SUCCESS; 8622 break; 8623 8624 case SCSIOP_SERVICE_ACTION16: 8625 8626 if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) { 8627 KdPrint2((PRINT_PREFIX 8628 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n", 8629 Srb->PathId, Srb->Lun, Srb->TargetId)); 8630 // Claim 512 byte blocks (big-endian). 8631 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000; 8632 i = DEV_BSIZE; 8633 RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY16_DATA)); 8634 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->BytesPerBlock, i ); 8635 8636 // Calculate last sector. 8637 if(!(lba = LunExt->NumOfSectors)) { 8638 lba = LunExt->IdentifyData.SectorsPerTrack * 8639 LunExt->IdentifyData.NumberOfHeads * 8640 LunExt->IdentifyData.NumberOfCylinders; 8641 } 8642 lba--; 8643 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->LogicalBlockAddress, lba ); 8644 8645 KdPrint2((PRINT_PREFIX 8646 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n", 8647 Srb->TargetId, 8648 LunExt->IdentifyData.SectorsPerTrack, 8649 LunExt->IdentifyData.NumberOfHeads, 8650 LunExt->IdentifyData.NumberOfCylinders)); 8651 8652 status = SRB_STATUS_SUCCESS; 8653 } else { 8654 goto default_abort; 8655 } 8656 break; 8657 8658 case SCSIOP_VERIFY: 8659 case SCSIOP_VERIFY12: 8660 case SCSIOP_VERIFY16: 8661 8662 KdPrint2((PRINT_PREFIX 8663 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n", 8664 Srb->PathId, Srb->Lun, Srb->TargetId)); 8665 status = IdeVerify(HwDeviceExtension,Srb); 8666 8667 break; 8668 8669 case SCSIOP_READ: 8670 case SCSIOP_WRITE: 8671 case SCSIOP_READ12: 8672 case SCSIOP_WRITE12: 8673 case SCSIOP_READ16: 8674 case SCSIOP_WRITE16: 8675 8676 KdPrint2((PRINT_PREFIX 8677 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n", 8678 (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ", 8679 Srb->PathId, Srb->Lun, Srb->TargetId)); 8680 AtaReq->Flags &= ~REQ_FLAG_RW_MASK; 8681 AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE || 8682 Srb->Cdb[0] == SCSIOP_WRITE12 || 8683 Srb->Cdb[0] == SCSIOP_WRITE16) ? REQ_FLAG_WRITE : REQ_FLAG_READ; 8684 status = IdeReadWrite(HwDeviceExtension, 8685 Srb, CmdAction); 8686 break; 8687 8688 case SCSIOP_START_STOP_UNIT: 8689 8690 KdPrint2((PRINT_PREFIX 8691 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n", 8692 cdb->START_STOP.Immediate, Srb->PathId, Srb->Lun, Srb->TargetId)); 8693 //Determine what type of operation we should perform 8694 8695 command = 0; 8696 8697 if(cdb->START_STOP.FL || 8698 cdb->START_STOP.FormatLayerNumber || 8699 cdb->START_STOP.Reserved2 || 8700 cdb->START_STOP.Reserved2_2 || 8701 cdb->START_STOP.Reserved3 || 8702 FALSE) { 8703 goto invalid_cdb; 8704 } 8705 8706 if (cdb->START_STOP.PowerConditions) { 8707 KdPrint2((PRINT_PREFIX "START_STOP Power %d\n", cdb->START_STOP.PowerConditions)); 8708 switch(cdb->START_STOP.PowerConditions) { 8709 case StartStop_Power_Idle: 8710 command = IDE_COMMAND_IDLE_IMMED; 8711 break; 8712 case StartStop_Power_Standby: 8713 command = IDE_COMMAND_STANDBY_IMMED; 8714 break; 8715 case StartStop_Power_Sleep: 8716 // TODO: we should save power state in order to know 8717 // that RESET sould be issued to revert device into 8718 // operable state 8719 8720 command = IDE_COMMAND_SLEEP; 8721 break; 8722 default: 8723 goto invalid_cdb; 8724 } 8725 LunExt->PowerState = cdb->START_STOP.PowerConditions; 8726 } else 8727 if (cdb->START_STOP.LoadEject == 1) { 8728 KdPrint2((PRINT_PREFIX "START_STOP eject\n")); 8729 // Eject media, 8730 // first select device 0 or 1. 8731 //SelectDrive(chan, DeviceNumber); 8732 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT); 8733 command = IDE_COMMAND_MEDIA_EJECT; 8734 } else 8735 if (cdb->START_STOP.Start == 0) { 8736 KdPrint2((PRINT_PREFIX "START_STOP standby\n")); 8737 command = IDE_COMMAND_STANDBY_IMMED; 8738 } else { 8739 // TODO: we may need to perform hard reset (after sleep) or 8740 // issue IDE_COMMAND_IDLE_IMMED in order to activate device 8741 KdPrint2((PRINT_PREFIX "START_STOP activate\n")); 8742 8743 if(LunExt->PowerState == StartStop_Power_Sleep) { 8744 UniataUserDeviceReset(deviceExtension, LunExt, lChannel); 8745 status = SRB_STATUS_SUCCESS; 8746 break; 8747 } else 8748 if(LunExt->PowerState > StartStop_Power_Idle) { 8749 KdPrint2((PRINT_PREFIX " issue IDLE\n")); 8750 command = IDE_COMMAND_IDLE_IMMED; 8751 } else { 8752 KdPrint2((PRINT_PREFIX " do nothing\n")); 8753 status = SRB_STATUS_SUCCESS; 8754 break; 8755 } 8756 } 8757 if(command) { 8758 statusByte = WaitOnBaseBusy(chan); 8759 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, command, 0, 0, 0, 0, 0, 8760 cdb->START_STOP.Immediate ? ATA_IMMEDIATE : ATA_WAIT_READY); 8761 status = (statusByte & IDE_STATUS_ERROR) ? SRB_STATUS_ERROR : SRB_STATUS_SUCCESS; 8762 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt 8763 8764 } else { 8765 invalid_cdb: 8766 KdPrint2((PRINT_PREFIX "START_STOP invalid\n")); 8767 if (Srb->SenseInfoBuffer) { 8768 8769 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 8770 8771 senseBuffer->ErrorCode = 0x70; 8772 senseBuffer->Valid = 1; 8773 senseBuffer->AdditionalSenseLength = 0xb; 8774 senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST; 8775 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_CDB; 8776 senseBuffer->AdditionalSenseCodeQualifier = 0; 8777 8778 Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID; 8779 Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; 8780 } 8781 status = SRB_STATUS_ERROR; 8782 } 8783 break; 8784 8785 case SCSIOP_MEDIUM_REMOVAL: 8786 8787 cdb = (PCDB)Srb->Cdb; 8788 8789 if(LunExt->IdentifyData.Removable) { 8790 statusByte = WaitOnBaseBusy(chan); 8791 8792 //SelectDrive(chan, DeviceNumber); 8793 if (cdb->MEDIA_REMOVAL.Prevent == TRUE) { 8794 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK); 8795 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_LOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE); 8796 } else { 8797 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK); 8798 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_UNLOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE); 8799 } 8800 status = SRB_STATUS_SUCCESS; 8801 } else { 8802 status = SRB_STATUS_INVALID_REQUEST; 8803 } 8804 break; 8805 8806 #if 0 8807 // Note: I don't implement this, because NTFS driver too often issues this command 8808 // It causes awful performance degrade. However, if somebody wants, I will implement 8809 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally. 8810 case SCSIOP_FLUSH_BUFFER: 8811 case SCSIOP_SYNCHRONIZE_CACHE: 8812 8813 SelectDrive(chan, DeviceNumber); 8814 AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_FLUSH_CACHE); 8815 status = SRB_STATUS_SUCCESS; 8816 // status = SRB_STATUS_PENDING; 8817 statusByte = WaitOnBusy(chan); 8818 break; 8819 #endif 8820 8821 case SCSIOP_REQUEST_SENSE: 8822 // this function makes sense buffers to report the results 8823 // of the original GET_MEDIA_STATUS command 8824 8825 KdPrint2((PRINT_PREFIX 8826 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n", 8827 Srb->PathId, Srb->Lun, Srb->TargetId)); 8828 if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { 8829 status = IdeBuildSenseBuffer(HwDeviceExtension,Srb); 8830 break; 8831 } 8832 status = SRB_STATUS_INVALID_REQUEST; 8833 break; 8834 8835 // ATA_PASSTHORUGH 8836 case SCSIOP_ATA_PASSTHROUGH: 8837 { 8838 PIDEREGS_EX regs; 8839 BOOLEAN use_dma = FALSE; 8840 ULONG to_lim; 8841 8842 regs = (PIDEREGS_EX) &(Srb->Cdb[2]); 8843 8844 if(chan->DeviceExtension->HwFlags & UNIATA_SATA) { 8845 //lChannel = Srb->TargetId >> 1; 8846 } else { 8847 DeviceNumber = max(DeviceNumber, 1); 8848 regs->bDriveHeadReg &= 0x0f; 8849 regs->bDriveHeadReg |= (UCHAR) (((DeviceNumber & 0x1) << 4) | 0xA0); 8850 } 8851 8852 if((regs->bOpFlags & 1) == 0) { // execute ATA command 8853 8854 KdPrint2((PRINT_PREFIX 8855 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n", 8856 Srb->PathId, Srb->Lun, Srb->TargetId)); 8857 8858 if((regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) == UNIATA_SPTI_EX_SPEC_TO) { 8859 to_lim = Srb->TimeOutValue; 8860 } else { 8861 if(Srb->TimeOutValue <= 2) { 8862 to_lim = Srb->TimeOutValue*900; 8863 } else { 8864 to_lim = (Srb->TimeOutValue*999) - 500; 8865 } 8866 } 8867 8868 AtapiDisableInterrupts(deviceExtension, lChannel); 8869 8870 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { 8871 // AHCI 8872 statusByte = UniataAhciSendPIOCommandDirect( 8873 deviceExtension, 8874 lChannel, 8875 DeviceNumber, 8876 Srb, 8877 regs, 8878 ATA_WAIT_INTR, 8879 to_lim 8880 ); 8881 if(statusByte == IDE_STATUS_WRONG) { 8882 goto passthrough_err; 8883 } 8884 if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) { 8885 UniataAhciAbortOperation(chan); 8886 goto passthrough_err; 8887 } 8888 goto passthrough_done; 8889 } 8890 8891 // SATA/PATA 8892 if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) { 8893 if((chan->lun[DeviceNumber]->LimitedTransferMode >= ATA_DMA)) { 8894 use_dma = TRUE; 8895 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success 8896 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 8897 (PUCHAR)(Srb->DataBuffer), 8898 ((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) { 8899 use_dma = FALSE; 8900 } 8901 } 8902 } 8903 8904 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg); 8905 AtapiStallExecution(10); 8906 if(use_dma) { 8907 AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb); 8908 } 8909 8910 if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command 8911 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg); 8912 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg); 8913 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg); 8914 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg); 8915 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg); 8916 } else { 8917 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesRegH); 8918 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg); 8919 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountRegH); 8920 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg); 8921 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberRegH); 8922 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg); 8923 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowRegH); 8924 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg); 8925 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighRegH); 8926 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg); 8927 } 8928 AtapiWritePort1(chan, IDX_IO1_o_Command, regs->bCommandReg); 8929 8930 if(use_dma) { 8931 GetBaseStatus(chan, statusByte); 8932 if(statusByte & IDE_STATUS_ERROR) { 8933 goto passthrough_err; 8934 } 8935 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); 8936 } 8937 8938 ScsiPortStallExecution(1); // wait for busy to be set 8939 8940 for(i=0; i<to_lim;i+=2) { // 2 msec from WaitOnBaseBusy() 8941 statusByte = WaitOnBaseBusy(chan); // wait for busy to be clear, up to 2 msec 8942 GetBaseStatus(chan, statusByte); 8943 if(statusByte & IDE_STATUS_ERROR) { 8944 break; 8945 } 8946 if(!(statusByte & IDE_STATUS_BUSY)) { 8947 break; 8948 } 8949 } 8950 if(i >= to_lim) { 8951 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) { 8952 //} 8953 AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_NONE); 8954 goto passthrough_err; 8955 } 8956 8957 if(use_dma) { 8958 AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel); 8959 } 8960 AtapiDmaDone(deviceExtension, DeviceNumber, lChannel, NULL); 8961 GetBaseStatus(chan, statusByte); 8962 8963 if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) { 8964 AtapiSuckPort2(chan); 8965 passthrough_err: 8966 if (Srb->SenseInfoBuffer) { 8967 8968 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 8969 8970 senseBuffer->ErrorCode = 0x70; 8971 senseBuffer->Valid = 1; 8972 senseBuffer->AdditionalSenseLength = 0xb; 8973 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND; 8974 senseBuffer->AdditionalSenseCode = 0; 8975 senseBuffer->AdditionalSenseCodeQualifier = 0; 8976 8977 Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID; 8978 Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; 8979 } 8980 status = SRB_STATUS_ERROR; 8981 } else { 8982 8983 if(!use_dma) { 8984 if (statusByte & IDE_STATUS_DRQ) { 8985 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 8986 ReadBuffer(chan, 8987 (PUSHORT) Srb->DataBuffer, 8988 Srb->DataTransferLength / 2, 8989 0); 8990 } else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { 8991 WriteBuffer(chan, 8992 (PUSHORT) Srb->DataBuffer, 8993 Srb->DataTransferLength / 2, 8994 0); 8995 } 8996 } 8997 } 8998 status = SRB_STATUS_SUCCESS; 8999 } 9000 passthrough_done:; 9001 AtapiEnableInterrupts(deviceExtension, lChannel); 9002 9003 } else { // read task register 9004 9005 BOOLEAN use48; 9006 regs = (PIDEREGS_EX) Srb->DataBuffer; 9007 9008 KdPrint2((PRINT_PREFIX 9009 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n", 9010 Srb->PathId, Srb->Lun, Srb->TargetId)); 9011 9012 if((Srb->DataTransferLength >= sizeof(IDEREGS_EX)) && 9013 (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND)) { 9014 use48 = TRUE; 9015 } else 9016 if(Srb->DataTransferLength >= sizeof(IDEREGS)) { 9017 use48 = FALSE; 9018 } else { 9019 KdPrint2((PRINT_PREFIX " buffer too small \n")); 9020 status = SRB_STATUS_DATA_OVERRUN; 9021 break; 9022 } 9023 RtlZeroMemory(regs, use48 ? sizeof(IDEREGS_EX) : sizeof(IDEREGS)); 9024 regs->bOpFlags = use48 ? ATA_FLAGS_48BIT_COMMAND : 0; 9025 UniataSnapAtaRegs(chan, 0, regs); 9026 9027 status = SRB_STATUS_SUCCESS; 9028 } 9029 break; 9030 } 9031 9032 default: 9033 default_abort: 9034 KdPrint2((PRINT_PREFIX 9035 "IdeSendCommand: Unsupported command %#x\n", 9036 Srb->Cdb[0])); 9037 9038 status = SRB_STATUS_INVALID_REQUEST; 9039 9040 } // end switch 9041 9042 if(status == SRB_STATUS_PENDING) { 9043 KdPrint2((PRINT_PREFIX "IdeSendCommand: SRB_STATUS_PENDING\n")); 9044 if(CmdAction & CMD_ACTION_EXEC) { 9045 KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_EXPECTING_INTR\n")); 9046 AtaReq->ReqState = REQ_STATE_EXPECTING_INTR; 9047 } 9048 } else { 9049 KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n")); 9050 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 9051 } 9052 9053 return status; 9054 9055 } // end IdeSendCommand() 9056 9057 9058 /*++ 9059 9060 Routine Description: 9061 Enables disables media status notification 9062 9063 Arguments: 9064 HwDeviceExtension - ATAPI driver storage. 9065 9066 --*/ 9067 VOID 9068 NTAPI 9069 IdeMediaStatus( 9070 BOOLEAN EnableMSN, 9071 IN PVOID HwDeviceExtension, 9072 IN ULONG lChannel, 9073 IN ULONG DeviceNumber 9074 ) 9075 { 9076 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 9077 PHW_CHANNEL chan; 9078 UCHAR statusByte,errorByte; 9079 9080 chan = &(deviceExtension->chan[lChannel]); 9081 SelectDrive(chan, DeviceNumber); 9082 9083 if (EnableMSN == TRUE){ 9084 9085 // If supported enable Media Status Notification support 9086 if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE)) { 9087 9088 // enable 9089 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, 9090 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 9091 0, ATA_C_F_ENAB_MEDIASTAT, ATA_WAIT_BASE_READY); 9092 9093 if (statusByte & IDE_STATUS_ERROR) { 9094 // Read the error register. 9095 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 9096 9097 KdPrint2((PRINT_PREFIX 9098 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n", 9099 statusByte, 9100 errorByte)); 9101 } else { 9102 chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_MEDIA_STATUS_ENABLED; 9103 KdPrint2((PRINT_PREFIX "IdeMediaStatus: Media Status Notification Supported\n")); 9104 chan->ReturningMediaStatus = 0; 9105 9106 } 9107 9108 } 9109 } else { // end if EnableMSN == TRUE 9110 9111 // disable if previously enabled 9112 if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)) { 9113 9114 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, 9115 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 9116 0, ATA_C_F_DIS_MEDIASTAT, ATA_WAIT_BASE_READY); 9117 chan->lun[DeviceNumber]->DeviceFlags &= ~DFLAGS_MEDIA_STATUS_ENABLED; 9118 } 9119 9120 9121 } 9122 9123 9124 } // end IdeMediaStatus() 9125 9126 9127 /*++ 9128 9129 Routine Description: 9130 9131 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS 9132 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE. 9133 Arguments: 9134 9135 HwDeviceExtension - ATAPI driver storage. 9136 Srb - System request block. 9137 9138 Return Value: 9139 9140 SRB status (ALWAYS SUCCESS). 9141 9142 --*/ 9143 ULONG 9144 NTAPI 9145 IdeBuildSenseBuffer( 9146 IN PVOID HwDeviceExtension, 9147 IN PSCSI_REQUEST_BLOCK Srb 9148 ) 9149 { 9150 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 9151 // ULONG status; 9152 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->DataBuffer; 9153 UCHAR ReturningMediaStatus = deviceExtension->chan[GET_CHANNEL(Srb)].ReturningMediaStatus; 9154 9155 if (senseBuffer){ 9156 9157 if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE) { 9158 9159 senseBuffer->ErrorCode = 0x70; 9160 senseBuffer->Valid = 1; 9161 senseBuffer->AdditionalSenseLength = 0xb; 9162 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION; 9163 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED; 9164 senseBuffer->AdditionalSenseCodeQualifier = 0; 9165 } else if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE_REQ) { 9166 9167 senseBuffer->ErrorCode = 0x70; 9168 senseBuffer->Valid = 1; 9169 senseBuffer->AdditionalSenseLength = 0xb; 9170 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION; 9171 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED; 9172 senseBuffer->AdditionalSenseCodeQualifier = 0; 9173 } else if(ReturningMediaStatus & IDE_ERROR_END_OF_MEDIA) { 9174 9175 senseBuffer->ErrorCode = 0x70; 9176 senseBuffer->Valid = 1; 9177 senseBuffer->AdditionalSenseLength = 0xb; 9178 senseBuffer->SenseKey = SCSI_SENSE_NOT_READY; 9179 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE; 9180 senseBuffer->AdditionalSenseCodeQualifier = 0; 9181 } else if(ReturningMediaStatus & IDE_ERROR_DATA_ERROR) { 9182 9183 senseBuffer->ErrorCode = 0x70; 9184 senseBuffer->Valid = 1; 9185 senseBuffer->AdditionalSenseLength = 0xb; 9186 senseBuffer->SenseKey = SCSI_SENSE_DATA_PROTECT; 9187 senseBuffer->AdditionalSenseCode = 0; 9188 senseBuffer->AdditionalSenseCodeQualifier = 0; 9189 } 9190 return SRB_STATUS_SUCCESS; 9191 } 9192 return SRB_STATUS_ERROR; 9193 9194 }// End of IdeBuildSenseBuffer 9195 9196 VOID 9197 NTAPI 9198 UniataUserDeviceReset( 9199 PHW_DEVICE_EXTENSION deviceExtension, 9200 PHW_LU_EXTENSION LunExt, 9201 ULONG lChannel 9202 ) 9203 { 9204 ULONG i; 9205 AtapiDisableInterrupts(deviceExtension, lChannel); 9206 if ((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) && 9207 (LunExt->PowerState != StartStop_Power_Sleep)) { 9208 KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n")); 9209 AtapiSoftReset(&(deviceExtension->chan[lChannel]), LunExt->Lun); 9210 } else { 9211 KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n")); 9212 AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_NONE); 9213 for(i=0; i<deviceExtension->NumberLuns; i++) { 9214 deviceExtension->chan[lChannel].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA; 9215 } 9216 } 9217 LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit 9218 AtapiEnableInterrupts(deviceExtension, lChannel); 9219 return; 9220 } // end UniataUserDeviceReset() 9221 9222 BOOLEAN 9223 NTAPI 9224 UniataNeedQueueing( 9225 PHW_DEVICE_EXTENSION deviceExtension, 9226 PHW_CHANNEL chan, 9227 BOOLEAN TopLevel 9228 ) 9229 { 9230 BOOLEAN PostReq = FALSE; 9231 if(TopLevel) { 9232 KdPrint3((PRINT_PREFIX "UniataNeedQueueing: TopLevel, qd=%x\n", chan->queue_depth)); 9233 if(chan->queue_depth > 0) { 9234 #if 0 9235 if(atapiDev && 9236 ((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY)/* || 9237 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) { 9238 KdPrint2((PRINT_PREFIX "spec: SCSIOP_TEST_UNIT_READY\n")); 9239 //PostReq = FALSE; 9240 status = SRB_STATUS_BUSY; 9241 goto skip_exec; 9242 } else { 9243 PostReq = TRUE; 9244 } 9245 #else 9246 PostReq = TRUE; 9247 #endif 9248 } else 9249 if(deviceExtension->simplexOnly && deviceExtension->queue_depth > 0) { 9250 PostReq = TRUE; 9251 } 9252 } else { 9253 KdPrint3((PRINT_PREFIX "UniataNeedQueueing: qd=%x\n", chan->queue_depth)); 9254 } 9255 return PostReq; 9256 } // end UniataNeedQueueing() 9257 9258 /*++ 9259 9260 Routine Description: 9261 9262 This routine is called from the SCSI port driver synchronized 9263 with the kernel to start an IO request. 9264 ->HwStartIo 9265 9266 Arguments: 9267 9268 HwDeviceExtension - HBA miniport driver's adapter data storage 9269 Srb - IO request packet 9270 9271 Return Value: 9272 9273 TRUE 9274 9275 --*/ 9276 BOOLEAN 9277 NTAPI 9278 AtapiStartIo( 9279 IN PVOID HwDeviceExtension, 9280 IN PSCSI_REQUEST_BLOCK Srb 9281 ) 9282 { 9283 return AtapiStartIo__(HwDeviceExtension, Srb, TRUE); 9284 } // end AtapiStartIo() 9285 9286 BOOLEAN 9287 NTAPI 9288 AtapiStartIo__( 9289 IN PVOID HwDeviceExtension, 9290 IN PSCSI_REQUEST_BLOCK Srb, 9291 IN BOOLEAN TopLevel 9292 ) 9293 { 9294 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 9295 UCHAR lChannel; 9296 PHW_CHANNEL chan; 9297 PHW_LU_EXTENSION LunExt; 9298 ULONG status; 9299 //ULONG ldev; 9300 ULONG DeviceNumber; 9301 UCHAR PathId; 9302 UCHAR TargetId; 9303 UCHAR Lun; 9304 PATA_REQ AtaReq; 9305 PSCSI_REQUEST_BLOCK tmpSrb; 9306 BOOLEAN PostReq = FALSE; 9307 BOOLEAN atapiDev; 9308 BOOLEAN commPort = FALSE; 9309 9310 // deviceExtension->Isr2DevObj must always be NULL for non-PCI 9311 if(deviceExtension->Isr2DevObj && !BMList[deviceExtension->DevIndex].Isr2Enable) { 9312 KdPrint2((PRINT_PREFIX "Isr2Enable -> 1\n")); 9313 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE; 9314 } 9315 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql()); 9316 9317 /* KeBugCheckEx(0xc000000e, 9318 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun), 9319 Srb->Function, 9320 TopLevel, 0x80000001); 9321 */ 9322 if(TopLevel && Srb && Srb->SrbExtension) { 9323 KdPrint2((PRINT_PREFIX "TopLevel\n")); 9324 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ)); 9325 UniAtaClearAtaReq(Srb->SrbExtension); 9326 } 9327 9328 do { // fetch all queued commands for the channel (if valid) 9329 9330 lChannel = GET_CHANNEL(Srb); 9331 //ldev = GET_LDEV(Srb); 9332 chan = NULL; 9333 LunExt = NULL; 9334 DeviceNumber = GET_CDEV(Srb); 9335 commPort = FALSE; 9336 9337 //ASSERT(deviceExtension); 9338 //ASSERT(chan); 9339 9340 KdPrint2((PRINT_PREFIX 9341 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n", 9342 Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId)); 9343 KdPrint2((PRINT_PREFIX " DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID)); 9344 9345 if(lChannel == deviceExtension->NumberChannels && 9346 !Srb->Lun && !Srb->TargetId && 9347 ((Srb->Function == SRB_FUNCTION_IO_CONTROL) || 9348 (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Cdb[0] == SCSIOP_INQUIRY)) 9349 ) { 9350 // This is our virtual device 9351 KdPrint2((PRINT_PREFIX 9352 "AtapiStartIo: Communication port\n")); 9353 if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) { 9354 9355 if(Srb->DataTransferLength < sizeof(PINQUIRYDATA)) { 9356 KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", Srb->DataTransferLength, 9357 sizeof(PINQUIRYDATA) )); 9358 wrong_buffer_size: 9359 status = SRB_STATUS_DATA_OVERRUN; 9360 goto complete_req; 9361 } 9362 9363 PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer); 9364 9365 KdPrint2((PRINT_PREFIX 9366 " INQUIRY\n")); 9367 // Zero INQUIRY data structure. 9368 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength); 9369 9370 inquiryData->DeviceType = COMMUNICATION_DEVICE; 9371 9372 // Fill in vendor identification fields. 9373 RtlCopyMemory(&inquiryData->VendorId, &uniata_comm_name, 28); 9374 9375 status = SRB_STATUS_SUCCESS; 9376 goto complete_req; 9377 } 9378 commPort = TRUE; 9379 /* Pass IOCTL request down */ 9380 } else 9381 if(lChannel >= deviceExtension->NumberChannels || 9382 Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns || 9383 Srb->Lun) { 9384 9385 if(lChannel >= deviceExtension->NumberChannels) { 9386 chan = NULL; 9387 } 9388 9389 reject_srb: 9390 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) { 9391 KdPrint3((PRINT_PREFIX 9392 "AtapiStartIo: SRB rejected\n")); 9393 // Indicate no device found at this address. 9394 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n")); 9395 status = SRB_STATUS_SELECTION_TIMEOUT; 9396 goto complete_req; 9397 //} 9398 } else 9399 if((deviceExtension->HwFlags & UNIATA_AHCI) && 9400 !UniataAhciChanImplemented(deviceExtension, lChannel)) { 9401 chan = NULL; 9402 } 9403 9404 if(!commPort) { 9405 chan = &(deviceExtension->chan[lChannel]); 9406 LunExt = chan->lun[DeviceNumber]; 9407 if(!LunExt) { 9408 goto reject_srb; 9409 } 9410 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE; 9411 } else { 9412 atapiDev = FALSE; 9413 } 9414 9415 #ifdef _DEBUG 9416 if(!commPort && !LunExt) { 9417 #if 0 9418 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n", 9419 deviceExtension, 9420 chan, DeviceNumber, 9421 deviceExtension->NumberChannels); 9422 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n", 9423 lChannel, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]); 9424 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n", 9425 Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId); 9426 #endif //0 9427 /* 9428 int i; 9429 for(i=0; i<1000; i++) { 9430 AtapiStallExecution(3*1000); 9431 } 9432 */ 9433 goto reject_srb; 9434 } 9435 #endif //_DEBUG 9436 9437 // Determine which function. 9438 switch (Srb->Function) { 9439 9440 case SRB_FUNCTION_EXECUTE_SCSI: 9441 9442 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 9443 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) { 9444 // let passthrough go 9445 } else 9446 if(Srb->Cdb[0] == SCSIOP_INQUIRY) { 9447 // let INQUIRY go 9448 } else { 9449 9450 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) { 9451 KdPrint2((PRINT_PREFIX 9452 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n")); 9453 // Indicate no device found at this address. 9454 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n")); 9455 status = SRB_STATUS_SELECTION_TIMEOUT; 9456 break; 9457 //} 9458 } 9459 } else { 9460 KdPrint2((PRINT_PREFIX 9461 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb, &(Srb->Cdb), Srb->SrbExtension, Srb->Cdb[0])); 9462 } 9463 /* 9464 __try { 9465 if(Srb->DataTransferLength) { 9466 UCHAR a; 9467 a = ((PUCHAR)(Srb->DataBuffer))[0]; 9468 g_foo += a; 9469 } 9470 } __except(EXCEPTION_EXECUTE_HANDLER) { 9471 KdPrint3((PRINT_PREFIX 9472 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n")); 9473 // Indicate no device found at this address. 9474 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n")); 9475 status = SRB_STATUS_ERROR; 9476 KdPrint2((PRINT_PREFIX " *** Exception...\n")); 9477 ASSERT(FALSE); 9478 break; 9479 } 9480 */ 9481 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel); 9482 9483 if(PostReq) { 9484 9485 KdPrint3((PRINT_PREFIX "Non-empty queue\n")); 9486 if (atapiDev && 9487 (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) { 9488 KdPrint3((PRINT_PREFIX "Try ATAPI prepare\n")); 9489 9490 status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE); 9491 } else { 9492 KdPrint2((PRINT_PREFIX "Try IDE prepare\n")); 9493 status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE); 9494 } 9495 /*KeBugCheckEx(0xc000000e, 9496 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun), 9497 Srb->Function, 9498 status, 0x80000001);*/ 9499 if(status == SRB_STATUS_BUSY) 9500 status = SRB_STATUS_PENDING; 9501 // Insert requests AFTER they have been initialized on 9502 // CMD_ACTION_PREPARE stage 9503 // we should not check TopLevel here (it is always TRUE) 9504 //ASSERT(chan->lun[GET_CDEV(Srb)]); 9505 UniataQueueRequest(chan, Srb); 9506 9507 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth)); 9508 9509 } else { 9510 9511 // Send command to device. 9512 KdPrint2((PRINT_PREFIX "Send to device %x\n", Srb->Cdb[0])); 9513 if(TopLevel) { 9514 KdPrint2((PRINT_PREFIX "TopLevel (2), srb %#x\n", Srb)); 9515 AtaReq = (PATA_REQ)(Srb->SrbExtension); 9516 KdPrint2((PRINT_PREFIX "TopLevel (3), AtaReq %#x\n", AtaReq)); 9517 //ASSERT(!AtaReq->Flags); 9518 //ASSERT(chan->lun[GET_CDEV(Srb)]); 9519 UniataQueueRequest(chan, Srb); 9520 // AtaReq = (PATA_REQ)(Srb->SrbExtension); 9521 //ASSERT(!AtaReq->Flags); 9522 AtaReq->ReqState = REQ_STATE_QUEUED; 9523 //ASSERT(!AtaReq->Flags); 9524 } 9525 9526 #ifndef NAVO_TEST 9527 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 9528 if(!LunExt) { 9529 goto reject_srb; 9530 } 9531 if(Srb->Cdb[0] == SCSIOP_INQUIRY) { 9532 if(UniataAnybodyHome(deviceExtension, chan->lChannel, DeviceNumber)) { 9533 if(!CheckDevice(HwDeviceExtension, chan->lChannel, DeviceNumber, TRUE)) { 9534 goto reject_srb; 9535 } 9536 } 9537 if(!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 9538 goto reject_srb; 9539 } 9540 } else 9541 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) { 9542 // allow 9543 } else { 9544 goto reject_srb; 9545 } 9546 } 9547 #endif //NAVO_TEST 9548 9549 if(atapiDev && 9550 (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)/* && 9551 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) { 9552 KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0])); 9553 #ifdef __REACTOS__ 9554 status = SRB_STATUS_BUSY; 9555 9556 if (Srb->Cdb[0] == SCSIOP_INQUIRY && 9557 (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) && 9558 (LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM || 9559 LunExt->IdentifyData.DeviceType == ATAPI_TYPE_OPTICAL) && 9560 LunExt->IdentifyData.ModelNumber[0]) 9561 { 9562 ULONG j; 9563 CCHAR vendorId[26]; 9564 9565 // Attempt to identify known broken CD/DVD drives 9566 for (j = 0; j < sizeof(vendorId); j += 2) 9567 { 9568 // Build a buffer based on the identify data. 9569 MOV_DW_SWP(vendorId[j], ((PUCHAR)LunExt->IdentifyData.ModelNumber)[j]); 9570 } 9571 9572 // Emulate INQUIRY support for broken CD/DVD drives (e.g. Microsoft Xbox). 9573 // Currently we implement it by explicitly checking the drive name from ATA IDENTIFY PACKET. 9574 if (!AtapiStringCmp(vendorId, "THOMSON-DVD", 11) || 9575 !AtapiStringCmp(vendorId, "PHILIPS XBOX DVD DRIVE", 22) || 9576 !AtapiStringCmp(vendorId, "PHILIPS J5 3235C", 16) || 9577 !AtapiStringCmp(vendorId, "SAMSUNG DVD-ROM SDG-605B", 24)) 9578 { 9579 // TODO: 9580 // Better send INQUIRY and then check for chan->ReturningMediaStatus >> 4 == SCSI_SENSE_ILLEGAL_REQUEST 9581 // in AtapiInterrupt__() and emulate the response only in this case. 9582 9583 // If this hack stays for long enough, consider adding Xbox 360 drive names to the condition, 9584 // as they are affected by the same problem. 9585 9586 // See https://jira.reactos.org/browse/CORE-16692 9587 ULONG i; 9588 PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer); 9589 PIDENTIFY_DATA2 identifyData = &(LunExt->IdentifyData); 9590 9591 // Zero INQUIRY data structure. 9592 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength); 9593 9594 // This is ATAPI CD- or DVD-ROM. 9595 inquiryData->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE; 9596 9597 // Set the removable bit, if applicable. 9598 if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) { 9599 KdPrint2((PRINT_PREFIX 9600 "RemovableMedia\n")); 9601 inquiryData->RemovableMedia = 1; 9602 } 9603 // Set the Relative Addressing (LBA) bit, if applicable. 9604 if (LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) { 9605 inquiryData->RelativeAddressing = 1; 9606 KdPrint2((PRINT_PREFIX 9607 "RelativeAddressing\n")); 9608 } 9609 // Set the CommandQueue bit 9610 inquiryData->CommandQueue = 1; 9611 9612 // Fill in vendor identification fields. 9613 #ifdef __REACTOS__ 9614 FillDeviceIdentificationString(inquiryData, identifyData); 9615 #else 9616 for (i = 0; i < 24; i += 2) { 9617 MOV_DW_SWP(inquiryData->DeviceIdentificationString[i], ((PUCHAR)identifyData->ModelNumber)[i]); 9618 } 9619 #endif 9620 9621 // Move firmware revision from IDENTIFY data to 9622 // product revision in INQUIRY data. 9623 for (i = 0; i < 4; i += 2) { 9624 MOV_DW_SWP(inquiryData->ProductRevisionLevel[i], ((PUCHAR)identifyData->FirmwareRevision)[i]); 9625 } 9626 9627 status = SRB_STATUS_SUCCESS; 9628 } 9629 } 9630 9631 if (status != SRB_STATUS_SUCCESS) 9632 #endif 9633 status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL); 9634 } else { 9635 KdPrint2((PRINT_PREFIX "Try IDE send\n")); 9636 /* { 9637 ULONG __ebp__ = 0; 9638 ULONG __esp__ = 0; 9639 9640 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n")); 9641 __asm { 9642 mov eax,ebp 9643 mov __ebp__, eax 9644 mov eax,esp 9645 mov __esp__, eax 9646 } 9647 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__)); 9648 }*/ 9649 status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL); 9650 } 9651 /* KeBugCheckEx(0xc000000e, 9652 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun), 9653 Srb->Function, 9654 status, 0x80000002);*/ 9655 9656 } 9657 //skip_exec: 9658 TopLevel = FALSE; 9659 9660 break; 9661 9662 case SRB_FUNCTION_ABORT_COMMAND: 9663 9664 tmpSrb = ScsiPortGetSrb(HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun, 9665 Srb->QueueTag); 9666 // Verify that SRB to abort is still outstanding. 9667 if((tmpSrb != Srb->NextSrb) || 9668 !chan->queue_depth) { 9669 9670 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB to abort already completed\n")); 9671 9672 // Complete abort SRB. 9673 status = SRB_STATUS_ABORT_FAILED; 9674 break; 9675 } 9676 9677 AtaReq = (PATA_REQ)(tmpSrb->SrbExtension); 9678 if(AtaReq->ReqState > REQ_STATE_READY_TO_TRANSFER) { 9679 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_CURRENT)) { 9680 KdPrint2((PRINT_PREFIX "AtapiStartIo: Abort command failed\n")); 9681 // Log reset failure. 9682 KdPrint3((PRINT_PREFIX 9683 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n", 9684 HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8 9685 )); 9686 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8); 9687 status = SRB_STATUS_ERROR; 9688 9689 } else { 9690 status = SRB_STATUS_SUCCESS; 9691 } 9692 } else { 9693 KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove aborted srb %#x\n", tmpSrb)); 9694 if (tmpSrb->SenseInfoBuffer && 9695 tmpSrb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) { 9696 9697 PSENSE_DATA senseBuffer = (PSENSE_DATA)tmpSrb->SenseInfoBuffer; 9698 9699 senseBuffer->ErrorCode = 0; 9700 senseBuffer->Valid = 1; 9701 senseBuffer->AdditionalSenseLength = 0xb; 9702 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND; 9703 senseBuffer->AdditionalSenseCode = 0; 9704 senseBuffer->AdditionalSenseCodeQualifier = 0; 9705 9706 tmpSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; 9707 } 9708 AtapiDmaDBSync(chan, tmpSrb); 9709 UniataRemoveRequest(chan, tmpSrb); 9710 // Indicate command complete. 9711 ScsiPortNotification(RequestComplete, 9712 deviceExtension, 9713 tmpSrb); 9714 status = SRB_STATUS_SUCCESS; 9715 } 9716 break; 9717 9718 // Abort function indicates that a request timed out. 9719 // Call reset routine. Card will only be reset if 9720 // status indicates something is wrong. 9721 // Fall through to reset code. 9722 9723 case SRB_FUNCTION_RESET_DEVICE: 9724 case SRB_FUNCTION_RESET_LOGICAL_UNIT: 9725 9726 // Reset single device. 9727 // For now we support only Lun=0 9728 9729 // Note: reset is immediate command, it cannot be queued since it is usually used to 9730 // revert not-responding device to operational state 9731 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device request received\n")); 9732 UniataUserDeviceReset(deviceExtension, LunExt, lChannel); 9733 status = SRB_STATUS_SUCCESS; 9734 break; 9735 9736 case SRB_FUNCTION_RESET_BUS: 9737 do_bus_reset: 9738 // Reset Atapi and SCSI bus. 9739 9740 // Note: reset is immediate command, it cannot be queued since it is usually used to 9741 // revert not- responding device to operational state 9742 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus request received\n")); 9743 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_ALL)) { 9744 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus failed\n")); 9745 // Log reset failure. 9746 KdPrint3((PRINT_PREFIX 9747 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n", 9748 HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8 9749 )); 9750 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8); 9751 status = SRB_STATUS_ERROR; 9752 9753 } else { 9754 status = SRB_STATUS_SUCCESS; 9755 } 9756 9757 break; 9758 9759 case SRB_FUNCTION_SHUTDOWN: 9760 9761 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown\n")); 9762 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 9763 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - no such device\n")); 9764 } else 9765 if(atapiDev) { 9766 // FLUSH ATAPI device - do nothing 9767 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - ATAPI device\n")); 9768 } else { 9769 // FLUSH IDE/ATA device 9770 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - IDE device\n")); 9771 AtapiDisableInterrupts(deviceExtension, lChannel); 9772 status = AtaCommand(deviceExtension, DeviceNumber, GET_CHANNEL(Srb), 9773 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_IDLE); 9774 // If supported & allowed, reset write cacheing 9775 if(LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) { 9776 9777 // Disable write cache 9778 status = AtaCommand(deviceExtension, DeviceNumber, lChannel, 9779 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 9780 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY); 9781 // Check for errors. 9782 if (status & IDE_STATUS_ERROR) { 9783 KdPrint2((PRINT_PREFIX 9784 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n", 9785 DeviceNumber)); 9786 } 9787 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; 9788 9789 // Re-enable write cache 9790 status = AtaCommand(deviceExtension, DeviceNumber, lChannel, 9791 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 9792 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY); 9793 // Check for errors. 9794 if (status & IDE_STATUS_ERROR) { 9795 KdPrint2((PRINT_PREFIX 9796 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n", 9797 DeviceNumber)); 9798 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; 9799 } else { 9800 LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED; 9801 } 9802 } 9803 9804 AtapiEnableInterrupts(deviceExtension, lChannel); 9805 } 9806 status = SRB_STATUS_SUCCESS; 9807 9808 break; 9809 9810 case SRB_FUNCTION_FLUSH: 9811 9812 KdPrint2((PRINT_PREFIX "AtapiStartIo: Flush (do nothing)\n")); 9813 status = SRB_STATUS_SUCCESS; 9814 break; 9815 9816 case SRB_FUNCTION_IO_CONTROL: { 9817 9818 ULONG len; 9819 9820 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n")); 9821 9822 len = Srb->DataTransferLength; 9823 9824 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) { 9825 9826 ULONG targetId = (ULONG)(-1); 9827 9828 if(len < sizeof(SRB_IO_CONTROL)) { 9829 goto wrong_buffer_size; 9830 } 9831 9832 // extract bogus bus address 9833 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) { 9834 case IOCTL_SCSI_MINIPORT_SMART_VERSION: { 9835 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 9836 9837 if(len < sizeof(SRB_IO_CONTROL)+sizeof(GETVERSIONINPARAMS)) { 9838 goto wrong_buffer_size; 9839 } 9840 9841 targetId = versionParameters->bIDEDeviceMap; 9842 KdPrint2((PRINT_PREFIX "targetId (smart ver) %d\n", targetId)); 9843 break; } 9844 case IOCTL_SCSI_MINIPORT_IDENTIFY: 9845 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS: 9846 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS: 9847 case IOCTL_SCSI_MINIPORT_ENABLE_SMART: 9848 case IOCTL_SCSI_MINIPORT_DISABLE_SMART: 9849 case IOCTL_SCSI_MINIPORT_RETURN_STATUS: 9850 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE: 9851 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES: 9852 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS: 9853 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE: 9854 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG: 9855 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG: 9856 { 9857 PSENDCMDINPARAMS cmdInParameters = (PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 9858 9859 if(len < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS) - 1) { 9860 goto wrong_buffer_size; 9861 } 9862 9863 targetId = cmdInParameters->bDriveNumber; 9864 KdPrint2((PRINT_PREFIX "targetId (smart/ident) %d\n", targetId)); 9865 break; } 9866 default: 9867 invalid_request: 9868 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n", 9869 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode )); 9870 status = SRB_STATUS_INVALID_REQUEST; 9871 goto complete_req; 9872 } // end switch() 9873 9874 // adjust (if necessary) bus address 9875 if(targetId != (ULONG)(-1)) { 9876 9877 // This is done because of how the IOCTL_SCSI_MINIPORT 9878 // determines 'targetid's'. Disk.sys places the real target id value 9879 // in the DeviceMap field. Once we do some parameter checking, the value passed 9880 // back to the application will be determined. 9881 9882 if (deviceExtension->NumberChannels == 1) { 9883 // do this for legacy controllers and legacy callers 9884 KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call\n")); 9885 DeviceNumber = (targetId & 0x01); 9886 lChannel = 0; 9887 } else 9888 if(commPort) { 9889 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d 9890 // due to DISK.SYS design bug, we have invalid SCSI address in SRB 9891 KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call (2)\n")); 9892 if(deviceExtension->HwFlags & UNIATA_AHCI) { 9893 lChannel = (UCHAR)targetId / 2; 9894 DeviceNumber = 0; 9895 } else { 9896 lChannel = (UCHAR)(targetId / 2); 9897 DeviceNumber = targetId & 0x01; 9898 } 9899 } else { 9900 // otherwise assume lChannel and DeviceNumber from Srb are ok 9901 } 9902 if(lChannel >= deviceExtension->NumberChannels || 9903 DeviceNumber >= deviceExtension->NumberLuns) { 9904 KdPrint2((PRINT_PREFIX 9905 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n", 9906 targetId)); 9907 // Indicate no device found at this address. 9908 goto reject_srb; 9909 } 9910 targetId = lChannel*deviceExtension->NumberLuns+DeviceNumber; 9911 chan = &(deviceExtension->chan[lChannel]); 9912 LunExt = chan->lun[DeviceNumber]; 9913 if(!LunExt) { 9914 goto reject_srb; 9915 } 9916 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE; 9917 9918 if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 9919 goto reject_srb; 9920 } 9921 } 9922 9923 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) { 9924 case IOCTL_SCSI_MINIPORT_SMART_VERSION: { 9925 9926 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 9927 UCHAR deviceNumberMap; 9928 9929 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n")); 9930 9931 // Version and revision per SMART 1.03 9932 9933 versionParameters->bVersion = 1; 9934 versionParameters->bRevision = 1; 9935 versionParameters->bReserved = 0; 9936 9937 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands. 9938 versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD); 9939 9940 if (atapiDev) { 9941 goto invalid_request; 9942 } 9943 9944 // NOTE: This will only set the bit 9945 // corresponding to this drive's target id. 9946 // The bit mask is as follows: 9947 // 9948 // -Sec Pri 9949 // S M S M 9950 // 3 2 1 0 9951 9952 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { 9953 deviceNumberMap = 1 << lChannel; 9954 DeviceNumber = 0; 9955 } else 9956 if (deviceExtension->NumberChannels == 1) { 9957 if (chan->PrimaryAddress) { 9958 deviceNumberMap = 1 << DeviceNumber; 9959 } else { 9960 deviceNumberMap = 4 << DeviceNumber; 9961 } 9962 } else { 9963 deviceNumberMap = 1 << (DeviceNumber+lChannel*2); 9964 } 9965 9966 versionParameters->bIDEDeviceMap = deviceNumberMap; 9967 9968 status = SRB_STATUS_SUCCESS; 9969 break; 9970 } 9971 9972 case IOCTL_SCSI_MINIPORT_IDENTIFY: { 9973 9974 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 9975 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 9976 9977 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n")); 9978 // Extract the target. 9979 KdPrint2((PRINT_PREFIX "targetId %d\n", targetId)); 9980 9981 switch(cmdInParameters.irDriveRegs.bCommandReg) { 9982 case ID_CMD: 9983 if(atapiDev) { 9984 KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n")); 9985 goto invalid_request; 9986 } 9987 /* FALL THROUGH */ 9988 case ATAPI_ID_CMD: 9989 9990 if(!atapiDev && 9991 (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) { 9992 KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n")); 9993 goto invalid_request; 9994 } 9995 9996 len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE); 9997 // Zero the output buffer 9998 RtlZeroMemory(cmdOutParameters, len); 9999 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) { 10000 ((PUCHAR)cmdOutParameters)[i] = 0; 10001 }*/ 10002 10003 // Build status block. 10004 cmdOutParameters->cBufferSize = min(IDENTIFY_BUFFER_SIZE, len - sizeof(SENDCMDOUTPARAMS) + 1); 10005 cmdOutParameters->DriverStatus.bDriverError = 0; 10006 cmdOutParameters->DriverStatus.bIDEError = 0; 10007 10008 // Extract the identify data from the device extension. 10009 ScsiPortMoveMemory (cmdOutParameters->bBuffer, &(LunExt->IdentifyData), 10010 cmdOutParameters->cBufferSize); 10011 10012 if((cmdOutParameters->cBufferSize == IDENTIFY_BUFFER_SIZE) && 10013 (LunExt->IdentifyData.ChecksumValid == ATA_ChecksumValid)) { 10014 // adjust checksum if it is possible 10015 CHAR csum = 0; 10016 ULONG i; 10017 10018 for(i=0; i < IDENTIFY_BUFFER_SIZE-1; i++) { 10019 csum += (CHAR)(cmdOutParameters->bBuffer[i]); 10020 } 10021 cmdOutParameters->bBuffer[i] = -csum; 10022 KdPrint2((PRINT_PREFIX "AtapiStartIo: adjust checksum %d\n")); 10023 } 10024 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n")); 10025 10026 status = SRB_STATUS_SUCCESS; 10027 10028 break; 10029 default: 10030 KdPrint2((PRINT_PREFIX "AtapiStartIo: not supported ID code %x\n", 10031 cmdInParameters.irDriveRegs.bCommandReg)); 10032 status = SRB_STATUS_INVALID_REQUEST; 10033 break; 10034 } 10035 break; 10036 } 10037 /* 10038 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS: 10039 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS: 10040 case IOCTL_SCSI_MINIPORT_ENABLE_SMART: 10041 case IOCTL_SCSI_MINIPORT_DISABLE_SMART: 10042 case IOCTL_SCSI_MINIPORT_RETURN_STATUS: 10043 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE: 10044 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES: 10045 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS: 10046 */ 10047 default: 10048 // *all* IOCTLs here are SMART 10049 if(commPort) { 10050 KdPrint2((PRINT_PREFIX 10051 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n")); 10052 } 10053 if (atapiDev) { 10054 goto invalid_request; 10055 } 10056 10057 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel); 10058 10059 if(PostReq || TopLevel) { 10060 UniataQueueRequest(chan, Srb); 10061 AtaReq = (PATA_REQ)(Srb->SrbExtension); 10062 AtaReq->ReqState = REQ_STATE_QUEUED; 10063 } 10064 10065 if(PostReq) { 10066 10067 KdPrint2((PRINT_PREFIX "Non-empty queue (SMART)\n")); 10068 status = SRB_STATUS_PENDING; 10069 10070 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth)); 10071 } else { 10072 10073 status = IdeSendSmartCommand(HwDeviceExtension, Srb, targetId); 10074 } 10075 break; 10076 10077 // we should not get here, checked above 10078 /* default : 10079 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n", 10080 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode )); 10081 status = SRB_STATUS_INVALID_REQUEST; 10082 break; 10083 */ 10084 } 10085 } else 10086 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) { 10087 10088 PUNIATA_CTL AtaCtl = (PUNIATA_CTL)(Srb->DataBuffer); 10089 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0); 10090 ULONG DeviceNumber = AtaCtl->addr.TargetId; 10091 BOOLEAN bad_ldev; 10092 ULONG i, pos; 10093 10094 pos = FIELD_OFFSET(UNIATA_CTL, RawData); 10095 //chan = &(deviceExtension->chan[lChannel]); 10096 if(len < pos) { 10097 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10098 FIELD_OFFSET(UNIATA_CTL, RawData) )); 10099 goto wrong_buffer_size; 10100 } 10101 10102 if(AtaCtl->addr.Lun || 10103 AtaCtl->addr.TargetId >= deviceExtension->NumberLuns || 10104 AtaCtl->addr.PathId >= deviceExtension->NumberChannels) { 10105 10106 chan = NULL; 10107 bad_ldev = TRUE; 10108 LunExt = NULL; 10109 10110 } else { 10111 bad_ldev = FALSE; 10112 lChannel = AtaCtl->addr.PathId; 10113 chan = &(deviceExtension->chan[lChannel]); 10114 LunExt = chan->lun[DeviceNumber]; 10115 } 10116 10117 KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl->hdr.ControlCode, DeviceNumber)); 10118 10119 /* check for valid LUN */ 10120 switch (AtaCtl->hdr.ControlCode) { 10121 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES: 10122 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: 10123 // this would be BUS reset 10124 if(bad_ldev && 10125 (AtaCtl->addr.PathId >= deviceExtension->NumberChannels || 10126 AtaCtl->addr.TargetId != 0xff || 10127 AtaCtl->addr.Lun != 0 10128 )) { 10129 if(AtaCtl->hdr.ControlCode == IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES && 10130 DeviceNumber < deviceExtension->NumberLuns) { // AtaCtl->addr.TargetId != 0xff 10131 lChannel = AtaCtl->addr.PathId; 10132 chan = &(deviceExtension->chan[lChannel]); 10133 LunExt = chan->lun[DeviceNumber]; 10134 // OK 10135 } else { 10136 goto handle_bad_ldev; 10137 } 10138 } else { 10139 lChannel = AtaCtl->addr.PathId; 10140 chan = &(deviceExtension->chan[lChannel]); 10141 } 10142 break; 10143 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: 10144 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: 10145 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE: 10146 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: 10147 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO: 10148 if(bad_ldev) { 10149 handle_bad_ldev: 10150 KdPrint2((PRINT_PREFIX 10151 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n")); 10152 // Indicate no device found at this address. 10153 goto reject_srb; 10154 } 10155 } 10156 10157 /* check if queueing is necessary */ 10158 switch (AtaCtl->hdr.ControlCode) { 10159 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: 10160 if(!LunExt->nBadBlocks) { 10161 break; 10162 } 10163 goto uata_ctl_queue; 10164 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: 10165 if(len < pos+sizeof(AtaCtl->SetMode)) { 10166 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10167 pos+sizeof(AtaCtl->SetMode) )); 10168 goto wrong_buffer_size; 10169 } 10170 if(!AtaCtl->SetMode.ApplyImmediately) { 10171 break; 10172 } 10173 goto uata_ctl_queue; 10174 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES: 10175 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately 10176 uata_ctl_queue: 10177 KdPrint2((PRINT_PREFIX "put to queue (UNIATA)\n")); 10178 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel); 10179 10180 if(PostReq || TopLevel) { 10181 UniataQueueRequest(chan, Srb); 10182 AtaReq = (PATA_REQ)(Srb->SrbExtension); 10183 AtaReq->ReqState = REQ_STATE_QUEUED; 10184 } 10185 if(PostReq) { 10186 KdPrint2((PRINT_PREFIX "Non-empty queue (UNIATA)\n")); 10187 status = SRB_STATUS_PENDING; 10188 10189 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth)); 10190 goto complete_req; 10191 } 10192 } // end switch (AtaCtl->hdr.ControlCode) 10193 10194 /* process request */ 10195 switch (AtaCtl->hdr.ControlCode) { 10196 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES: 10197 10198 KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n")); 10199 10200 if(len < pos+sizeof(AtaCtl->FindDelDev)) { 10201 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10202 pos+sizeof(AtaCtl->FindDelDev) )); 10203 goto wrong_buffer_size; 10204 } 10205 if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) { 10206 KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n")); 10207 if(AtaCtl->addr.TargetId != 0xff) { 10208 LunExt->DeviceFlags &= ~DFLAGS_HIDDEN; 10209 } else { 10210 } 10211 } 10212 10213 for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) { 10214 AtapiStallExecution(1000 * 1000); 10215 } 10216 10217 FindDevices(HwDeviceExtension, 10218 ((AtaCtl->addr.TargetId == 0xff) && (AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE)) 10219 ? UNIATA_FIND_DEV_UNHIDE : 0, 10220 AtaCtl->addr.PathId); 10221 status = SRB_STATUS_SUCCESS; 10222 10223 break; 10224 10225 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: { 10226 10227 KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId)); 10228 10229 if(len < pos+sizeof(AtaCtl->FindDelDev)) { 10230 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10231 pos+sizeof(AtaCtl->FindDelDev) )); 10232 goto wrong_buffer_size; 10233 } 10234 LunExt->DeviceFlags = 0; 10235 if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) { 10236 KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n")); 10237 //LunExt->DeviceFlags |= DFLAGS_HIDDEN; 10238 UniataForgetDevice(LunExt); 10239 } 10240 10241 for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) { 10242 AtapiStallExecution(1000 * 1000); 10243 } 10244 10245 status = SRB_STATUS_SUCCESS; 10246 break; 10247 } 10248 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: { 10249 10250 KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n")); 10251 10252 if(len < pos+sizeof(AtaCtl->SetMode)) { 10253 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10254 pos+sizeof(AtaCtl->SetMode) )); 10255 goto wrong_buffer_size; 10256 } 10257 if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) { 10258 LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode); 10259 } 10260 if(AtaCtl->SetMode.MaxMode != IOMODE_NOT_SPECIFIED) { 10261 LunExt->LimitedTransferMode = (UCHAR)(AtaCtl->SetMode.MaxMode); 10262 if(LunExt->LimitedTransferMode > 10263 LunExt->OrigTransferMode) { 10264 // check for incorrect value 10265 LunExt->LimitedTransferMode = 10266 LunExt->OrigTransferMode; 10267 } 10268 } 10269 LunExt->TransferMode = min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode); 10270 10271 LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit 10272 if(AtaCtl->SetMode.ApplyImmediately) { 10273 AtapiDmaInit__(deviceExtension, LunExt); 10274 } 10275 /* LunExt->TransferMode = 10276 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/ 10277 status = SRB_STATUS_SUCCESS; 10278 break; 10279 } 10280 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE: { 10281 10282 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get transfer mode\n")); 10283 10284 if(len < pos+sizeof(AtaCtl->GetMode)) { 10285 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10286 pos+sizeof(AtaCtl->GetMode) )); 10287 goto wrong_buffer_size; 10288 } 10289 AtaCtl->GetMode.OrigMode = LunExt->OrigTransferMode; 10290 AtaCtl->GetMode.MaxMode = LunExt->LimitedTransferMode; 10291 AtaCtl->GetMode.CurrentMode = LunExt->TransferMode; 10292 AtaCtl->GetMode.PhyMode = LunExt->PhyTransferMode; 10293 10294 status = SRB_STATUS_SUCCESS; 10295 break; 10296 } 10297 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION: { 10298 10299 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n")); 10300 10301 if(len < pos+sizeof(AtaCtl->Version)) { 10302 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10303 pos+sizeof(AtaCtl->Version) )); 10304 goto wrong_buffer_size; 10305 } 10306 AtaCtl->Version.Length = sizeof(GETDRVVERSION); 10307 AtaCtl->Version.VersionMj = UNIATA_VER_MJ; 10308 AtaCtl->Version.VersionMn = UNIATA_VER_MN; 10309 AtaCtl->Version.SubVerMj = UNIATA_VER_SUB_MJ; 10310 AtaCtl->Version.SubVerMn = UNIATA_VER_SUB_MN; 10311 10312 status = SRB_STATUS_SUCCESS; 10313 break; 10314 } 10315 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO: { 10316 10317 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n")); 10318 10319 if(len < pos+sizeof(AtaCtl->AdapterInfo)) { 10320 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10321 pos+sizeof(AtaCtl->AdapterInfo) )); 10322 goto wrong_buffer_size; 10323 } 10324 AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO); 10325 10326 AtaCtl->AdapterInfo.DevID = deviceExtension->DevID; 10327 AtaCtl->AdapterInfo.RevID = deviceExtension->RevID; 10328 AtaCtl->AdapterInfo.slotNumber = deviceExtension->slotNumber; 10329 AtaCtl->AdapterInfo.SystemIoBusNumber = deviceExtension->SystemIoBusNumber; 10330 AtaCtl->AdapterInfo.DevIndex = deviceExtension->DevIndex; 10331 AtaCtl->AdapterInfo.Channel = deviceExtension->Channel; 10332 AtaCtl->AdapterInfo.HbaCtrlFlags = deviceExtension->HbaCtrlFlags; 10333 AtaCtl->AdapterInfo.simplexOnly= deviceExtension->simplexOnly; 10334 AtaCtl->AdapterInfo.MemIo = FALSE;/*deviceExtension->MemIo;*/ 10335 AtaCtl->AdapterInfo.UnknownDev = deviceExtension->UnknownDev; 10336 AtaCtl->AdapterInfo.MasterDev = deviceExtension->MasterDev; 10337 AtaCtl->AdapterInfo.MaxTransferMode = deviceExtension->MaxTransferMode; 10338 AtaCtl->AdapterInfo.HwFlags = deviceExtension->HwFlags; 10339 AtaCtl->AdapterInfo.OrigAdapterInterfaceType = deviceExtension->OrigAdapterInterfaceType; 10340 AtaCtl->AdapterInfo.BusInterruptLevel = deviceExtension->BusInterruptLevel; 10341 AtaCtl->AdapterInfo.InterruptMode = deviceExtension->InterruptMode; 10342 AtaCtl->AdapterInfo.BusInterruptVector = deviceExtension->BusInterruptVector; 10343 AtaCtl->AdapterInfo.NumberChannels = deviceExtension->NumberChannels; 10344 AtaCtl->AdapterInfo.NumberLuns = (UCHAR)deviceExtension->NumberLuns; 10345 AtaCtl->AdapterInfo.AdapterInterfaceType = deviceExtension->AdapterInterfaceType; 10346 if(deviceExtension->FullDevName) { 10347 strncpy(AtaCtl->AdapterInfo.DeviceName, deviceExtension->FullDevName, 64); 10348 } 10349 AtaCtl->AdapterInfo.ChanInfoValid = FALSE; 10350 AtaCtl->AdapterInfo.LunInfoValid = FALSE; 10351 AtaCtl->AdapterInfo.ChanHeaderLengthValid = TRUE; 10352 10353 pos += AtaCtl->AdapterInfo.HeaderLength; 10354 10355 // zero tail 10356 RtlZeroMemory(((PCHAR)AtaCtl)+pos, 10357 len-pos); 10358 10359 if(len >= pos+AtaCtl->AdapterInfo.NumberChannels*sizeof(CHANINFO)) { 10360 PCHANINFO ChanInfo = (PCHANINFO)( ((PCHAR)AtaCtl)+pos ); 10361 PHW_CHANNEL cur_chan; 10362 KdPrint2((PRINT_PREFIX "AtapiStartIo: Fill channel info\n")); 10363 for(i=0;i<AtaCtl->AdapterInfo.NumberChannels;i++) { 10364 KdPrint2((PRINT_PREFIX "chan[%d] %x\n", i, cur_chan)); 10365 cur_chan = &(deviceExtension->chan[i]); 10366 ChanInfo->MaxTransferMode = cur_chan->MaxTransferMode; 10367 ChanInfo->ChannelCtrlFlags = cur_chan->ChannelCtrlFlags; 10368 RtlCopyMemory(&(ChanInfo->QueueStat), &(cur_chan->QueueStat), sizeof(ChanInfo->QueueStat)); 10369 ChanInfo->ReorderCount = cur_chan->ReorderCount; 10370 ChanInfo->IntersectCount = cur_chan->IntersectCount; 10371 ChanInfo->TryReorderCount = cur_chan->TryReorderCount; 10372 ChanInfo->TryReorderHeadCount = cur_chan->TryReorderHeadCount; 10373 ChanInfo->TryReorderTailCount = cur_chan->TryReorderTailCount; 10374 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode; 10375 ChanInfo++; 10376 } 10377 AtaCtl->AdapterInfo.ChanInfoValid = TRUE; 10378 AtaCtl->AdapterInfo.ChanHeaderLength = sizeof(*ChanInfo); 10379 } 10380 10381 status = SRB_STATUS_SUCCESS; 10382 break; 10383 } 10384 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: { 10385 10386 KdPrint2((PRINT_PREFIX "AtapiStartIo: Forget BB list\n")); 10387 10388 ForgetBadBlocks(LunExt); 10389 10390 status = SRB_STATUS_SUCCESS; 10391 break; 10392 } 10393 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: { 10394 10395 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device\n")); 10396 10397 if(bad_ldev) { 10398 goto do_bus_reset; 10399 } else { 10400 UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId); 10401 } 10402 10403 status = SRB_STATUS_SUCCESS; 10404 break; 10405 } 10406 default : 10407 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n", 10408 AtaCtl->hdr.ControlCode )); 10409 status = SRB_STATUS_INVALID_REQUEST; 10410 break; 10411 } 10412 10413 } else { 10414 KdPrint2((PRINT_PREFIX "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n", 10415 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature, 10416 "SCSIDISK", "-UNIATA-")); 10417 10418 status = SRB_STATUS_INVALID_REQUEST; 10419 break; 10420 } 10421 10422 break; 10423 } // end SRB_FUNCTION_IO_CONTROL 10424 default: 10425 10426 KdPrint2((PRINT_PREFIX "AtapiStartIo: Unknown IOCTL\n")); 10427 // Indicate unsupported command. 10428 status = SRB_STATUS_INVALID_REQUEST; 10429 10430 // break; 10431 10432 } // end switch 10433 10434 complete_req: 10435 10436 PathId = Srb->PathId; 10437 TargetId = Srb->TargetId; 10438 Lun = Srb->Lun; 10439 10440 if (status != SRB_STATUS_PENDING) { 10441 10442 KdPrint2((PRINT_PREFIX 10443 "AtapiStartIo: Srb %#x complete with status %#x\n", 10444 Srb, 10445 status)); 10446 10447 // Set status in SRB. 10448 Srb->SrbStatus = (UCHAR)status; 10449 10450 if(chan && Srb) { 10451 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb)); 10452 AtapiDmaDBSync(chan, Srb); 10453 } 10454 KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan, Srb)); 10455 UniataRemoveRequest(chan, Srb); 10456 // Indicate command complete. 10457 KdPrint2((PRINT_PREFIX "AtapiStartIo: ScsiPortNotification\n")); 10458 ScsiPortNotification(RequestComplete, 10459 deviceExtension, 10460 Srb); 10461 10462 KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataGetCurRequest\n")); 10463 // Remove current Srb & get next one 10464 if((Srb = UniataGetCurRequest(chan))) { 10465 AtaReq = (PATA_REQ)(Srb->SrbExtension); 10466 if(AtaReq->ReqState > REQ_STATE_QUEUED) { 10467 // current request is under precessing, thus 10468 // we should do nothing here 10469 Srb = NULL; 10470 } 10471 } 10472 KdPrint2((PRINT_PREFIX "AtapiStartIo: chan %x, Src %x\n", chan, Srb)); 10473 if(!chan) { 10474 //ASSERT(TopLevel); 10475 } 10476 } 10477 KdPrint2((PRINT_PREFIX "AtapiStartIo: next Srb %x\n", Srb)); 10478 10479 } while (Srb && (status != SRB_STATUS_PENDING)); 10480 10481 KdPrint2((PRINT_PREFIX "AtapiStartIo: query PORT for next request\n")); 10482 // Indicate ready for next request. 10483 ScsiPortNotification(NextRequest, 10484 deviceExtension, 10485 NULL); 10486 10487 ScsiPortNotification(NextLuRequest, 10488 deviceExtension, 10489 PathId, 10490 TargetId, 10491 Lun); 10492 10493 return TRUE; 10494 10495 } // end AtapiStartIo__() 10496 10497 #if 0 10498 void 10499 NTAPI 10500 UniataInitAtaCommands() 10501 { 10502 int i; 10503 UCHAR command; 10504 UCHAR flags; 10505 10506 KdPrint2((PRINT_PREFIX "UniataInitAtaCommands:\n")); 10507 10508 for(i=0; i<256; i++) { 10509 10510 flags = 0; 10511 command = i; 10512 10513 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command)); 10514 10515 switch(command) { 10516 case IDE_COMMAND_READ_DMA48: 10517 case IDE_COMMAND_READ_DMA_Q48: 10518 case IDE_COMMAND_READ_STREAM_DMA48: 10519 case IDE_COMMAND_READ_STREAM48: 10520 case IDE_COMMAND_WRITE_DMA48: 10521 case IDE_COMMAND_WRITE_DMA_Q48: 10522 case IDE_COMMAND_READ_DMA_Q: 10523 case IDE_COMMAND_READ_DMA: 10524 case IDE_COMMAND_WRITE_DMA: 10525 case IDE_COMMAND_WRITE_DMA_Q: 10526 case IDE_COMMAND_WRITE_STREAM_DMA48: 10527 case IDE_COMMAND_WRITE_STREAM48: 10528 case IDE_COMMAND_WRITE_FUA_DMA48: 10529 case IDE_COMMAND_WRITE_FUA_DMA_Q48: 10530 case IDE_COMMAND_READ_LOG_DMA48: 10531 case IDE_COMMAND_WRITE_LOG_DMA48: 10532 case IDE_COMMAND_TRUSTED_RCV_DMA: 10533 case IDE_COMMAND_TRUSTED_SEND_DMA: 10534 case IDE_COMMAND_DATA_SET_MGMT: // TRIM 10535 //KdPrint2((PRINT_PREFIX "DMA ")); 10536 flags |= ATA_CMD_FLAG_DMA; 10537 } 10538 10539 switch(command) { 10540 case IDE_COMMAND_WRITE_FUA_DMA48: 10541 case IDE_COMMAND_WRITE_FUA_DMA_Q48: 10542 case IDE_COMMAND_WRITE_MUL_FUA48: 10543 10544 flags |= ATA_CMD_FLAG_FUA; 10545 /* FALL THROUGH */ 10546 10547 case IDE_COMMAND_READ48: 10548 case IDE_COMMAND_READ_DMA48: 10549 case IDE_COMMAND_READ_DMA_Q48: 10550 case IDE_COMMAND_READ_MUL48: 10551 case IDE_COMMAND_READ_STREAM_DMA48: 10552 case IDE_COMMAND_READ_STREAM48: 10553 case IDE_COMMAND_WRITE48: 10554 case IDE_COMMAND_WRITE_DMA48: 10555 case IDE_COMMAND_WRITE_DMA_Q48: 10556 case IDE_COMMAND_WRITE_MUL48: 10557 case IDE_COMMAND_WRITE_STREAM_DMA48: 10558 case IDE_COMMAND_WRITE_STREAM48: 10559 case IDE_COMMAND_FLUSH_CACHE48: 10560 case IDE_COMMAND_VERIFY48: 10561 10562 //KdPrint2((PRINT_PREFIX "48 ")); 10563 flags |= ATA_CMD_FLAG_48; 10564 /* FALL THROUGH */ 10565 10566 case IDE_COMMAND_READ: 10567 case IDE_COMMAND_READ_MULTIPLE: 10568 case IDE_COMMAND_READ_DMA: 10569 case IDE_COMMAND_READ_DMA_Q: 10570 case IDE_COMMAND_WRITE: 10571 case IDE_COMMAND_WRITE_MULTIPLE: 10572 case IDE_COMMAND_WRITE_DMA: 10573 case IDE_COMMAND_WRITE_DMA_Q: 10574 case IDE_COMMAND_FLUSH_CACHE: 10575 case IDE_COMMAND_VERIFY: 10576 10577 //KdPrint2((PRINT_PREFIX "LBA ")); 10578 flags |= ATA_CMD_FLAG_LBAIOsupp; 10579 } 10580 10581 switch(command) { 10582 case IDE_COMMAND_READ_NATIVE_SIZE48: 10583 case IDE_COMMAND_SET_NATIVE_SIZE48: 10584 // we cannot set LBA flag for these commands to avoid BadBlock handling 10585 //flags |= ATA_CMD_FLAG_LBAIOsupp; 10586 flags |= ATA_CMD_FLAG_48; 10587 10588 case IDE_COMMAND_READ_NATIVE_SIZE: 10589 case IDE_COMMAND_SET_NATIVE_SIZE: 10590 10591 flags |= ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_FUA; 10592 } 10593 10594 flags |= ATA_CMD_FLAG_48supp; 10595 10596 switch (command) { 10597 case IDE_COMMAND_READ: 10598 command = IDE_COMMAND_READ48; break; 10599 case IDE_COMMAND_READ_MULTIPLE: 10600 command = IDE_COMMAND_READ_MUL48; break; 10601 case IDE_COMMAND_READ_DMA: 10602 command = IDE_COMMAND_READ_DMA48; break; 10603 case IDE_COMMAND_READ_DMA_Q: 10604 command = IDE_COMMAND_READ_DMA_Q48; break; 10605 case IDE_COMMAND_WRITE: 10606 command = IDE_COMMAND_WRITE48; break; 10607 case IDE_COMMAND_WRITE_MULTIPLE: 10608 command = IDE_COMMAND_WRITE_MUL48; break; 10609 case IDE_COMMAND_WRITE_DMA: 10610 command = IDE_COMMAND_WRITE_DMA48; break; 10611 case IDE_COMMAND_WRITE_DMA_Q: 10612 command = IDE_COMMAND_WRITE_DMA_Q48; break; 10613 case IDE_COMMAND_FLUSH_CACHE: 10614 command = IDE_COMMAND_FLUSH_CACHE48; break; 10615 // case IDE_COMMAND_READ_NATIVE_SIZE: 10616 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break; 10617 case IDE_COMMAND_SET_NATIVE_SIZE: 10618 command = IDE_COMMAND_SET_NATIVE_SIZE48; break; 10619 case IDE_COMMAND_VERIFY: 10620 command = IDE_COMMAND_VERIFY48; break; 10621 default: 10622 //KdPrint2((PRINT_PREFIX "!28->48 ")); 10623 flags &= ~ATA_CMD_FLAG_48supp; 10624 } 10625 10626 switch (command) { 10627 case IDE_COMMAND_READ: 10628 case IDE_COMMAND_READ_MULTIPLE: 10629 case IDE_COMMAND_READ_DMA48: 10630 case IDE_COMMAND_READ_DMA_Q48: 10631 case IDE_COMMAND_READ_STREAM_DMA48: 10632 case IDE_COMMAND_READ_STREAM48: 10633 case IDE_COMMAND_READ_DMA_Q: 10634 case IDE_COMMAND_READ_DMA: 10635 case IDE_COMMAND_READ_LOG_DMA48: 10636 case IDE_COMMAND_TRUSTED_RCV_DMA: 10637 case IDE_COMMAND_IDENTIFY: 10638 case IDE_COMMAND_ATAPI_IDENTIFY: 10639 //KdPrint2((PRINT_PREFIX "RD ")); 10640 flags |= ATA_CMD_FLAG_In; 10641 break; 10642 case IDE_COMMAND_WRITE: 10643 case IDE_COMMAND_WRITE_MULTIPLE: 10644 case IDE_COMMAND_WRITE_DMA48: 10645 case IDE_COMMAND_WRITE_DMA_Q48: 10646 case IDE_COMMAND_WRITE_DMA: 10647 case IDE_COMMAND_WRITE_DMA_Q: 10648 case IDE_COMMAND_WRITE_STREAM_DMA48: 10649 case IDE_COMMAND_WRITE_STREAM48: 10650 case IDE_COMMAND_WRITE_FUA_DMA48: 10651 case IDE_COMMAND_WRITE_FUA_DMA_Q48: 10652 //KdPrint2((PRINT_PREFIX "WR ")); 10653 flags |= ATA_CMD_FLAG_Out; 10654 break; 10655 } 10656 10657 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags)); 10658 AtaCommands48[i] = command; 10659 AtaCommandFlags[i] = flags; 10660 } 10661 } // end UniataInitAtaCommands() 10662 #endif 10663 10664 /*++ 10665 10666 Routine Description: 10667 10668 Installable driver initialization entry point for system. 10669 10670 Arguments: 10671 10672 Driver Object 10673 10674 Return Value: 10675 10676 Status from ScsiPortInitialize() 10677 10678 --*/ 10679 extern "C" 10680 ULONG 10681 NTAPI 10682 DriverEntry( 10683 IN PVOID DriverObject, 10684 IN PVOID Argument2 10685 ) 10686 { 10687 HW_INITIALIZATION_DATA_COMMON hwInitializationData; 10688 ULONG adapterCount; 10689 ULONG i, c, alt, pref_alt; 10690 ULONG statusToReturn, newStatus; 10691 PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2; 10692 BOOLEAN ReEnter = FALSE; 10693 // WCHAR a; 10694 #ifndef USE_REACTOS_DDK 10695 NTSTATUS status; 10696 #endif 10697 10698 PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation(); 10699 BOOLEAN PrimaryClaimed = FALSE; 10700 BOOLEAN SecondaryClaimed = FALSE; 10701 BOOLEAN IgnoreIsaCompatiblePci = FALSE; 10702 BOOLEAN IgnoreNativePci = FALSE; 10703 10704 LARGE_INTEGER t0, t1; 10705 10706 KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string)); 10707 //a = (WCHAR)strlen(ver_string); 10708 10709 statusToReturn = 0xffffffff; 10710 10711 // Zero out structure. 10712 RtlZeroMemory(((PCHAR)&hwInitializationData), sizeof(hwInitializationData)); 10713 10714 // Set size of hwInitializationData. 10715 hwInitializationData.comm.HwInitializationDataSize = 10716 sizeof(hwInitializationData.comm) + 10717 // sizeof(hwInitializationData.nt4) + 10718 ((WinVer_Id() <= WinVer_NT) ? 0 : sizeof(hwInitializationData.w2k)); 10719 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData.comm.HwInitializationDataSize)); 10720 10721 // Set entry points. 10722 hwInitializationData.comm.HwInitialize = (PHW_INITIALIZE)AtapiHwInitialize; 10723 hwInitializationData.comm.HwResetBus = (PHW_RESET_BUS)AtapiResetController; 10724 hwInitializationData.comm.HwStartIo = (PHW_STARTIO)AtapiStartIo; 10725 hwInitializationData.comm.HwInterrupt = (PHW_INTERRUPT)AtapiInterrupt; 10726 10727 // Specify size of extensions. 10728 hwInitializationData.comm.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); 10729 hwInitializationData.comm.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION); 10730 hwInitializationData.comm.SrbExtensionSize = sizeof(ATA_REQ); 10731 10732 // Indicate PIO device. 10733 hwInitializationData.comm.MapBuffers = TRUE; 10734 10735 // Request and parse arument string. 10736 KdPrint2((PRINT_PREFIX "\n\nUniATA: parse ArgumentString\n")); 10737 // Zero out structure. 10738 hwInitializationData.comm.NumberOfAccessRanges = 2; 10739 hwInitializationData.comm.HwFindAdapter = AtapiReadArgumentString; 10740 ScsiPortInitialize(DriverObject, 10741 Argument2, 10742 &hwInitializationData.comm, 10743 &adapterCount); 10744 10745 if(!g_Dump) { 10746 Connect_DbgPrint(); 10747 g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0); 10748 if(g_opt_Verbose) { 10749 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR "\n"); 10750 } 10751 IgnoreIsaCompatiblePci = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", IgnoreIsaCompatiblePci) ? TRUE : FALSE; 10752 IgnoreNativePci = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", IgnoreNativePci) ? TRUE : FALSE; 10753 } else { 10754 KdPrint(("crashdump mode\n")); 10755 } 10756 10757 if(!SavedDriverObject) { 10758 SavedDriverObject = (PDRIVER_OBJECT)DriverObject; 10759 #ifdef USE_REACTOS_DDK 10760 KdPrint(("UniATA Init: OS should be ReactOS\n")); 10761 MajorVersion=0x04; 10762 MinorVersion=0x01; 10763 BuildNumber=1; 10764 CPU_num = KeNumberProcessors; 10765 #else 10766 // we are here for the 1st time 10767 // init CrossNT and get OS version 10768 if(!NT_SUCCESS(status = CrNtInit(SavedDriverObject, RegistryPath))) { 10769 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status)); 10770 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n"); 10771 return status; 10772 } 10773 CPU_num = *KeNumberProcessors; 10774 #endif // USE_REACTOS_DDK 10775 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, CPU_num)); 10776 10777 KeQuerySystemTime(&t0); 10778 do { 10779 KeQuerySystemTime(&t1); 10780 } while(t0.QuadPart == t1.QuadPart); 10781 t0=t1; 10782 g_Perf=0; 10783 do { 10784 KeQuerySystemTime(&t1); 10785 g_Perf++; 10786 } while(t0.QuadPart == t1.QuadPart); 10787 g_PerfDt = (ULONG)((t1.QuadPart - t0.QuadPart)/10); 10788 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt, g_Perf )); 10789 } else { 10790 KdPrint(("UniATA Init: ReEnter\n")); 10791 ReEnter = TRUE; 10792 } 10793 10794 // (re)read bad block list 10795 InitBadBlocks(NULL); 10796 10797 if(!ReEnter) { 10798 // init ATA command translation table 10799 //UniataInitAtaCommands(); 10800 10801 // get registry path to settings 10802 RtlCopyMemory(&SavedRegPath, RegistryPath, sizeof(UNICODE_STRING)); 10803 SavedRegPath.Buffer = (PWCHAR)&SavedRegPathBuffer; 10804 SavedRegPath.Length = min(RegistryPath->Length, 255*sizeof(WCHAR)); 10805 SavedRegPath.MaximumLength = 255*sizeof(WCHAR); 10806 RtlCopyMemory(SavedRegPath.Buffer, RegistryPath->Buffer, SavedRegPath.Length); 10807 SavedRegPath.Buffer[SavedRegPath.Length/sizeof(WCHAR)] = 0; 10808 } 10809 10810 if(WinVer_Id() >= WinVer_2k) { 10811 #ifndef __REACTOS__ 10812 if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"1", 0)) { 10813 #else 10814 if(AtapiRegCheckParameterValue(NULL, L"Parameters\\PnpInterface", L"1", 0)) { 10815 #endif 10816 KdPrint(("UniATA: Behave as WDM, mlia (1)\n")); 10817 WinVer_WDM_Model = TRUE; 10818 } 10819 #ifndef __REACTOS__ 10820 if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"5", 0)) { 10821 #else 10822 if(AtapiRegCheckParameterValue(NULL, L"Parameters\\PnpInterface", L"5", 0)) { 10823 #endif 10824 KdPrint(("UniATA: Behave as WDM, mlia (5)\n")); 10825 WinVer_WDM_Model = TRUE; 10826 } 10827 } 10828 10829 SkipRaids = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"SkipRaids", 1); 10830 ForceSimplex = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"ForceSimplex", 0); 10831 #ifdef _DEBUG 10832 g_LogToDisplay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"LogToDisplay", 0); 10833 #endif //_DEBUG 10834 10835 // Set PnP-specific API 10836 if(WinVer_Id() > WinVer_NT) { 10837 KdPrint(("set NeedPhysicalAddresses = TRUE\n")); 10838 hwInitializationData.comm.NeedPhysicalAddresses = TRUE; 10839 KdPrint(("set AtapiAdapterControl() ptr\n")); 10840 hwInitializationData.w2k.HwAdapterControl = (PHW_ADAPTER_CONTROL)AtapiAdapterControl; 10841 } 10842 10843 KdPrint2((PRINT_PREFIX "\n\nUniATA init... (%d)\n", ReEnter)); 10844 if(!ReEnter) { 10845 10846 g_opt_VirtualMachine = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualMachineType", g_opt_VirtualMachine); 10847 if(g_opt_VirtualMachine > VM_MAX_KNOWN) { 10848 g_opt_VirtualMachine = 0; 10849 } 10850 if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualBox", (g_opt_VirtualMachine == VM_VBOX))) { 10851 g_opt_VirtualMachine = VM_VBOX; 10852 } 10853 // Pre-scan PCI bus, also check if we are under VM 10854 // But do not perform scan if PCI bus is claimed as unused 10855 if(!IgnoreIsaCompatiblePci || !IgnoreNativePci) { 10856 KdPrint2((PRINT_PREFIX "\nATAPI IDE enum supported PCI BusMaster Devices\n")); 10857 UniataEnumBusMasterController(DriverObject, Argument2); 10858 } 10859 10860 switch(g_opt_VirtualMachine) { 10861 case VM_VBOX: 10862 KdPrint2((PRINT_PREFIX "adjust options for VirtualBox\n")); 10863 // adjust options for VirtualBox 10864 g_opt_WaitBusyCount = 20000; 10865 g_opt_WaitBusyDelay = 150; 10866 g_opt_WaitDrqDelay = 100; 10867 g_opt_WaitBusyLongCount = 20000; 10868 g_opt_MaxIsrWait = 200; 10869 g_opt_AtapiSendDisableIntr = FALSE; 10870 g_opt_AtapiDmaRawRead = FALSE; 10871 break; 10872 case VM_BOCHS: 10873 KdPrint2((PRINT_PREFIX "adjust options for Bochs\n")); 10874 g_opt_AtapiNoDma = TRUE; 10875 } 10876 10877 if(!hasPCI) { 10878 KdPrint2((PRINT_PREFIX "old slow machine, adjust timings\n")); 10879 // old slow machine, adjust timings (us) 10880 g_opt_WaitBusyResetCount = 20000; 10881 g_opt_WaitBusyCount = 20000; 10882 g_opt_WaitBusyDelay = 150; 10883 g_opt_WaitDrqDelay = 100; 10884 g_opt_WaitBusyLongCount = 20000; 10885 g_opt_MaxIsrWait = 200; 10886 g_opt_DriveSelectNanoDelay = 400; 10887 } 10888 if(g_opt_VirtualMachine > VM_NONE) { 10889 g_opt_DriveSelectNanoDelay = 0; 10890 } 10891 if(CPU_num > 1) { 10892 g_opt_AtapiSendDisableIntr = TRUE; 10893 } 10894 10895 g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000 10896 g_opt_WaitBusyDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyDelay", g_opt_WaitBusyDelay); // 10 vs 150 10897 g_opt_WaitDrqDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay", g_opt_WaitDrqDelay); // 10 vs 100 10898 g_opt_WaitBusyLongCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongCount", g_opt_WaitBusyLongCount); // 2000 vs 20000 10899 g_opt_WaitBusyLongDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongDelay", g_opt_WaitBusyLongDelay); // 250 vs 250 10900 g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr) ? TRUE : FALSE; // 1 vs 0 10901 g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead) ? TRUE : FALSE; // 1 vs 0 10902 g_opt_AtapiNoDma = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiNoDma", g_opt_AtapiNoDma) ? TRUE : FALSE; // 1 vs 0 10903 g_opt_MaxIsrWait = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"MaxIsrWait", g_opt_MaxIsrWait); // 40 vs xxx 10904 g_opt_DriveSelectNanoDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"DriveSelectNanoDelay", g_opt_DriveSelectNanoDelay); 10905 } // end !re-enter 10906 10907 // Look for legacy ISA-bridged PCI IDE controller (onboard) 10908 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n")); 10909 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: BMListLen %d\n", BMListLen)); 10910 for (i=0; i <BMListLen; i++) { 10911 10912 if(!BMList[i].MasterDev) { 10913 KdPrint2((PRINT_PREFIX "!BMList[i].MasterDev\n")); 10914 break; 10915 } 10916 if(IgnoreIsaCompatiblePci) { 10917 break; 10918 } 10919 if(ReEnter) { 10920 KdPrint2((PRINT_PREFIX "ReEnter, skip it\n")); 10921 if(BMList[i].ChanInitOk & 0x03) { 10922 KdPrint2((PRINT_PREFIX "Already initialized, skip it\n")); 10923 statusToReturn = 10924 newStatus = STATUS_SUCCESS; 10925 } 10926 continue; 10927 } 10928 //BMList[i].AltInitMasterDev = (UCHAR)0xff; 10929 10930 if(GlobalConfig->AtDiskPrimaryAddressClaimed) 10931 PrimaryClaimed = TRUE; 10932 if(GlobalConfig->AtDiskSecondaryAddressClaimed) 10933 SecondaryClaimed = TRUE; 10934 pref_alt = 0; 10935 10936 if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed && !g_Dump && 10937 !(BMList[i].ChanInitOk & 0x80)) { 10938 10939 // We just want to claim our PCI device in compatible mode, since we shall not 10940 // tell system that we use it inside HwInitialize 10941 // Even more, we shall cheat system, that work with ISA 10942 // Note: this call may (but not 'must' or 'can') cause IO resource 10943 // reallocation and switch to native mode if HAL supports this 10944 newStatus = (ULONG)UniataClaimLegacyPCIIDE(i); 10945 // Special check for NT3.51/NT4 (not ReactOS !!!) 10946 if(((NTSTATUS)newStatus == STATUS_CONFLICTING_ADDRESSES) && 10947 //(BMList[i].ChanInitOk & 0x40) && 10948 /*CPU_num > 1 &&*/ 10949 (WinVer_Id() <= WinVer_NT)) { 10950 // Some NT3/4 SMP (but not only) HALs cannot reallocate IO resources of 10951 // BusMaster PCI controller 10952 // Since nobody claimed Primary/Secondary yet, try init and claim them 10953 // However it is not 100% safe way, especially under ReactOS, which doesn't resolve 10954 // conflicts yet. 10955 // We relay on ScsiPort internal checks 10956 KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster on SMP NT3/4 system, try init anyway.\n")); 10957 newStatus = STATUS_SUCCESS; 10958 // Prefer alternative init method (try to change Isa -> PCI in ConfigInfo first) 10959 pref_alt = 1; 10960 } 10961 if(newStatus != STATUS_SUCCESS) { 10962 KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster, try as pure ISA later.\n")); 10963 break; 10964 } 10965 } 10966 10967 if(g_opt_Verbose) { 10968 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:"); 10969 } 10970 10971 for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) { 10972 10973 for(c=0; c<2; c++) { 10974 // check is channel is manually excluded 10975 if(AtapiRegCheckDevValue(NULL, c, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) { 10976 break; 10977 } 10978 if(c==0) { 10979 if(PrimaryClaimed) { 10980 KdPrint2((PRINT_PREFIX "Primary already claimed\n")); 10981 continue; 10982 } 10983 } else 10984 if(c==1) { 10985 if(SecondaryClaimed) { 10986 KdPrint2((PRINT_PREFIX "Secondary already claimed\n")); 10987 continue; 10988 } 10989 } 10990 10991 if((WinVer_Id() < WinVer_2k)) { 10992 // do not even try if already claimed 10993 if(c==0) { 10994 GlobalConfig->AtDiskPrimaryAddressClaimed = FALSE; 10995 } else 10996 if(c==1) { 10997 GlobalConfig->AtDiskSecondaryAddressClaimed = FALSE; 10998 } 10999 } 11000 if(!WinVer_WDM_Model) { 11001 hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController; 11002 } else { 11003 // in WDM model things are different.... 11004 hwInitializationData.comm.HwFindAdapter = (c == 0) ? 11005 UniataFindCompatBusMasterController1 : UniataFindCompatBusMasterController2; 11006 } 11007 hwInitializationData.comm.NumberOfAccessRanges = 6; 11008 hwInitializationData.comm.AdapterInterfaceType = Isa; 11009 11010 if(!WinVer_WDM_Model) { 11011 BMList[i].channel = (UCHAR)c; 11012 } 11013 11014 KdPrint2((PRINT_PREFIX "Try init channel %d, method %d\n", c, alt)); 11015 newStatus = ScsiPortInitialize(DriverObject, 11016 Argument2, 11017 &hwInitializationData.comm, 11018 UlongToPtr(i | ((alt ^ pref_alt) ? 0x80000000 : 0))); 11019 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus)); 11020 if (newStatus < statusToReturn) { 11021 statusToReturn = newStatus; 11022 } 11023 if (newStatus == STATUS_SUCCESS) { 11024 if(WinVer_Id() < WinVer_2k) { 11025 // This should be done in HwInitialize under w2k+ to ensure that 11026 // channel is actually initialized 11027 BMList[i].ChanInitOk |= 0x01 << c; 11028 } else { 11029 if(BMList[i].ChanInitOk & (0x01 << c)) { 11030 KdPrint2((PRINT_PREFIX "HwInit passed\n")); 11031 } 11032 } 11033 /* 11034 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) { 11035 c = 1; // this will break our for() 11036 BMList[i].ChanInitOk |= 0x01 << c; 11037 } 11038 */ 11039 } 11040 } 11041 /* if(WinVer_Id() >= WinVer_2k) { 11042 // the following didn't work under higher OSes, 11043 // until we move setting of FLAGS to HwInit 11044 KdPrint2((PRINT_PREFIX "make still one attempt\n")); 11045 continue; 11046 }*/ 11047 if(BMList[i].ChanInitOk & 0x03) { 11048 // Under NT we receive status immediately, so 11049 // we can omit alternative init method if STATUS_SUCCESS returned. 11050 // Under w2k+ we relay on flags, set in HwInitialize. 11051 KdPrint2((PRINT_PREFIX "Ok, no more retries required\n")); 11052 break; 11053 } else 11054 if(WinVer_Id() >= WinVer_2k) { 11055 // try AltInit if HwInit was not called immediately under w2k+ 11056 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n")); 11057 } else { 11058 // if (WinVer_Id() == WinVer_NT) and some error occured 11059 // try alternative init method 11060 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n")); 11061 } 11062 } // for(alt...) 11063 if(g_opt_Verbose) { 11064 if(BMList[i].ChanInitOk & 0x03) { 11065 _PrintNtConsole(" OK\n"); 11066 } else { 11067 _PrintNtConsole(" failed\n"); 11068 } 11069 } 11070 11071 } 11072 11073 /* KeBugCheckEx(0xc000000e, 11074 (i << 16) | BMList[0].ChanInitOk, 11075 c, 11076 newStatus, statusToReturn);*/ 11077 11078 // Look for PCI IDE controller 11079 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for PCI IDE controller\n")); 11080 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: i %d, BMListLen %d\n", i, BMListLen)); 11081 for (; i <BMListLen; i++) { 11082 11083 if(IgnoreNativePci) { 11084 break; 11085 } 11086 /* if(BMList[i].MasterDev) 11087 continue;*/ 11088 if(g_opt_Verbose) { 11089 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d", 11090 BMList[i].VendorId, BMList[i].DeviceId, 11091 BMList[i].busNumber, 11092 BMList[i].slotNumber % PCI_MAX_FUNCTION, 11093 (BMList[i].slotNumber / PCI_MAX_FUNCTION) % PCI_MAX_DEVICES); 11094 } 11095 11096 hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController; 11097 hwInitializationData.comm.NumberOfAccessRanges = 6; 11098 hwInitializationData.comm.AdapterInterfaceType = PCIBus; 11099 11100 hwInitializationData.comm.VendorId = (PVOID)BMList[i].VendorId; 11101 hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength; 11102 hwInitializationData.comm.DeviceId = (PVOID)BMList[i].DeviceId; 11103 hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength; 11104 11105 BMList[i].channel = 0/*(UCHAR)c*/; 11106 11107 KdPrint2((PRINT_PREFIX "Try init %4.4s %4.4s \n", 11108 hwInitializationData.comm.VendorId, 11109 hwInitializationData.comm.DeviceId)); 11110 newStatus = ScsiPortInitialize(DriverObject, 11111 Argument2, 11112 &hwInitializationData.comm, 11113 UlongToPtr(i)); 11114 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus)); 11115 if(newStatus == (ULONG)STATUS_DEVICE_DOES_NOT_EXIST && BMList[i].NeedAltInit) { 11116 // Note: this is actually a BUG in scsiport.sys 11117 // It stops scanning PCI bus when reaches empty PCI Function inside Slot 11118 // However, this PCI Slot may have higher non-empty Functions 11119 // UniATA will perform all staff instead of ScsiPort under NT, 11120 // but for ReactOS it is better to patch ScsiPort. 11121 KdPrint2((PRINT_PREFIX "STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n")); 11122 hwInitializationData.comm.AdapterInterfaceType = Isa; 11123 newStatus = ScsiPortInitialize(DriverObject, 11124 Argument2, 11125 &hwInitializationData.comm, 11126 UlongToPtr(i | 0x80000000)); 11127 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x (2)\n", newStatus)); 11128 } 11129 if (newStatus < statusToReturn) 11130 statusToReturn = newStatus; 11131 11132 if(g_opt_Verbose) { 11133 if(newStatus == STATUS_SUCCESS) { 11134 _PrintNtConsole(" OK\n"); 11135 } else { 11136 _PrintNtConsole(" failed\n"); 11137 } 11138 } 11139 11140 } 11141 11142 /* KeBugCheckEx(0xc000000e, 11143 i, 11144 c, 11145 newStatus, statusToReturn);*/ 11146 11147 // -------------- 11148 11149 hwInitializationData.comm.VendorId = 0; 11150 hwInitializationData.comm.VendorIdLength = 0; 11151 hwInitializationData.comm.DeviceId = 0; 11152 hwInitializationData.comm.DeviceIdLength = 0; 11153 11154 if(!BMListLen) { 11155 hwInitializationData.comm.SrbExtensionSize = //FIELD_OFFSET(ATA_REQ, ata); 11156 sizeof(ATA_REQ); 11157 KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", hwInitializationData.comm.SrbExtensionSize)); 11158 } 11159 11160 // The adapter count is used by the find adapter routine to track how 11161 // which adapter addresses have been tested. 11162 11163 // Indicate 2 access ranges and reset FindAdapter. 11164 hwInitializationData.comm.NumberOfAccessRanges = 2; 11165 hwInitializationData.comm.HwFindAdapter = AtapiFindIsaController; 11166 11167 if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsa", 0)) { 11168 // Indicate ISA bustype. 11169 hwInitializationData.comm.AdapterInterfaceType = Isa; 11170 adapterCount = 0; 11171 11172 // Call initialization for ISA bustype. 11173 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for ISA Controllers\n")); 11174 newStatus = ScsiPortInitialize(DriverObject, 11175 Argument2, 11176 &hwInitializationData.comm, 11177 &adapterCount); 11178 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus)); 11179 if (newStatus < statusToReturn) 11180 statusToReturn = newStatus; 11181 } 11182 if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreMca", 0)) { 11183 // Set up for MCA 11184 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for MCA Controllers\n")); 11185 hwInitializationData.comm.AdapterInterfaceType = MicroChannel; 11186 adapterCount = 0; 11187 11188 newStatus = ScsiPortInitialize(DriverObject, 11189 Argument2, 11190 &hwInitializationData.comm, 11191 &adapterCount); 11192 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus)); 11193 if (newStatus < statusToReturn) 11194 statusToReturn = newStatus; 11195 } 11196 InDriverEntry = FALSE; 11197 11198 KdPrint2((PRINT_PREFIX "\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn)); 11199 11200 return statusToReturn; 11201 11202 } // end DriverEntry() 11203 11204 11205 PSCSI_REQUEST_BLOCK 11206 NTAPI 11207 BuildMechanismStatusSrb( 11208 IN PVOID HwDeviceExtension, 11209 IN PSCSI_REQUEST_BLOCK Srb 11210 ) 11211 { 11212 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 11213 PSCSI_REQUEST_BLOCK srb; 11214 PCDB cdb; 11215 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 11216 11217 srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb); 11218 11219 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK)); 11220 11221 srb->PathId = (UCHAR)(Srb->PathId); 11222 srb->TargetId = (UCHAR)(Srb->TargetId); 11223 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 11224 srb->Length = sizeof(SCSI_REQUEST_BLOCK); 11225 11226 // Set flags to disable synchronous negociation. 11227 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 11228 11229 // Set timeout to 4 seconds. 11230 srb->TimeOutValue = 4; 11231 11232 srb->CdbLength = 6; 11233 srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusData); 11234 srb->DataTransferLength = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER); 11235 srb->SrbExtension = AtaReq; 11236 11237 // Set CDB operation code. 11238 cdb = (PCDB)srb->Cdb; 11239 cdb->MECH_STATUS.OperationCode = SCSIOP_MECHANISM_STATUS; 11240 cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER); 11241 11242 KdPrint2((PRINT_PREFIX " MechanismStatusSrb %#x\n", srb)); 11243 11244 return srb; 11245 } // end BuildMechanismStatusSrb() 11246 11247 #endif //UNIATA_CORE 11248 11249 PSCSI_REQUEST_BLOCK 11250 NTAPI 11251 BuildRequestSenseSrb ( 11252 IN PVOID HwDeviceExtension, 11253 IN PSCSI_REQUEST_BLOCK Srb 11254 ) 11255 { 11256 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 11257 PSCSI_REQUEST_BLOCK srb; 11258 PCDB cdb; 11259 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 11260 11261 srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb); 11262 11263 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK)); 11264 11265 srb->PathId = (UCHAR)(Srb->PathId); 11266 srb->TargetId = (UCHAR)(Srb->TargetId); 11267 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 11268 srb->Length = sizeof(SCSI_REQUEST_BLOCK); 11269 11270 // Set flags to disable synchronous negociation. 11271 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 11272 11273 // Set timeout to 2 seconds. 11274 srb->TimeOutValue = 4; 11275 11276 srb->CdbLength = 6; 11277 srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusSense); 11278 srb->DataTransferLength = sizeof(SENSE_DATA); 11279 srb->SrbExtension = AtaReq; 11280 11281 // Set CDB operation code. 11282 cdb = (PCDB)srb->Cdb; 11283 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE; 11284 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA); 11285 11286 KdPrint2((PRINT_PREFIX " RequestSenseSrb %#x\n", srb)); 11287 11288 return srb; 11289 } // end BuildRequestSenseSrb() 11290 11291 #ifndef UNIATA_CORE 11292 11293 ULONG 11294 NTAPI 11295 AtapiRegCheckDevLunValue( 11296 IN PVOID HwDeviceExtension, 11297 IN PCWCH NamePrefix, 11298 IN ULONG chan, 11299 IN ULONG dev, 11300 IN PCWSTR Name, 11301 IN ULONG Default 11302 ) 11303 { 11304 WCHAR namex[160]; 11305 ULONG val = Default; 11306 11307 val = AtapiRegCheckParameterValue( 11308 HwDeviceExtension, NamePrefix, Name, val); 11309 11310 if(chan != CHAN_NOT_SPECIFIED) { 11311 swprintf(namex, L"%s\\Chan_%1.1d", NamePrefix, chan); 11312 val = AtapiRegCheckParameterValue( 11313 HwDeviceExtension, namex, Name, val); 11314 if(dev != DEVNUM_NOT_SPECIFIED) { 11315 swprintf(namex, L"%s\\Chan_%1.1d\\%s", NamePrefix, chan, (dev & 0x01) ? L"Lun_1" : L"Lun_0"); 11316 val = AtapiRegCheckParameterValue( 11317 HwDeviceExtension, namex, Name, val); 11318 } 11319 } 11320 return val; 11321 } // end AtapiRegCheckDevLunValue() 11322 11323 ULONG 11324 NTAPI 11325 EncodeVendorStr( 11326 OUT PWCHAR Buffer, 11327 IN PUCHAR Str, 11328 IN ULONG Length 11329 ) 11330 { 11331 ULONG i,j; 11332 WCHAR a; 11333 11334 for(i=0, j=0; i<Length; i++, j++) { 11335 // fix byte-order 11336 a = Str[i ^ 0x01]; 11337 if(!a) { 11338 Buffer[j] = 0; 11339 return j; 11340 } else 11341 if(a == ' ') { 11342 Buffer[j] = '_'; 11343 } else 11344 if((a == '_') || 11345 (a == '#') || 11346 (a == '\\') || 11347 (a == '\"') || 11348 (a == '\'') || 11349 (a < ' ') || 11350 (a >= 127)) { 11351 Buffer[j] = '#'; 11352 j++; 11353 swprintf(Buffer+j, L"%2.2x", a); 11354 j++; 11355 } else { 11356 Buffer[j] = a; 11357 } 11358 } 11359 Buffer[j] = 0; 11360 return j; 11361 } // end EncodeVendorStr() 11362 11363 ULONG 11364 NTAPI 11365 AtapiRegCheckDevValue( 11366 IN PVOID HwDeviceExtension, 11367 IN ULONG chan, 11368 IN ULONG dev, 11369 IN PCWSTR Name, 11370 IN ULONG Default 11371 ) 11372 { 11373 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 11374 // WCHAR name0[11]; 11375 // WCHAR name1[11+4+5]; 11376 // WCHAR name2[11+4+4+10]; 11377 // WCHAR name3[11+4+4+5+20]; 11378 // WCHAR name3[11+4+4+5+20+1]; 11379 WCHAR namex[160]; 11380 11381 WCHAR namev[16]; 11382 WCHAR named[16]; 11383 WCHAR names[20]; 11384 11385 IN ULONG VendorID; 11386 IN ULONG DeviceID; 11387 IN ULONG SlotNumber; 11388 IN ULONG HwFlags; 11389 11390 ULONG val = Default; 11391 11392 KdPrint(( " Parameter %ws\n", Name)); 11393 11394 if(deviceExtension) { 11395 VendorID = deviceExtension->DevID & 0xffff; 11396 DeviceID = (deviceExtension->DevID >> 16) & 0xffff; 11397 SlotNumber = deviceExtension->slotNumber; 11398 HwFlags = deviceExtension->HwFlags; 11399 } else { 11400 VendorID = 0xffff; 11401 DeviceID = 0xffff; 11402 SlotNumber = 0xffffffff; 11403 HwFlags = 0; 11404 } 11405 11406 val = AtapiRegCheckDevLunValue( 11407 HwDeviceExtension, L"Parameters", chan, dev, Name, val); 11408 11409 if(deviceExtension) { 11410 11411 if(HwFlags & UNIATA_SATA) { 11412 swprintf(namev, L"\\SATA"); 11413 swprintf(namex, L"Parameters%s", namev); 11414 val = AtapiRegCheckDevLunValue( 11415 HwDeviceExtension, namex, chan, dev, Name, val); 11416 } 11417 if(HwFlags & UNIATA_AHCI) { 11418 swprintf(namev, L"\\AHCI"); 11419 swprintf(namex, L"Parameters%s", namev); 11420 val = AtapiRegCheckDevLunValue( 11421 HwDeviceExtension, namex, chan, dev, Name, val); 11422 } 11423 if(!(HwFlags & (UNIATA_SATA | UNIATA_AHCI))) { 11424 swprintf(namev, L"\\PATA"); 11425 swprintf(namex, L"Parameters%s", namev); 11426 val = AtapiRegCheckDevLunValue( 11427 HwDeviceExtension, namex, chan, dev, Name, val); 11428 } 11429 11430 if(deviceExtension->AdapterInterfaceType == PCIBus) { 11431 // PCI 11432 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex); 11433 swprintf(namex, L"Parameters%s", namev); 11434 val = AtapiRegCheckDevLunValue( 11435 HwDeviceExtension, namex, chan, dev, Name, val); 11436 11437 11438 swprintf(namev, L"\\Ven_%4.4x", VendorID); 11439 swprintf(named, L"\\Dev_%4.4x", DeviceID); 11440 swprintf(names, L"\\Slot_%8.8x", SlotNumber); 11441 11442 swprintf(namex, L"Parameters%s", namev); 11443 val = AtapiRegCheckDevLunValue( 11444 HwDeviceExtension, namex, chan, dev, Name, val); 11445 11446 swprintf(namex, L"Parameters%s%s", namev, named); 11447 val = AtapiRegCheckDevLunValue( 11448 HwDeviceExtension, namex, chan, dev, Name, val); 11449 11450 swprintf(namex, L"Parameters%s%s%s", namev, named, names); 11451 val = AtapiRegCheckDevLunValue( 11452 HwDeviceExtension, namex, chan, dev, Name, val); 11453 } else 11454 if(deviceExtension->AdapterInterfaceType == Isa) { 11455 // Isa 11456 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen); 11457 swprintf(namex, L"Parameters%s", namev); 11458 val = AtapiRegCheckDevLunValue( 11459 HwDeviceExtension, namex, chan, dev, Name, val); 11460 11461 swprintf(namev, L"\\ISA_%d", deviceExtension->DevIndex); 11462 swprintf(namex, L"Parameters%s", namev); 11463 val = AtapiRegCheckDevLunValue( 11464 HwDeviceExtension, namex, chan, dev, Name, val); 11465 11466 } else 11467 if(deviceExtension->AdapterInterfaceType == MicroChannel) { 11468 // MicroChannel 11469 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen+IsaCount); 11470 swprintf(namex, L"Parameters%s", namev); 11471 val = AtapiRegCheckDevLunValue( 11472 HwDeviceExtension, namex, chan, dev, Name, val); 11473 11474 swprintf(namev, L"\\MCA_%d", deviceExtension->DevIndex); 11475 swprintf(namex, L"Parameters%s", namev); 11476 val = AtapiRegCheckDevLunValue( 11477 HwDeviceExtension, namex, chan, dev, Name, val); 11478 11479 } 11480 } 11481 11482 KdPrint(( " Parameter %ws = %#x\n", Name, val)); 11483 return val; 11484 11485 } // end AtapiRegCheckDevValue() 11486 11487 /* 11488 The user must specify that Xxx is to run on the platform 11489 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\ 11490 Services\UniATA\Xxx:REG_DWORD:Zzz. 11491 11492 The user can override the global setting to enable or disable Xxx on a 11493 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\ 11494 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero. 11495 11496 If this registry value does not exist or contains the value zero then 11497 the timer to check for media change does not run. 11498 11499 Arguments: 11500 11501 RegistryPath - pointer to the unicode string inside 11502 ...\CurrentControlSet\Services\UniATA 11503 DeviceNumber - The number of the HBA device object 11504 11505 Returns: Registry Key value 11506 */ 11507 ULONG 11508 NTAPI 11509 AtapiRegCheckParameterValue( 11510 IN PVOID HwDeviceExtension, 11511 IN PCWSTR PathSuffix, 11512 IN PCWSTR Name, 11513 IN ULONG Default 11514 ) 11515 { 11516 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched 11517 11518 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 11519 NTSTATUS status; 11520 LONG zero = Default; 11521 11522 RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY]; 11523 11524 // LONG tmp = 0; 11525 LONG doRun = Default; 11526 11527 PUNICODE_STRING RegistryPath = &SavedRegPath; 11528 11529 UNICODE_STRING paramPath; 11530 11531 if(g_Dump) { 11532 goto failed; 11533 } 11534 11535 // <SavedRegPath>\<PathSuffix> -> <Name> 11536 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name)); 11537 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer)); 11538 11539 paramPath.Length = 0; 11540 paramPath.MaximumLength = RegistryPath->Length + 11541 (wcslen(PathSuffix)+2)*sizeof(WCHAR); 11542 paramPath.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, paramPath.MaximumLength); 11543 if(!paramPath.Buffer) { 11544 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n")); 11545 return Default; 11546 } 11547 11548 RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength); 11549 RtlAppendUnicodeToString(¶mPath, RegistryPath->Buffer); 11550 RtlAppendUnicodeToString(¶mPath, L"\\"); 11551 RtlAppendUnicodeToString(¶mPath, REGRTL_STR_PTYPE PathSuffix); 11552 11553 // Check for the Xxx value. 11554 RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY)); 11555 11556 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 11557 parameters[0].Name = REGRTL_STR_PTYPE Name; 11558 parameters[0].EntryContext = &doRun; 11559 parameters[0].DefaultType = REG_DWORD; 11560 parameters[0].DefaultData = &zero; 11561 parameters[0].DefaultLength = sizeof(ULONG); 11562 11563 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/, 11564 paramPath.Buffer, parameters, NULL, NULL); 11565 if(NT_SUCCESS(status)) { 11566 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun)); 11567 } 11568 11569 ExFreePool(paramPath.Buffer); 11570 11571 if(!NT_SUCCESS(status)) { 11572 failed: 11573 doRun = Default; 11574 } 11575 11576 return doRun; 11577 11578 #undef ITEMS_TO_QUERY 11579 11580 } // end AtapiRegCheckParameterValue() 11581 11582 11583 SCSI_ADAPTER_CONTROL_STATUS 11584 NTAPI 11585 AtapiAdapterControl( 11586 IN PVOID HwDeviceExtension, 11587 IN SCSI_ADAPTER_CONTROL_TYPE ControlType, 11588 IN PVOID Parameters 11589 ) 11590 { 11591 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 11592 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList; 11593 ULONG numberChannels = deviceExtension->NumberChannels; 11594 ULONG c; 11595 NTSTATUS status; 11596 11597 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType)); 11598 11599 switch(ControlType) { 11600 case ScsiQuerySupportedControlTypes: { 11601 BOOLEAN supportedTypes[ScsiAdapterControlMax] = { 11602 TRUE, // ScsiQuerySupportedControlTypes 11603 TRUE, // ScsiStopAdapter 11604 TRUE, // ScsiRestartAdapter 11605 FALSE, // ScsiSetBootConfig 11606 FALSE // ScsiSetRunningConfig 11607 }; 11608 11609 ULONG lim = ScsiAdapterControlMax; 11610 ULONG i; 11611 11612 pControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST) Parameters; 11613 11614 if(pControlTypeList->MaxControlType < lim) { 11615 lim = pControlTypeList->MaxControlType; 11616 } 11617 11618 for(i = 0; i < lim; i++) { 11619 pControlTypeList->SupportedTypeList[i] = supportedTypes[i]; 11620 } 11621 11622 break; 11623 11624 } 11625 case ScsiStopAdapter: { 11626 11627 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n")); 11628 // Shut down all interrupts on the adapter. They'll get re-enabled 11629 // by the initialization routines. 11630 for (c = 0; c < numberChannels; c++) { 11631 AtapiResetController(deviceExtension, c); 11632 AtapiDisableInterrupts(deviceExtension, c); 11633 } 11634 if(deviceExtension->AdapterInterfaceType == PCIBus) { 11635 // we must never get here for non-PCI 11636 /*status =*/ UniataDisconnectIntr2(HwDeviceExtension); 11637 BMList[deviceExtension->DevIndex].Isr2Enable = FALSE; 11638 } 11639 break; 11640 } 11641 case ScsiRestartAdapter: { 11642 11643 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n")); 11644 // Enable all the interrupts on the adapter while port driver call 11645 // for power up an HBA that was shut down for power management 11646 11647 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED); 11648 status = UniataConnectIntr2(HwDeviceExtension); 11649 if(NT_SUCCESS(status)) { 11650 for (c = 0; c < numberChannels; c++) { 11651 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c); 11652 FindDevices(HwDeviceExtension, 0, c); 11653 AtapiEnableInterrupts(deviceExtension, c); 11654 AtapiHwInitialize__(deviceExtension, c); 11655 } 11656 if(deviceExtension->Isr2DevObj) { 11657 // we must never get here for non-PCI 11658 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE; 11659 } 11660 } 11661 11662 break; 11663 } 11664 11665 default: { 11666 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n")); 11667 return ScsiAdapterControlUnsuccessful; 11668 } 11669 } 11670 11671 return ScsiAdapterControlSuccess; 11672 } // end AtapiAdapterControl() 11673 11674 #endif //UNIATA_CORE 11675 11676 extern "C" 11677 NTHALAPI 11678 VOID 11679 NTAPI 11680 HalDisplayString ( 11681 PUCHAR String 11682 ); 11683 11684 #define DEBUG_MSG_BUFFER_SIZE 512 11685 11686 extern "C" 11687 VOID 11688 _cdecl 11689 _PrintNtConsole( 11690 PCCH DebugMessage, 11691 ... 11692 ) 11693 { 11694 //int len; 11695 UCHAR dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE]; 11696 // UNICODE_STRING msgBuff; 11697 va_list ap; 11698 va_start(ap, DebugMessage); 11699 11700 /*len =*/ _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], DEBUG_MSG_BUFFER_SIZE-1, DebugMessage, ap); 11701 11702 dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE-1] = 0; 11703 11704 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro 11705 HalDisplayString(dbg_print_tmp_buff); 11706 11707 #ifdef _DEBUG 11708 if(g_LogToDisplay > 1) { 11709 AtapiStallExecution(g_LogToDisplay*1000); 11710 } 11711 #endif // _DEBUG 11712 11713 va_end(ap); 11714 11715 } // end PrintNtConsole() 11716 11717