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