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 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI command status %#x\n", status)); 6188 if (status == SRB_STATUS_DATA_OVERRUN) { 6189 // Check to see if we at least get mininum number of bytes 6190 if ((srb->DataTransferLength - AtaReq->WordsLeft) > 6191 (FIELD_OFFSET (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) { 6192 status = SRB_STATUS_SUCCESS; 6193 } 6194 } 6195 6196 if (status == SRB_STATUS_SUCCESS) { 6197 #ifndef UNIATA_CORE 6198 #ifdef UNIATA_INIT_CHANGERS 6199 if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) && 6200 FALSE && 6201 chan->MechStatusRetryCount) { 6202 6203 KdPrint3((PRINT_PREFIX "AtapiInterrupt: MechStatusRetryCount %#x\n", chan->MechStatusRetryCount)); 6204 // The sense key doesn't say the last request is illegal, so try again 6205 chan->MechStatusRetryCount--; 6206 srb = AtaReq->Srb = BuildMechanismStatusSrb ( 6207 HwDeviceExtension, 6208 AtaReq->OriginalSrb); 6209 } else 6210 #endif // UNIATA_INIT_CHANGERS 6211 { 6212 // Get ready to issue the original srb 6213 srb = AtaReq->Srb = AtaReq->OriginalSrb; 6214 AtaReq->OriginalSrb = NULL; 6215 } 6216 #endif //UNIATA_CORE 6217 /* 6218 // do not enable interrupts in DPC, do not waste time, do it now! 6219 if(UseDpc && chan->DisableIntr) { 6220 AtapiEnableInterrupts(HwDeviceExtension, c); 6221 UseDpc = FALSE; 6222 RestoreUseDpc = TRUE; 6223 } 6224 */ 6225 srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL); 6226 6227 KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan->ExpectingInterrupt)); 6228 6229 if (srbStatus == SRB_STATUS_PENDING) { 6230 KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n")); 6231 goto ReturnEnableIntr; 6232 } 6233 /* 6234 if(RestoreUseDpc) { 6235 // restore state on error 6236 UseDpc = TRUE; 6237 AtapiDisableInterrupts(HwDeviceExtension, c); 6238 } 6239 */ 6240 } 6241 } 6242 6243 // If we get here, it means AtapiSendCommand() has failed 6244 // Can't recover. Pretend the original srb has failed and complete it. 6245 6246 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. complete OriginalSrb\n")); 6247 6248 if (AtaReq->OriginalSrb) { 6249 srb = AtaReq->Srb = AtaReq->OriginalSrb; 6250 AtaReq->OriginalSrb = NULL; 6251 } 6252 6253 KdPrint2((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan->ExpectingInterrupt)); 6254 6255 // fake an error and read no data 6256 status = SRB_STATUS_ERROR; 6257 srb->ScsiStatus = 0; 6258 AtaReq->DataBuffer = (PUSHORT)(srb->DataBuffer); 6259 AtaReq->WordsLeft = srb->DataTransferLength; 6260 chan->RDP = FALSE; 6261 6262 } else if (status == SRB_STATUS_ERROR) { 6263 6264 // Map error to specific SRB status and handle request sense. 6265 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. Begin mapping...\n")); 6266 status = MapError(deviceExtension, 6267 srb); 6268 6269 chan->RDP = FALSE; 6270 6271 } else if(!DmaTransfer) { 6272 6273 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion\n")); 6274 // Command complete. 6275 PIO_wait_busy: 6276 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion, wait BUSY\n")); 6277 // Wait for busy to drop. 6278 for (i = 0; i < 5*30; i++) { 6279 GetBaseStatus(chan, statusByte); 6280 if (!(statusByte & IDE_STATUS_BUSY)) { 6281 break; 6282 } 6283 if(!InDpc) { 6284 // goto DPC 6285 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY; 6286 TimerValue = 200; 6287 KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (busy)\n")); 6288 #ifndef UNIATA_CORE 6289 goto PostToDpc; 6290 #else //UNIATA_CORE 6291 AtapiStallExecution(TimerValue); 6292 goto ServiceInterrupt; 6293 #endif //UNIATA_CORE 6294 } 6295 AtapiStallExecution(100); 6296 } 6297 6298 if (i == 5*30) { 6299 6300 // reset the controller. 6301 KdPrint2((PRINT_PREFIX 6302 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n", 6303 statusByte)); 6304 goto IntrPrepareResetController; 6305 } 6306 // Check to see if DRQ is still up. 6307 if(statusByte & IDE_STATUS_DRQ) { 6308 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DRQ...\n")); 6309 if(srb) { 6310 if(srb->SrbFlags & SRB_FLAGS_DATA_IN) { 6311 KdPrint2((PRINT_PREFIX "srb %x data in\n", srb)); 6312 } else { 6313 KdPrint2((PRINT_PREFIX "srb %x data out\n", srb)); 6314 } 6315 } else { 6316 KdPrint2((PRINT_PREFIX "srb NULL\n")); 6317 } 6318 if(AtaReq) { 6319 KdPrint2((PRINT_PREFIX "AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq, AtaReq->WordsLeft)); 6320 } else { 6321 KdPrint2((PRINT_PREFIX "AtaReq NULL\n")); 6322 } 6323 if(AtaReq && AtaReq->WordsLeft /*&& 6324 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) { 6325 KdPrint2((PRINT_PREFIX "DRQ+AtaReq->WordsLeft -> next portion\n")); 6326 goto continue_PIO; 6327 } 6328 } 6329 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {} 6330 //if ((statusByte & IDE_STATUS_DRQ)) {} 6331 if((statusByte & IDE_STATUS_DRQ) && 6332 (LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED)) ) { 6333 6334 PIO_wait_DRQ: 6335 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO_wait_DRQ\n")); 6336 for (i = 0; i < 200; i++) { 6337 GetBaseStatus(chan, statusByte); 6338 if (!(statusByte & IDE_STATUS_DRQ)) { 6339 break; 6340 } 6341 if(!InDpc) { 6342 // goto DPC 6343 KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq)\n")); 6344 AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ; 6345 TimerValue = 100; 6346 #ifndef UNIATA_CORE 6347 goto PostToDpc; 6348 #else //UNIATA_CORE 6349 AtapiStallExecution(TimerValue); 6350 goto ServiceInterrupt; 6351 #endif //UNIATA_CORE 6352 } 6353 AtapiStallExecution(100); 6354 } 6355 6356 if (i == 200) { 6357 // reset the controller. 6358 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ still up - %#x\n", 6359 statusByte)); 6360 goto IntrPrepareResetController; 6361 } 6362 } 6363 if(atapiDev) { 6364 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n", 6365 AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)(-1)), srb->DataTransferLength )); 6366 //KdDump(srb->DataBuffer, srb->DataTransferLength); 6367 } 6368 if(!AtapiDmaPioSync(HwDeviceExtension, srb, (PUCHAR)(srb->DataBuffer), srb->DataTransferLength)) { 6369 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n")); 6370 } 6371 } 6372 6373 // Clear interrupt expecting flag. 6374 UniataExpectChannelInterrupt(chan, FALSE); 6375 // clear this flag now, it can be set again in sub-calls 6376 InterlockedExchange(&(chan->CheckIntr), 6377 CHECK_INTR_IDLE); 6378 6379 // Sanity check that there is a current request. 6380 if(srb != NULL) { 6381 // Set status in SRB. 6382 srb->SrbStatus = (UCHAR)status; 6383 6384 // Check for underflow. 6385 if(AtaReq->WordsLeft) { 6386 6387 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq->WordsLeft)); 6388 // Subtract out residual words and update if filemark hit, 6389 // setmark hit , end of data, end of media... 6390 if (!(LunExt->DeviceFlags & DFLAGS_TAPE_DEVICE)) { 6391 if (status == SRB_STATUS_DATA_OVERRUN) { 6392 srb->DataTransferLength -= AtaReq->WordsLeft*2; 6393 } else { 6394 srb->DataTransferLength = 0; 6395 } 6396 } else { 6397 srb->DataTransferLength -= AtaReq->WordsLeft*2; 6398 } 6399 } 6400 if(status == SRB_STATUS_SUCCESS) { 6401 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) { 6402 // // This should be set in UniataAhciEndTransaction() for AHCI 6403 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2; 6404 //} 6405 if(!atapiDev && 6406 AtaReq->WordsTransfered*2 < AtaReq->TransferLength) { 6407 KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n", 6408 AtaReq->WordsTransfered*2, AtaReq->TransferLength)); 6409 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 6410 AtaReq->ReqState = REQ_STATE_PREPARE_TO_NEXT; 6411 goto reenqueue_req; 6412 } else { 6413 KdPrint2((PRINT_PREFIX " Transfered %x, full size %x\n", 6414 AtaReq->WordsTransfered*2, AtaReq->TransferLength)); 6415 } 6416 } 6417 6418 if (srb->Function != SRB_FUNCTION_IO_CONTROL) { 6419 6420 CompleteRDP: 6421 // Indicate command complete. 6422 if (!(chan->RDP)) { 6423 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete\n")); 6424 IntrCompleteReq: 6425 6426 if (status == SRB_STATUS_SUCCESS && 6427 srb->SenseInfoBuffer && 6428 srb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) { 6429 6430 PSENSE_DATA senseBuffer = (PSENSE_DATA)srb->SenseInfoBuffer; 6431 6432 KdPrint2((PRINT_PREFIX "AtapiInterrupt: set AutoSense\n")); 6433 senseBuffer->ErrorCode = 0; 6434 senseBuffer->Valid = 1; 6435 senseBuffer->AdditionalSenseLength = 0xb; 6436 senseBuffer->SenseKey = 0; 6437 senseBuffer->AdditionalSenseCode = 0; 6438 senseBuffer->AdditionalSenseCodeQualifier = 0; 6439 6440 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; 6441 } 6442 AtapiDmaDBSync(chan, srb); 6443 KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove srb %#x, status %x\n", srb, status)); 6444 UniataRemoveRequest(chan, srb); 6445 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete, srb %#x\n", srb)); 6446 ScsiPortNotification(RequestComplete, 6447 deviceExtension, 6448 srb); 6449 } 6450 } else { 6451 6452 KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n")); 6453 6454 if (status != SRB_STATUS_SUCCESS) { 6455 error = AtapiReadPort1(chan, IDX_IO1_i_Error); 6456 KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error)); 6457 } 6458 6459 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) { 6460 6461 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 6462 // Build the SMART status block depending upon the completion status. 6463 cmdOutParameters->cBufferSize = wordCount; 6464 cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0; 6465 cmdOutParameters->DriverStatus.bIDEError = error; 6466 6467 // If the sub-command is return smart status, jam the value from cylinder low and high, into the 6468 // data buffer. 6469 if (chan->SmartCommand == RETURN_SMART_STATUS) { 6470 PIDEREGS_EX regs = (PIDEREGS_EX)&(cmdOutParameters->bBuffer); 6471 6472 regs->bOpFlags = 0; 6473 UniataSnapAtaRegs(chan, 0, regs); 6474 6475 regs->bCommandReg = SMART_CMD; 6476 regs->bFeaturesReg = RETURN_SMART_STATUS; 6477 6478 cmdOutParameters->cBufferSize = 8; 6479 } 6480 chan->SmartCommand = 0; // cleanup after execution 6481 } 6482 // Indicate command complete. 6483 goto IntrCompleteReq; 6484 } 6485 6486 } else { 6487 6488 KdPrint2((PRINT_PREFIX "AtapiInterrupt: No SRB!\n")); 6489 } 6490 6491 if (chan->RDP) { 6492 // Check DSC 6493 for (i = 0; i < 5; i++) { 6494 GetBaseStatus(chan, statusByte); 6495 if(!(statusByte & IDE_STATUS_BUSY)) { 6496 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RDP + cleared BUSY\n")); 6497 chan->RDP = FALSE; 6498 goto CompleteRDP; 6499 } else 6500 if (statusByte & IDE_STATUS_DSC) { 6501 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Clear RDP\n")); 6502 chan->RDP = FALSE; 6503 goto CompleteRDP; 6504 } 6505 AtapiStallExecution(50); 6506 } 6507 } 6508 // RDP can be cleared since previous check 6509 if (chan->RDP) { 6510 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestTimerCall 2000\n")); 6511 6512 TimerValue = 2000; 6513 #ifndef UNIATA_CORE 6514 goto CallTimerDpc; 6515 #else //UNIATA_CORE 6516 AtapiStallExecution(TimerValue); 6517 goto ServiceInterrupt; 6518 #endif //UNIATA_CORE 6519 } 6520 6521 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 6522 enqueue_next_req: 6523 // Get next request 6524 srb = UniataGetCurRequest(chan); 6525 6526 reenqueue_req: 6527 6528 #ifndef UNIATA_CORE 6529 KdPrint2((PRINT_PREFIX "AtapiInterrupt: NextRequest, srb=%#x\n",srb)); 6530 if(!srb) { 6531 ScsiPortNotification(NextRequest, 6532 deviceExtension, 6533 NULL); 6534 } else { 6535 ScsiPortNotification(NextLuRequest, 6536 deviceExtension, 6537 PathId, 6538 TargetId, 6539 Lun); 6540 // in simplex mode next command must NOT be sent here 6541 if(!deviceExtension->simplexOnly) { 6542 AtapiStartIo__(HwDeviceExtension, srb, FALSE); 6543 } 6544 } 6545 // Try to get SRB fron any non-empty queue (later) 6546 if(deviceExtension->simplexOnly) { 6547 NoStartIo = FALSE; 6548 } 6549 #endif //UNIATA_CORE 6550 6551 goto ReturnEnableIntr; 6552 6553 } else { 6554 6555 // Unexpected int. Catch it 6556 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n", 6557 interruptReason, 6558 statusByte)); 6559 6560 if(g_opt_VirtualMachine == VM_QEMU) { 6561 if(interruptReason == ATAPI_IR_IO_toDev && !(statusByte & IDE_STATUS_DRQ) && !DmaTransfer) { 6562 statusByte = WaitForDrq(chan); 6563 if(statusByte & IDE_STATUS_DRQ) { 6564 goto continue_PIO; 6565 } 6566 } 6567 } 6568 6569 if(OldReqState == REQ_STATE_DPC_WAIT_BUSY0 && 6570 AtaReq->WordsLeft == 0) { 6571 KdPrint2((PRINT_PREFIX "AtapiInterrupt: pending WAIT_BUSY0. Complete.\n")); 6572 status = SRB_STATUS_SUCCESS; 6573 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; 6574 goto CompleteRequest; 6575 } 6576 } 6577 6578 ReturnEnableIntr: 6579 6580 KdPrint2((PRINT_PREFIX "AtapiInterrupt: ReturnEnableIntr\n",srb)); 6581 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt 6582 deviceExtension->ExpectingInterrupt = TRUE; 6583 if(UseDpc) { 6584 if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) { 6585 KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiEnableInterrupts__()\n")); 6586 #ifdef UNIATA_USE_XXableInterrupts 6587 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 6588 chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ; 6589 // must be called on DISPATCH_LEVEL 6590 ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension, 6591 AtapiEnableInterrupts__); 6592 #else 6593 AtapiEnableInterrupts(HwDeviceExtension, c); 6594 InterlockedExchange(&(chan->CheckIntr), 6595 CHECK_INTR_IDLE); 6596 // Will raise IRQL to DIRQL 6597 #ifndef UNIATA_CORE 6598 AtapiQueueTimerDpc(HwDeviceExtension, lChannel, 6599 AtapiEnableInterrupts__, 6600 1); 6601 #endif // UNIATA_CORE 6602 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n")); 6603 #endif // UNIATA_USE_XXableInterrupts 6604 } 6605 } 6606 6607 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE); 6608 // in simplex mode next command must be sent here if 6609 // DPC is not used 6610 KdPrint2((PRINT_PREFIX "AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc, NoStartIo)); 6611 6612 #ifndef UNIATA_CORE 6613 if(!UseDpc && /*deviceExtension->simplexOnly &&*/ !NoStartIo) { 6614 chan = UniataGetNextChannel(chan); 6615 if(chan) { 6616 srb = UniataGetCurRequest(chan); 6617 } else { 6618 srb = NULL; 6619 } 6620 KdPrint2((PRINT_PREFIX "AtapiInterrupt: run srb %x\n", srb)); 6621 if(srb) { 6622 AtapiStartIo__(HwDeviceExtension, srb, FALSE); 6623 } 6624 } 6625 #endif //UNIATA_CORE 6626 return TRUE; 6627 6628 } // end AtapiInterrupt__() 6629 6630 #ifndef UNIATA_CORE 6631 6632 /*++ 6633 6634 Routine Description: 6635 6636 This routine handles SMART enable, disable, read attributes and threshold commands. 6637 6638 Arguments: 6639 6640 HwDeviceExtension - HBA miniport driver's adapter data storage 6641 Srb - IO request packet 6642 6643 Return Value: 6644 6645 SRB status 6646 6647 --*/ 6648 ULONG 6649 NTAPI 6650 IdeSendSmartCommand( 6651 IN PVOID HwDeviceExtension, 6652 IN PSCSI_REQUEST_BLOCK Srb, 6653 IN ULONG targetId // assume it is always valid 6654 ) 6655 { 6656 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 6657 ULONG c ; // = GET_CHANNEL(Srb); may be invalid 6658 PHW_CHANNEL chan ; // = &(deviceExtension->chan[c]); 6659 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 6660 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 6661 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 6662 PIDEREGS regs = &cmdInParameters.irDriveRegs; 6663 // ULONG i; 6664 UCHAR statusByte; 6665 ULONG DeviceNumber; 6666 6667 if (regs->bCommandReg != SMART_CMD) { 6668 KdPrint2((PRINT_PREFIX 6669 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n")); 6670 return SRB_STATUS_INVALID_REQUEST; 6671 } 6672 6673 c = targetId / deviceExtension->NumberLuns; 6674 DeviceNumber = targetId % deviceExtension->NumberLuns; 6675 KdPrint2((PRINT_PREFIX " c %d, dev %d\n", c, DeviceNumber)); 6676 6677 chan = &(deviceExtension->chan[c]); 6678 6679 chan->SmartCommand = regs->bFeaturesReg; 6680 6681 // Determine which of the commands to carry out. 6682 switch(regs->bFeaturesReg) { 6683 case READ_ATTRIBUTES: 6684 case READ_THRESHOLDS: 6685 case READ_LOG_SECTOR: 6686 case WRITE_LOG_SECTOR: 6687 6688 if(Srb->DataTransferLength < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1) { 6689 KdPrint2((PRINT_PREFIX 6690 "IdeSendSmartCommand: wrong buffer size\n")); 6691 return SRB_STATUS_DATA_OVERRUN; 6692 } 6693 6694 statusByte = WaitOnBusy(chan); 6695 6696 if (statusByte & IDE_STATUS_BUSY) { 6697 KdPrint2((PRINT_PREFIX 6698 "IdeSendSmartCommand: Returning BUSY status\n")); 6699 return SRB_STATUS_BUSY; 6700 } 6701 6702 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same). 6703 RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1); 6704 6705 // Set data buffer pointer and words left. 6706 AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer; 6707 AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2; 6708 6709 statusByte = AtaCommand(deviceExtension, DeviceNumber, c, 6710 regs->bCommandReg, 6711 (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8), 6712 0, 6713 regs->bSectorNumberReg, 6714 regs->bSectorCountReg, 6715 regs->bFeaturesReg, 6716 ATA_IMMEDIATE); 6717 6718 if(!(statusByte & IDE_STATUS_ERROR)) { 6719 // Wait for interrupt. 6720 return SRB_STATUS_PENDING; 6721 } 6722 return SRB_STATUS_ERROR; 6723 6724 case ENABLE_SMART: 6725 case DISABLE_SMART: 6726 case RETURN_SMART_STATUS: 6727 case ENABLE_DISABLE_AUTOSAVE: 6728 case EXECUTE_OFFLINE_DIAGS: 6729 case SAVE_ATTRIBUTE_VALUES: 6730 case AUTO_OFFLINE: 6731 6732 statusByte = WaitOnBusy(chan); 6733 6734 if (statusByte & IDE_STATUS_BUSY) { 6735 KdPrint2((PRINT_PREFIX 6736 "IdeSendSmartCommand: Returning BUSY status\n")); 6737 return SRB_STATUS_BUSY; 6738 } 6739 6740 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same). 6741 RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) - 1); 6742 6743 // Set data buffer pointer and indicate no data transfer. 6744 AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer; 6745 AtaReq->WordsLeft = 0; 6746 6747 statusByte = AtaCommand(deviceExtension, DeviceNumber, c, 6748 regs->bCommandReg, 6749 (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8), 6750 0, 6751 regs->bSectorNumberReg, 6752 regs->bSectorCountReg, 6753 regs->bFeaturesReg, 6754 ATA_IMMEDIATE); 6755 6756 if(!(statusByte & IDE_STATUS_ERROR)) { 6757 // Wait for interrupt. 6758 UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt 6759 return SRB_STATUS_PENDING; 6760 } 6761 return SRB_STATUS_ERROR; 6762 } // end switch(regs->bFeaturesReg) 6763 6764 return SRB_STATUS_INVALID_REQUEST; 6765 6766 } // end IdeSendSmartCommand() 6767 6768 #endif //UNIATA_CORE 6769 6770 ULONGLONG 6771 NTAPI 6772 UniAtaCalculateLBARegs( 6773 PHW_LU_EXTENSION LunExt, 6774 ULONGLONG startingSector, 6775 PULONG max_bcount 6776 ) 6777 { 6778 UCHAR drvSelect,sectorNumber; 6779 USHORT cylinder; 6780 ULONG tmp; 6781 6782 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) { 6783 (*max_bcount) = 0; 6784 if(LunExt->LimitedTransferMode >= ATA_DMA) { 6785 if(LunExt->DeviceExtension) { 6786 (*max_bcount) = LunExt->DeviceExtension->MaximumDmaTransferLength / DEV_BSIZE; 6787 } 6788 } 6789 return startingSector; 6790 } 6791 tmp = LunExt->IdentifyData.SectorsPerTrack * 6792 LunExt->IdentifyData.NumberOfHeads; 6793 if(!tmp) { 6794 KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: 0-sized\n")); 6795 cylinder = 0; 6796 drvSelect = 0; 6797 sectorNumber = 1; 6798 (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack; 6799 } else { 6800 cylinder = (USHORT)(startingSector / tmp); 6801 drvSelect = (UCHAR)((startingSector % tmp) / LunExt->IdentifyData.SectorsPerTrack); 6802 sectorNumber = (UCHAR)(startingSector % LunExt->IdentifyData.SectorsPerTrack) + 1; 6803 (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack - sectorNumber + 1; 6804 KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n", 6805 cylinder, drvSelect, sectorNumber, (*max_bcount))); 6806 } 6807 6808 return (ULONG)(sectorNumber&0xff) | (((ULONG)cylinder&0xffff)<<8) | (((ULONG)drvSelect&0xf)<<24); 6809 } // end UniAtaCalculateLBARegs() 6810 6811 ULONGLONG 6812 NTAPI 6813 UniAtaCalculateLBARegsBack( 6814 PHW_LU_EXTENSION LunExt, 6815 ULONGLONG lba 6816 ) 6817 { 6818 ULONG drvSelect,sectorNumber; 6819 ULONG cylinder; 6820 ULONG tmp; 6821 6822 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) { 6823 return lba; 6824 } 6825 tmp = LunExt->IdentifyData.SectorsPerTrack * 6826 LunExt->IdentifyData.NumberOfHeads; 6827 6828 cylinder = (USHORT)((lba >> 8) & 0xffff); 6829 drvSelect = (UCHAR)((lba >> 24) & 0xf); 6830 sectorNumber = (UCHAR)(lba & 0xff); 6831 6832 lba = sectorNumber-1 + 6833 (drvSelect*LunExt->IdentifyData.SectorsPerTrack) + 6834 (cylinder*tmp); 6835 6836 return lba; 6837 } // end UniAtaCalculateLBARegsBack() 6838 6839 6840 /*++ 6841 6842 Routine Description: 6843 6844 This routine handles IDE read and writes. 6845 6846 Arguments: 6847 6848 HwDeviceExtension - HBA miniport driver's adapter data storage 6849 Srb - IO request packet 6850 6851 Return Value: 6852 6853 SRB status 6854 6855 --*/ 6856 ULONG 6857 NTAPI 6858 IdeReadWrite( 6859 IN PVOID HwDeviceExtension, 6860 IN PSCSI_REQUEST_BLOCK Srb, 6861 IN ULONG CmdAction 6862 ) 6863 { 6864 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 6865 UCHAR lChannel = GET_CHANNEL(Srb); 6866 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 6867 PHW_LU_EXTENSION LunExt; 6868 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 6869 //ULONG ldev = GET_LDEV(Srb); 6870 UCHAR DeviceNumber = GET_CDEV(Srb);; 6871 ULONGLONG startingSector=0; 6872 ULONG max_bcount = 0; 6873 ULONG wordCount = 0; 6874 UCHAR statusByte,statusByte2; 6875 UCHAR cmd; 6876 ULONGLONG lba; 6877 BOOLEAN use_dma = FALSE; 6878 ULONG fis_size; 6879 6880 AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD; 6881 LunExt = chan->lun[DeviceNumber]; 6882 6883 if((CmdAction & CMD_ACTION_PREPARE) && 6884 (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) { 6885 6886 if(LunExt->opt_ReadOnly && 6887 (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) { 6888 if(LunExt->opt_ReadOnly == 1) { 6889 KdPrint2((PRINT_PREFIX "Abort WRITE (Soft R/O)\n")); 6890 return SRB_STATUS_ERROR; 6891 } else { 6892 KdPrint2((PRINT_PREFIX "Ignore WRITE (Soft R/O)\n")); 6893 return SRB_STATUS_SUCCESS; 6894 } 6895 } 6896 6897 // Set data buffer pointer and words left. 6898 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 6899 6900 if(AtaReq->WordsTransfered) { 6901 AtaReq->DataBuffer = ((PUSHORT)(Srb->DataBuffer)) + AtaReq->WordsTransfered; 6902 startingSector = (UniAtaCalculateLBARegsBack(LunExt, AtaReq->lba)) /* latest lba */ + AtaReq->bcount /* previous bcount */; 6903 AtaReq->bcount = (AtaReq->TransferLength - AtaReq->WordsTransfered*2 + DEV_BSIZE-1) / DEV_BSIZE; 6904 KdPrint2((PRINT_PREFIX "IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n", 6905 startingSector, 6906 AtaReq->TransferLength/2, 6907 AtaReq->WordsTransfered, 6908 AtaReq->bcount)); 6909 } else { 6910 AtaReq->DataBuffer = (PUSHORT)(Srb->DataBuffer); 6911 AtaReq->TransferLength = Srb->DataTransferLength; 6912 // Set up 1st block. 6913 switch(Srb->Cdb[0]) { 6914 case SCSIOP_WRITE: 6915 if(LunExt->DeviceFlags & DFLAGS_LBA32plus) { 6916 KdPrint2((PRINT_PREFIX "Attention: SCSIOP_WRITE on 2TB\n")); 6917 //return SRB_STATUS_ERROR; 6918 } 6919 // FALLTHROUGH 6920 case SCSIOP_READ: 6921 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA); 6922 MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks); 6923 break; 6924 case SCSIOP_WRITE12: 6925 if(LunExt->DeviceFlags & DFLAGS_LBA32plus) { 6926 KdPrint2((PRINT_PREFIX "Attention: SCSIOP_WRITE12 on 2TB\n")); 6927 //return SRB_STATUS_ERROR; 6928 } 6929 // FALLTHROUGH 6930 case SCSIOP_READ12: 6931 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA); 6932 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks); 6933 break; 6934 case SCSIOP_READ16: 6935 case SCSIOP_WRITE16: 6936 MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA); 6937 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks); 6938 break; 6939 } 6940 KdPrint2((PRINT_PREFIX "IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n", 6941 startingSector, 6942 AtaReq->TransferLength/2, 6943 AtaReq->bcount)); 6944 } 6945 lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount); 6946 6947 if(max_bcount) { 6948 AtaReq->bcount = min(AtaReq->bcount, max_bcount); 6949 } 6950 AtaReq->WordsLeft = min(AtaReq->TransferLength - AtaReq->WordsTransfered*2, 6951 AtaReq->bcount * DEV_BSIZE) / 2; 6952 6953 KdPrint2((PRINT_PREFIX "IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n", 6954 startingSector, 6955 AtaReq->WordsLeft, 6956 AtaReq->bcount)); 6957 6958 AtaReq->lba = lba; 6959 if(LunExt->errRetry && 6960 lba == LunExt->errLastLba && 6961 /* AtaReq->bcount && */ // errRetry can be set only for non-zero bcount 6962 AtaReq->bcount == LunExt->errBCount) { 6963 KdPrint3((PRINT_PREFIX "IdeReadWrite: Retry after BUS_RESET %d @%#I64x (%#x)\n", 6964 LunExt->errRetry, LunExt->errLastLba, LunExt->errBCount)); 6965 if(AtaReq->retry < MAX_RETRIES) { 6966 AtaReq->retry = LunExt->errRetry; 6967 AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE; 6968 } 6969 LunExt->errRetry = 0; 6970 } 6971 6972 // assume best case here 6973 // we cannot reinit Dma until previous request is completed 6974 if(deviceExtension->HwFlags & UNIATA_AHCI) { 6975 UniataAhciSetupCmdPtr(AtaReq); 6976 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 6977 (PUCHAR)(AtaReq->DataBuffer), 6978 AtaReq->bcount * DEV_BSIZE)) { 6979 KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !DMA\n")); 6980 return SRB_STATUS_ERROR; 6981 } 6982 } else 6983 if ((LunExt->LimitedTransferMode >= ATA_DMA)) { 6984 use_dma = TRUE; 6985 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success 6986 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 6987 (PUCHAR)(AtaReq->DataBuffer), 6988 AtaReq->bcount * DEV_BSIZE)) { 6989 use_dma = FALSE; 6990 } 6991 } 6992 6993 if(deviceExtension->HwFlags & UNIATA_AHCI) { 6994 KdPrint2((PRINT_PREFIX "IdeReadWrite: setup AHCI FIS\n")); 6995 RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis)); 6996 6997 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel, 6998 &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]), 6999 (AtaReq->Flags & REQ_FLAG_READ) ? IDE_COMMAND_READ_DMA : IDE_COMMAND_WRITE_DMA, 7000 lba, 7001 (USHORT)(AtaReq->bcount), 7002 0 7003 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/ 7004 ); 7005 7006 if(!fis_size) { 7007 KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !FIS\n")); 7008 return SRB_STATUS_ERROR; 7009 } 7010 7011 AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0, (AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE, fis_size, DeviceNumber); 7012 KdPrint2((PRINT_PREFIX "IdeReadWrite ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags)); 7013 } 7014 7015 AtaReq->ReqState = REQ_STATE_READY_TO_TRANSFER; 7016 7017 } else { // exec_only 7018 KdPrint2((PRINT_PREFIX "IdeReadWrite (ExecOnly): \n")); 7019 lba = AtaReq->lba; 7020 7021 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) { 7022 use_dma = TRUE; 7023 } 7024 } 7025 if(!(CmdAction & CMD_ACTION_EXEC)) { 7026 7027 return SRB_STATUS_PENDING; 7028 } 7029 7030 // if this is queued request, reinit DMA and check 7031 // if DMA mode is still available 7032 AtapiDmaReinit(deviceExtension, LunExt, AtaReq); 7033 if (/*EnableDma &&*/ 7034 (LunExt->TransferMode >= ATA_DMA)) { 7035 use_dma = TRUE; 7036 } else { 7037 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7038 use_dma = FALSE; 7039 } 7040 7041 // Check if write request. 7042 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 7043 7044 // Prepare read command. 7045 if(use_dma) { 7046 cmd = IDE_COMMAND_READ_DMA; 7047 } else 7048 if(LunExt->MaximumBlockXfer) { 7049 cmd = IDE_COMMAND_READ_MULTIPLE; 7050 } else { 7051 cmd = IDE_COMMAND_READ; 7052 } 7053 } else { 7054 7055 // Prepare write command. 7056 if (use_dma) { 7057 wordCount = AtaReq->bcount*DEV_BSIZE/2; 7058 cmd = IDE_COMMAND_WRITE_DMA; 7059 } else 7060 if (LunExt->MaximumBlockXfer) { 7061 wordCount = DEV_BSIZE/2 * LunExt->MaximumBlockXfer; 7062 7063 if (AtaReq->WordsLeft < wordCount) { 7064 // Transfer only words requested. 7065 wordCount = AtaReq->WordsLeft; 7066 } 7067 cmd = IDE_COMMAND_WRITE_MULTIPLE; 7068 7069 } else { 7070 wordCount = DEV_BSIZE/2; 7071 cmd = IDE_COMMAND_WRITE; 7072 } 7073 } 7074 7075 // Send IO command. 7076 KdPrint2((PRINT_PREFIX "IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba, ((Srb->DataTransferLength + 0x1FF) / 0x200), 7077 ((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE))); 7078 if(use_dma) { 7079 chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION; 7080 } else { 7081 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; 7082 } 7083 7084 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7085 // AHCI doesn't distinguish DMA and PIO 7086 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); 7087 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 7088 UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt 7089 InterlockedExchange(&(chan->CheckIntr), 7090 CHECK_INTR_IDLE); 7091 return SRB_STATUS_PENDING; 7092 } 7093 7094 if ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) || 7095 use_dma) { 7096 if(use_dma) { 7097 AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb); 7098 if(g_opt_BochsDmaReadWorkaround && 7099 (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) { 7100 KdPrint2((PRINT_PREFIX "CTRFLAGS_DMA_BEFORE_R on BOCHS\n")); 7101 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); 7102 } 7103 } 7104 statusByte2 = AtaCommand48(deviceExtension, DeviceNumber, lChannel, 7105 cmd, lba, 7106 (USHORT)(AtaReq->bcount), 7107 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE), 7108 0, ATA_IMMEDIATE); 7109 /* if(statusByte2 != IDE_STATUS_WRONG) { 7110 GetStatus(chan, statusByte2); 7111 }*/ 7112 if(statusByte2 & IDE_STATUS_ERROR) { 7113 // Unfortunately, we cannot handle errors in such a way in real life (except known bad blocks). 7114 // Because some devices doesn't reset ERR from previous command immediately after getting new one. 7115 // On the other hand we cannot wait here because of possible timeout condition 7116 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 7117 KdPrint2((PRINT_PREFIX "IdeReadWrite: status %#x, error %#x\n", statusByte2, statusByte)); 7118 return SRB_STATUS_ERROR; 7119 } 7120 if(use_dma) { 7121 if(!g_opt_BochsDmaReadWorkaround || 7122 !(Srb->SrbFlags & SRB_FLAGS_DATA_IN)) { 7123 //GetStatus(chan, statusByte2); 7124 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); 7125 } 7126 } 7127 return SRB_STATUS_PENDING; 7128 } 7129 7130 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel, 7131 cmd, lba, 7132 (USHORT)(AtaReq->bcount), 7133 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE), 7134 0, ATA_WAIT_INTR); 7135 7136 if (!(statusByte & IDE_STATUS_DRQ) || 7137 statusByte == IDE_STATUS_WRONG) { 7138 7139 if(statusByte == IDE_STATUS_WRONG) { 7140 KdPrint2((PRINT_PREFIX 7141 "IdeReadWrite: error sending command (%#x)\n", 7142 statusByte)); 7143 } else { 7144 KdPrint2((PRINT_PREFIX 7145 "IdeReadWrite: DRQ never asserted (%#x)\n", 7146 statusByte)); 7147 } 7148 7149 AtaReq->WordsLeft = 0; 7150 7151 // Clear interrupt expecting flag. 7152 UniataExpectChannelInterrupt(chan, FALSE); 7153 InterlockedExchange(&(chan->CheckIntr), 7154 CHECK_INTR_IDLE); 7155 7156 // Clear current SRB. 7157 UniataRemoveRequest(chan, Srb); 7158 7159 return (statusByte == IDE_STATUS_WRONG) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT; 7160 } 7161 7162 UniataExpectChannelInterrupt(chan, TRUE); 7163 InterlockedExchange(&(chan->CheckIntr), 7164 CHECK_INTR_IDLE); 7165 7166 // Write next DEV_BSIZE/2*N words. 7167 if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) || (wordCount & 1)) { 7168 KdPrint2((PRINT_PREFIX 7169 "IdeReadWrite: Write %#x words\n", wordCount)); 7170 7171 WriteBuffer(chan, 7172 AtaReq->DataBuffer, 7173 wordCount, 7174 UniataGetPioTiming(LunExt)); 7175 7176 } else { 7177 7178 KdPrint2((PRINT_PREFIX 7179 "IdeReadWrite: Write %#x Dwords\n", wordCount/2)); 7180 7181 WriteBuffer2(chan, 7182 (PULONG)(AtaReq->DataBuffer), 7183 wordCount / 2, 7184 UniataGetPioTiming(LunExt)); 7185 } 7186 7187 // Adjust buffer address and words left count. 7188 AtaReq->WordsLeft -= wordCount; 7189 AtaReq->DataBuffer += wordCount; 7190 AtaReq->WordsTransfered += wordCount; 7191 7192 // Wait for interrupt. 7193 return SRB_STATUS_PENDING; 7194 7195 } // end IdeReadWrite() 7196 7197 #ifndef UNIATA_CORE 7198 7199 /*++ 7200 7201 Routine Description: 7202 This routine handles IDE Verify. 7203 7204 Arguments: 7205 HwDeviceExtension - HBA miniport driver's adapter data storage 7206 Srb - IO request packet 7207 ` 7208 Return Value: 7209 SRB status 7210 7211 --*/ 7212 ULONG 7213 NTAPI 7214 IdeVerify( 7215 IN PVOID HwDeviceExtension, 7216 IN PSCSI_REQUEST_BLOCK Srb 7217 ) 7218 { 7219 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 7220 UCHAR lChannel = GET_CHANNEL(Srb); 7221 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 7222 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 7223 PHW_LU_EXTENSION LunExt; 7224 //ULONG ldev = GET_LDEV(Srb); 7225 ULONG DeviceNumber = GET_CDEV(Srb); 7226 UCHAR statusByte; 7227 ULONGLONG startingSector=0; 7228 ULONG max_bcount; 7229 ULONGLONG sectors; 7230 ULONGLONG endSector; 7231 ULONG sectorCount=0; 7232 ULONGLONG lba; 7233 7234 LunExt = chan->lun[DeviceNumber]; 7235 // Drive has these number sectors. 7236 if(!(sectors = (ULONG)(LunExt->NumOfSectors))) { 7237 sectors = LunExt->IdentifyData.SectorsPerTrack * 7238 LunExt->IdentifyData.NumberOfHeads * 7239 LunExt->IdentifyData.NumberOfCylinders; 7240 } 7241 7242 KdPrint2((PRINT_PREFIX 7243 "IdeVerify: Total sectors %#I64x\n", 7244 sectors)); 7245 7246 // Get starting sector number from CDB. 7247 switch(Srb->Cdb[0]) { 7248 case SCSIOP_VERIFY: 7249 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA); 7250 MOV_SWP_DW2DD(sectorCount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks); 7251 break; 7252 case SCSIOP_VERIFY12: 7253 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA); 7254 MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks); 7255 break; 7256 case SCSIOP_VERIFY16: 7257 MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA); 7258 MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks); 7259 break; 7260 } 7261 7262 KdPrint2((PRINT_PREFIX 7263 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n", 7264 startingSector, 7265 sectorCount)); 7266 7267 endSector = startingSector + sectorCount; 7268 7269 KdPrint2((PRINT_PREFIX 7270 "IdeVerify: Ending sector %#I64x\n", 7271 endSector)); 7272 7273 if (endSector > sectors) { 7274 7275 // Too big, round down. 7276 KdPrint2((PRINT_PREFIX 7277 "IdeVerify: Truncating request to %#x blocks\n", 7278 sectors - startingSector - 1)); 7279 7280 sectorCount = (ULONG)(sectors - startingSector - 1); 7281 7282 } else { 7283 7284 // Set up sector count register. Round up to next block. 7285 if (sectorCount > 0xFF) { 7286 sectorCount = (USHORT)0xFF; 7287 } 7288 } 7289 7290 // Set data buffer pointer and words left. 7291 AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer; 7292 AtaReq->WordsLeft = Srb->DataTransferLength / 2; 7293 7294 // Indicate expecting an interrupt. 7295 InterlockedExchange(&(chan->CheckIntr), 7296 CHECK_INTR_IDLE); 7297 7298 lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount); 7299 7300 statusByte = AtaCommand48(deviceExtension, LunExt->Lun, GET_CHANNEL(Srb), 7301 IDE_COMMAND_VERIFY, lba, 7302 (USHORT)sectorCount, 7303 0, ATA_IMMEDIATE); 7304 7305 if(!(statusByte & IDE_STATUS_ERROR)) { 7306 // Wait for interrupt. 7307 UniataExpectChannelInterrupt(chan, TRUE); 7308 return SRB_STATUS_PENDING; 7309 } 7310 return SRB_STATUS_ERROR; 7311 7312 } // end IdeVerify() 7313 7314 #endif //UNIATA_CORE 7315 7316 /*++ 7317 7318 Routine Description: 7319 Send ATAPI packet command to device. 7320 7321 Arguments: 7322 HwDeviceExtension - HBA miniport driver's adapter data storage 7323 Srb - IO request packet 7324 7325 Return Value: 7326 7327 --*/ 7328 ULONG 7329 NTAPI 7330 AtapiSendCommand( 7331 IN PVOID HwDeviceExtension, 7332 IN PSCSI_REQUEST_BLOCK Srb, 7333 IN ULONG CmdAction 7334 ) 7335 { 7336 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 7337 UCHAR lChannel = GET_CHANNEL(Srb); 7338 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); 7339 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 7340 PHW_LU_EXTENSION LunExt; 7341 //ULONG ldev = GET_LDEV(Srb); 7342 ULONG DeviceNumber = GET_CDEV(Srb); 7343 ULONG flags; 7344 UCHAR statusByte,statusByte0,byteCountLow,byteCountHigh; 7345 UCHAR interruptReason; 7346 BOOLEAN use_dma = FALSE; 7347 BOOLEAN dma_reinited = FALSE; 7348 BOOLEAN retried = FALSE; 7349 ULONG fis_size, i; 7350 UCHAR FeatureReg=0; 7351 7352 LunExt = chan->lun[DeviceNumber]; 7353 7354 KdPrint3((PRINT_PREFIX "AtapiSendCommand: req state %#x, Action %x\n", AtaReq->ReqState, CmdAction)); 7355 if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER) 7356 AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER; 7357 7358 7359 #ifdef UNIATA_DUMP_ATAPI 7360 if(CmdAction & CMD_ACTION_PREPARE) { 7361 UCHAR ScsiCommand; 7362 PCDB Cdb; 7363 PCHAR CdbData; 7364 PCHAR ModeSelectData; 7365 ULONG CdbDataLen; 7366 7367 Cdb = (PCDB)(Srb->Cdb); 7368 ScsiCommand = Cdb->CDB6.OperationCode; 7369 CdbData = (PCHAR)(Srb->DataBuffer); 7370 CdbDataLen = Srb->DataTransferLength; 7371 7372 if(CdbDataLen > 0x1000) { 7373 CdbDataLen = 0x1000; 7374 } 7375 7376 KdPrint(("--\n")); 7377 KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID)); 7378 KdPrint2(("P:T:D=%d:%d:%d\n", 7379 Srb->PathId, 7380 Srb->TargetId, 7381 Srb->Lun)); 7382 KdPrint(("SCSI Command %2.2x\n", ScsiCommand)); 7383 KdDump(Cdb, 16); 7384 7385 if(ScsiCommand == SCSIOP_WRITE_CD) { 7386 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n", 7387 Cdb->WRITE_CD.LBA[0], 7388 Cdb->WRITE_CD.LBA[1], 7389 Cdb->WRITE_CD.LBA[2], 7390 Cdb->WRITE_CD.LBA[3] 7391 )); 7392 } else 7393 if(ScsiCommand == SCSIOP_WRITE12) { 7394 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n", 7395 Cdb->CDB12READWRITE.LBA[0], 7396 Cdb->CDB12READWRITE.LBA[1], 7397 Cdb->CDB12READWRITE.LBA[2], 7398 Cdb->CDB12READWRITE.LBA[3] 7399 )); 7400 } else 7401 if(ScsiCommand == SCSIOP_WRITE16) { 7402 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", 7403 Cdb->CDB16READWRITE.LBA[0], 7404 Cdb->CDB16READWRITE.LBA[1], 7405 Cdb->CDB16READWRITE.LBA[2], 7406 Cdb->CDB16READWRITE.LBA[3], 7407 Cdb->CDB16READWRITE.LBA[4], 7408 Cdb->CDB16READWRITE.LBA[5], 7409 Cdb->CDB16READWRITE.LBA[6], 7410 Cdb->CDB16READWRITE.LBA[7] 7411 )); 7412 } else 7413 if(ScsiCommand == SCSIOP_MODE_SELECT) { 7414 KdPrint(("ModeSelect 6\n")); 7415 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData; 7416 ModeSelectData = CdbData+4; 7417 KdDump(CdbData, CdbDataLen); 7418 } else 7419 if(ScsiCommand == SCSIOP_MODE_SELECT10) { 7420 KdPrint(("ModeSelect 10\n")); 7421 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData; 7422 ModeSelectData = CdbData+8; 7423 KdDump(CdbData, CdbDataLen); 7424 } else { 7425 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { 7426 KdPrint(("Send buffer to device:\n")); 7427 KdDump(CdbData, CdbDataLen); 7428 } 7429 } 7430 KdPrint(("--\n")); 7431 } 7432 #endif //UNIATA_DUMP_ATAPI 7433 7434 7435 if(CmdAction == CMD_ACTION_PREPARE) { 7436 KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb->Cdb))); 7437 7438 switch (Srb->Cdb[0]) { 7439 case SCSIOP_RECEIVE: 7440 case SCSIOP_SEND: 7441 case SCSIOP_READ: 7442 case SCSIOP_WRITE: 7443 case SCSIOP_READ12: 7444 case SCSIOP_WRITE12: 7445 case SCSIOP_READ16: 7446 case SCSIOP_WRITE16: 7447 // all right 7448 break; 7449 case SCSIOP_READ_CD: 7450 case SCSIOP_READ_CD_MSF: 7451 if(deviceExtension->opt_AtapiDmaRawRead) { 7452 // all right 7453 break; 7454 } 7455 /* FALL THROUGH */ 7456 default: 7457 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY\n")); 7458 return SRB_STATUS_BUSY; 7459 } 7460 // 7461 #ifdef UNIATA_INIT_CHANGERS 7462 if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) && 7463 !AtaReq->OriginalSrb) { 7464 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY (2)\n")); 7465 return SRB_STATUS_BUSY; 7466 } 7467 #endif // UNIATA_INIT_CHANGERS 7468 } 7469 7470 #ifndef UNIATA_CORE 7471 // standard atapi.sys claims: 7472 7473 // We need to know how many platters our atapi cd-rom device might have. 7474 // Before anyone tries to send a srb to our target for the first time, 7475 // we must "secretly" send down a separate mechanism status srb in order to 7476 // initialize our device extension changer data. That's how we know how 7477 // many platters our target has. 7478 7479 // BUT! 7480 // some devices freeze (sometimes) forever on this command 7481 // Let CD-ROM driver send this command itself, if it find it necessary 7482 // We shall just parse output (if any) 7483 7484 #ifdef UNIATA_INIT_CHANGERS 7485 if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) && 7486 !AtaReq->OriginalSrb) { 7487 7488 ULONG srbStatus; 7489 7490 KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n")); 7491 // Set this flag now. If the device hangs on the mech. status 7492 // command, we will not have the chance to set it. 7493 LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED; 7494 7495 chan->MechStatusRetryCount = 3; 7496 AtaReq->OriginalSrb = Srb; 7497 AtaReq->Srb = BuildMechanismStatusSrb ( 7498 HwDeviceExtension, 7499 Srb); 7500 7501 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n")); 7502 srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL); 7503 if (srbStatus == SRB_STATUS_PENDING) { 7504 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n")); 7505 return srbStatus; 7506 } else { 7507 7508 // failed! Get the sense key and maybe try again 7509 AtaReq->Srb = BuildRequestSenseSrb ( HwDeviceExtension, 7510 AtaReq->OriginalSrb); 7511 7512 srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL); 7513 7514 KdPrint3((PRINT_PREFIX "AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt)); 7515 7516 if (srbStatus == SRB_STATUS_PENDING) { 7517 KdPrint2((PRINT_PREFIX "AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n")); 7518 return srbStatus; 7519 } 7520 7521 // failed again ? should not get here 7522 AtaReq->Srb = AtaReq->OriginalSrb; 7523 AtaReq->OriginalSrb = NULL; 7524 // fall out 7525 } 7526 } 7527 #endif // UNIATA_INIT_CHANGERS 7528 #endif //UNIATA_CORE 7529 7530 if((CmdAction & CMD_ACTION_PREPARE) && 7531 (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) { 7532 7533 KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb->Cdb[0], &(Srb->Cdb))); 7534 7535 if(!LunExt->IdentifyData.AtapiCmdSize && 7536 (Srb->CdbLength > 12)) { 7537 KdPrint2((PRINT_PREFIX "Cdb16 not supported\n")); 7538 return SRB_STATUS_INVALID_REQUEST; 7539 } 7540 7541 // Set data buffer pointer and words left. 7542 AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer; 7543 AtaReq->WordsLeft = Srb->DataTransferLength / 2; 7544 AtaReq->TransferLength = Srb->DataTransferLength; 7545 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7546 // reset this to force PRD init. May be already setup by recursive SRB 7547 AtaReq->dma_entries = 0; 7548 7549 // check if reorderable 7550 switch(Srb->Cdb[0]) { 7551 case SCSIOP_READ16: 7552 case SCSIOP_WRITE16: 7553 7554 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks); 7555 MOV_QD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA); 7556 goto GetLba2; 7557 7558 case SCSIOP_READ12: 7559 case SCSIOP_WRITE12: 7560 7561 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks); 7562 goto GetLba; 7563 7564 case SCSIOP_READ: 7565 case SCSIOP_WRITE: 7566 7567 MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks); 7568 GetLba: 7569 MOV_DD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB10.LBA); 7570 GetLba2: 7571 AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD; 7572 AtaReq->Flags &= ~REQ_FLAG_RW_MASK; 7573 AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE || 7574 Srb->Cdb[0] == SCSIOP_WRITE12 || 7575 Srb->Cdb[0] == SCSIOP_WRITE16) ? 7576 REQ_FLAG_WRITE : REQ_FLAG_READ; 7577 break; 7578 default: 7579 AtaReq->Flags &= ~REQ_FLAG_RW_MASK; 7580 if(!AtaReq->TransferLength) { 7581 KdPrint((" assume 0-transfer\n")); 7582 } else 7583 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { 7584 KdPrint((" assume OUT\n")); 7585 AtaReq->Flags |= REQ_FLAG_WRITE; 7586 } else 7587 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 7588 KdPrint((" assume IN\n")); 7589 AtaReq->Flags |= REQ_FLAG_READ; 7590 } 7591 break; 7592 } 7593 7594 // check if DMA read/write 7595 if(g_opt_AtapiNoDma) { 7596 KdPrint2((PRINT_PREFIX "AtapiSendCommand: CTRFLAGS_DMA_BEFORE_R => no dma\n")); 7597 use_dma = FALSE; 7598 } else 7599 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7600 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (ahci)\n")); 7601 use_dma = TRUE; 7602 goto setup_dma; 7603 } else 7604 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) { 7605 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n")); 7606 use_dma = TRUE; 7607 goto setup_dma; 7608 } else*/ 7609 if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) { 7610 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n")); 7611 } else 7612 if(AtaReq->TransferLength && !(AtaReq->TransferLength & 0x0f)) { 7613 KdPrint2((PRINT_PREFIX "AtapiSendCommand: try DMA setup\n")); 7614 // try use DMA if TransferLength is 16-byte aligned 7615 switch(Srb->Cdb[0]) { 7616 case SCSIOP_WRITE: 7617 case SCSIOP_WRITE12: 7618 case SCSIOP_WRITE16: 7619 case SCSIOP_SEND: 7620 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) 7621 break; 7622 /* FALLTHROUGH */ 7623 case SCSIOP_RECEIVE: 7624 case SCSIOP_READ: 7625 case SCSIOP_READ12: 7626 case SCSIOP_READ16: 7627 7628 if(deviceExtension->opt_AtapiDmaReadWrite) { 7629 call_dma_setup: 7630 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7631 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n")); 7632 use_dma = TRUE; 7633 } else 7634 if(AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 7635 (PUCHAR)(AtaReq->DataBuffer), 7636 Srb->DataTransferLength 7637 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/ 7638 )) { 7639 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n")); 7640 use_dma = TRUE; 7641 } 7642 } 7643 break; 7644 case SCSIOP_READ_CD: 7645 case SCSIOP_READ_CD_MSF: 7646 if(deviceExtension->opt_AtapiDmaRawRead) 7647 goto call_dma_setup; 7648 break; 7649 default: 7650 7651 if(deviceExtension->opt_AtapiDmaControlCmd) { 7652 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 7653 // read operation 7654 use_dma = TRUE; 7655 } else { 7656 // write operation 7657 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) { 7658 KdPrint2((PRINT_PREFIX "dma RO\n")); 7659 use_dma = FALSE; 7660 } else { 7661 use_dma = TRUE; 7662 } 7663 } 7664 } 7665 break; 7666 } 7667 // try setup DMA 7668 setup_dma: 7669 if(use_dma) { 7670 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7671 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n")); 7672 //use_dma = TRUE; 7673 } else 7674 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 7675 (PUCHAR)(AtaReq->DataBuffer), 7676 Srb->DataTransferLength)) { 7677 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma\n")); 7678 use_dma = FALSE; 7679 } else { 7680 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n")); 7681 } 7682 } 7683 } else { 7684 KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero/unaligned transfer %x, no DMA setup\n", AtaReq->TransferLength)); 7685 } 7686 7687 7688 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7689 7690 UniataAhciSetupCmdPtr(AtaReq); 7691 7692 if(!Srb->DataTransferLength) { 7693 KdPrint2((PRINT_PREFIX "zero-transfer\n")); 7694 use_dma = FALSE; 7695 } else 7696 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 7697 (PUCHAR)(AtaReq->DataBuffer), 7698 Srb->DataTransferLength)) { 7699 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no AHCI dma!\n")); 7700 return SRB_STATUS_ERROR; 7701 } 7702 if(!use_dma) { 7703 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7704 } else { 7705 FeatureReg |= ATA_F_DMA; 7706 if(LunExt->IdentifyData.AtapiDMA.DMADirRequired) { 7707 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 7708 KdPrint2((PRINT_PREFIX "Set DMADir.\n")); 7709 FeatureReg |= ATA_F_DMAREAD; 7710 } 7711 } 7712 } 7713 7714 KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n")); 7715 // this is done in UniataAhciSetupFIS_H2D() 7716 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis)); 7717 RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, Srb->CdbLength); 7718 7719 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel, 7720 &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]), 7721 IDE_COMMAND_ATAPI_PACKET /* command */, 7722 0 /* lba */, 7723 (Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength), 7724 FeatureReg/* feature */ 7725 ); 7726 7727 if(!fis_size) { 7728 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n")); 7729 return SRB_STATUS_ERROR; 7730 } 7731 7732 AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0, 7733 ((Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) ? ATA_AHCI_CMD_WRITE : 0) | 7734 (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH), 7735 fis_size, DeviceNumber); 7736 7737 KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags)); 7738 } 7739 7740 } else { 7741 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) { 7742 // if this is queued request, reinit DMA and check 7743 // if DMA mode is still available 7744 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() (1)\n")); 7745 AtapiDmaReinit(deviceExtension, LunExt, AtaReq); 7746 if (/*EnableDma &&*/ 7747 (LunExt->TransferMode >= ATA_DMA)) { 7748 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (2)\n")); 7749 use_dma = TRUE; 7750 } else { 7751 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7752 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma (2)\n")); 7753 use_dma = FALSE; 7754 } 7755 dma_reinited = TRUE; 7756 } 7757 } 7758 7759 if(!(CmdAction & CMD_ACTION_EXEC)) { 7760 KdPrint2((PRINT_PREFIX "AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n")); 7761 return SRB_STATUS_PENDING; 7762 } 7763 KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma, Srb->Cdb[0])); 7764 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) { 7765 KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n")); 7766 } 7767 7768 if((Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) && !(deviceExtension->HwFlags & UNIATA_SATA)) { 7769 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n")); 7770 use_dma = FALSE; 7771 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7772 AtapiDmaReinit(deviceExtension, LunExt, AtaReq); 7773 } if(AtaReq->TransferLength) { 7774 if(!dma_reinited) { 7775 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()\n")); 7776 AtapiDmaReinit(deviceExtension, LunExt, AtaReq); 7777 if (/*EnableDma &&*/ 7778 (LunExt->TransferMode >= ATA_DMA)) { 7779 use_dma = TRUE; 7780 } else { 7781 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7782 use_dma = FALSE; 7783 } 7784 } 7785 } else { 7786 KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer\n")); 7787 use_dma = FALSE; 7788 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; 7789 if(!deviceExtension->opt_AtapiDmaZeroTransfer && !(deviceExtension->HwFlags & UNIATA_SATA)) { 7790 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() to PIO\n")); 7791 AtapiDmaReinit(deviceExtension, LunExt, AtaReq); 7792 } 7793 } 7794 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma)); 7795 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) { 7796 KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n")); 7797 } 7798 7799 KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_EXEC\n")); 7800 7801 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n", 7802 &(Srb->Cdb), Srb->Cdb[0], Srb->TargetId, Srb->Lun)); 7803 7804 // Make sure command is to ATAPI device. 7805 flags = LunExt->DeviceFlags; 7806 if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) { 7807 if((Srb->Lun) > (LunExt->DiscsPresent - 1)) { 7808 7809 // Indicate no device found at this address. 7810 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7811 return SRB_STATUS_SELECTION_TIMEOUT; 7812 } 7813 } else if(Srb->Lun > 0) { 7814 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7815 return SRB_STATUS_SELECTION_TIMEOUT; 7816 } 7817 7818 if(!(flags & DFLAGS_ATAPI_DEVICE)) { 7819 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7820 return SRB_STATUS_SELECTION_TIMEOUT; 7821 } 7822 retry: 7823 // Select device 0 or 1. Or more for PM 7824 SelectDrive(chan, DeviceNumber); 7825 7826 // Verify that controller is ready for next command. 7827 GetStatus(chan, statusByte); 7828 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte)); 7829 7830 if(statusByte == IDE_STATUS_WRONG) { 7831 KdPrint2((PRINT_PREFIX "AtapiSendCommand: bad status 0xff on entry\n")); 7832 goto make_reset; 7833 } 7834 if(statusByte & IDE_STATUS_BUSY) { 7835 if(statusByte & IDE_STATUS_DSC) { 7836 KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte)); 7837 } else { 7838 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte)); 7839 // We have to make reset here, since we are expecting device to be available 7840 //return SRB_STATUS_BUSY; // this cause queue freeze 7841 goto make_reset; 7842 } 7843 } 7844 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7845 ULONG CI; 7846 // Check if command list is free 7847 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI); 7848 if(CI) { 7849 // controller is busy, however we expect it to be free 7850 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI)); 7851 goto make_reset; 7852 } 7853 } 7854 if(statusByte & IDE_STATUS_ERROR) { 7855 if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) { 7856 7857 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on entry: (%#x)\n", statusByte)); 7858 // Read the error reg. to clear it and fail this request. 7859 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7860 return MapError(deviceExtension, Srb); 7861 } else { 7862 KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n", statusByte)); 7863 } 7864 } 7865 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send 7866 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157. 7867 if((!(statusByte & IDE_STATUS_DSC)) && 7868 (flags & (DFLAGS_TAPE_DEVICE | DFLAGS_ATAPI_DEVICE)) && chan->RDP) { 7869 7870 AtapiStallExecution(200); 7871 KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte)); 7872 AtaReq->ReqState = REQ_STATE_QUEUED; 7873 return SRB_STATUS_PENDING; 7874 } 7875 7876 if(IS_RDP(Srb->Cdb[0])) { 7877 chan->RDP = TRUE; 7878 KdPrint2((PRINT_PREFIX "AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb->Cdb[0])); 7879 } else { 7880 chan->RDP = FALSE; 7881 } 7882 if(statusByte & IDE_STATUS_DRQ) { 7883 7884 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n", 7885 statusByte)); 7886 // Try to drain the data that one preliminary device thinks that it has 7887 // to transfer. Hopefully this random assertion of DRQ will not be present 7888 // in production devices. 7889 statusByte = AtapiSuckPort2(chan); 7890 /* 7891 for (i = 0; i < 0x10000; i++) { 7892 GetStatus(chan, statusByte); 7893 if(statusByte & IDE_STATUS_DRQ) { 7894 AtapiReadPort2(chan, IDX_IO1_i_Data); 7895 } else { 7896 break; 7897 } 7898 } 7899 */ 7900 if (statusByte & IDE_STATUS_DRQ) { 7901 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted. Status (%#x)\n", statusByte)); 7902 make_reset: 7903 AtapiDisableInterrupts(deviceExtension, lChannel); 7904 7905 AtapiSoftReset(chan, DeviceNumber); 7906 7907 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Issued soft reset to Atapi device. \n")); 7908 // Re-initialize Atapi device. 7909 CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), DeviceNumber, TRUE); 7910 /* 7911 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb), 7912 IDE_COMMAND_ATAPI_IDENTIFY, FALSE); 7913 */ 7914 // Inform the port driver that the bus has been reset. 7915 ScsiPortNotification(ResetDetected, HwDeviceExtension, 0); 7916 // Clean up device extension fields that AtapiStartIo won't. 7917 UniataExpectChannelInterrupt(chan, FALSE); 7918 chan->RDP = FALSE; 7919 InterlockedExchange(&(deviceExtension->chan[GET_CHANNEL(Srb)].CheckIntr), 7920 CHECK_INTR_IDLE); 7921 7922 AtapiEnableInterrupts(deviceExtension, lChannel); 7923 /* 7924 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7925 return SRB_STATUS_BUS_RESET; 7926 */ 7927 if(!retried) { 7928 KdPrint3((PRINT_PREFIX "AtapiSendCommand: retry after reset.\n")); 7929 retried = TRUE; 7930 goto retry; 7931 } 7932 KdPrint3((PRINT_PREFIX "AtapiSendCommand: selection timeout.\n")); 7933 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 7934 return SRB_STATUS_SELECTION_TIMEOUT; 7935 } 7936 } 7937 7938 if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) { 7939 // As the cdrom driver sets the LUN field in the cdb, it must be removed. 7940 Srb->Cdb[1] &= ~0xE0; 7941 if((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) { 7942 // Torisan changer. TUR's are overloaded to be platter switches. 7943 Srb->Cdb[7] = Srb->Lun; 7944 } 7945 } 7946 7947 // SETUP DMA !!!!! 7948 7949 if(use_dma) { 7950 chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION; 7951 } else { 7952 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; 7953 } 7954 7955 if(deviceExtension->HwFlags & UNIATA_AHCI) { 7956 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n")); 7957 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling 7958 UniataExpectChannelInterrupt(chan, TRUE); 7959 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 7960 return SRB_STATUS_PENDING; 7961 } 7962 7963 statusByte = WaitOnBusy(chan); 7964 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n", 7965 statusByte)); 7966 7967 if(use_dma) { 7968 FeatureReg |= ATA_F_DMA; 7969 if(LunExt->IdentifyData.AtapiDMA.DMADirRequired) { 7970 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 7971 FeatureReg |= ATA_F_DMAREAD; 7972 } 7973 } 7974 } 7975 7976 // Write transfer byte count to registers. 7977 if (Srb->DataTransferLength >= 0x10000) { 7978 byteCountLow = byteCountHigh = 0xFF; 7979 } else { 7980 byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF); 7981 byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8); 7982 } 7983 7984 KdPrint3((PRINT_PREFIX "AtapiSendCommand: F:%#x, CntHL:%#x:%#x.\n", FeatureReg, byteCountHigh, byteCountLow)); 7985 7986 if (flags & DFLAGS_INT_DRQ) { 7987 // This device interrupts when ready to receive the packet. 7988 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n", 7989 statusByte)); 7990 7991 UniataExpectChannelInterrupt(chan, TRUE); 7992 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR; 7993 InterlockedExchange(&(chan->CheckIntr), 7994 CHECK_INTR_IDLE); 7995 // inform driver that packet command must be sent in ISR 7996 flags |= DFLAGS_INT_DRQ; 7997 } else { 7998 // This device quickly sets DRQ when ready to receive the packet. 7999 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n", 8000 statusByte)); 8001 8002 UniataExpectChannelInterrupt(chan, TRUE); 8003 AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR; 8004 InterlockedExchange(&(chan->CheckIntr), 8005 CHECK_INTR_IDLE); 8006 8007 if(g_opt_AtapiSendDisableIntr) { 8008 AtapiDisableInterrupts(deviceExtension, lChannel); 8009 } 8010 // remember status. Later we may check if error appeared after cmd packet 8011 statusByte0 = statusByte; 8012 } 8013 8014 // must be already selected, experimental for ROS BUG-9119 8015 //AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) ); 8016 AtapiWritePort1(chan, IDX_IO2_o_Control , 0); 8017 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Feature /*IDX_IO1_o_Feature*/, FeatureReg); 8018 //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused0, 0); // experimental for ROS BUG-9119 8019 //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused1, 0); // experimental for ROS BUG-9119 8020 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow); 8021 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh); 8022 // Write ATAPI packet command. 8023 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Command /*IDX_IO1_o_Command*/, IDE_COMMAND_ATAPI_PACKET); 8024 8025 if (flags & DFLAGS_INT_DRQ) { 8026 // Wait for interrupt and send PACKET there 8027 KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n")); 8028 return SRB_STATUS_PENDING; 8029 } 8030 8031 WaitOnBusy(chan); 8032 /* 8033 // Wait for DRQ. 8034 statusByte = WaitForDrq(chan); 8035 8036 // Need to read status register and clear interrupt (if any) 8037 GetBaseStatus(chan, statusByte); 8038 8039 if (!(statusByte & IDE_STATUS_DRQ)) { 8040 if(g_opt_AtapiSendDisableIntr) { 8041 AtapiEnableInterrupts(deviceExtension, lChannel); 8042 } 8043 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte)); 8044 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 8045 return SRB_STATUS_ERROR; 8046 } 8047 */ 8048 GetStatus(chan, statusByte); 8049 KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte)); 8050 8051 //statusByte = WaitOnBaseBusy(chan); 8052 8053 // Indicate expecting an interrupt and wait for it. 8054 UniataExpectChannelInterrupt(chan, TRUE); 8055 8056 for(i=0; i<5000; i++) { 8057 if(g_opt_AtapiSendDisableIntr) { 8058 GetStatus(chan, statusByte); 8059 } else { 8060 GetBaseStatus(chan, statusByte); 8061 } 8062 interruptReason = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason); 8063 //KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i)); 8064 if(((interruptReason & ATAPI_IR_COD) == ATAPI_IR_COD_Cmd) && 8065 (((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) == IDE_STATUS_DRQ))) { 8066 break; 8067 } 8068 AtapiStallExecution(g_opt_WaitDrqDelay*2); 8069 #ifdef _DEBUG 8070 // KdPrint3((PRINT_PREFIX "AtapiSendCommand: wait CoD, status (%#x)\n", interruptReason)); 8071 #endif // _DEBUG 8072 } 8073 if(((interruptReason & ATAPI_IR_COD) != ATAPI_IR_COD_Cmd) || 8074 (((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) != IDE_STATUS_DRQ)) ) { 8075 KdPrint3((PRINT_PREFIX "AtapiSendCommand: no CoD raised, abort cmd\n")); 8076 KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i)); 8077 KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte)); 8078 if(g_opt_AtapiSendDisableIntr) { 8079 AtapiEnableInterrupts(deviceExtension, lChannel); 8080 } 8081 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ+CoD never asserted\n")); 8082 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 8083 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte)); 8084 if(statusByte >> 4) { 8085 GetBaseStatus(chan, statusByte); 8086 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 8087 return MapError(deviceExtension, Srb); 8088 } 8089 goto make_reset; 8090 // AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 8091 // return SRB_STATUS_ERROR; 8092 } else { 8093 KdPrint3((PRINT_PREFIX "AtapiSendCommand: ready for packet, status %#x, i=%d\n", interruptReason, i)); 8094 } 8095 // clear interrupt 8096 GetBaseStatus(chan, statusByte); 8097 8098 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) { 8099 AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb); 8100 } 8101 if(g_opt_AtapiSendDisableIntr) { 8102 AtapiEnableInterrupts(deviceExtension, lChannel); 8103 } 8104 8105 // Send CDB to device. 8106 WriteBuffer(chan, 8107 (PUSHORT)Srb->Cdb, 8108 LunExt->IdentifyData.AtapiCmdSize ? 8 : 6, 8109 /*0*/ PIO0_TIMING); 8110 8111 GetStatus(chan, statusByte); 8112 KdPrint3((PRINT_PREFIX "AtapiSendCommand: cmd status (%#x)\n", statusByte)); 8113 8114 // When we operate in DMA mode, we should not start transfer when there is an error on entry 8115 // Interrupt may never come in such case. 8116 if(statusByte & IDE_STATUS_ERROR) { 8117 8118 GetBaseStatus(chan, statusByte); 8119 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on cmd: (%#x)\n", statusByte)); 8120 8121 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); 8122 KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x\n", interruptReason)); 8123 8124 // TODO: we should check interruptReason and decide what to do now 8125 8126 // Read the error reg. to clear it and fail this request. 8127 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 8128 return MapError(deviceExtension, Srb); 8129 } 8130 if(statusByte & IDE_STATUS_DRQ) { 8131 // Some devices require this. If error condition is not checked in such a way, 8132 // device may not operate correctly and would be treated as failed 8133 // (and finally invisible for OS) 8134 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ on cmd: (%#x)\n", statusByte)); 8135 // Read the error reg. to clear it and fail this request. 8136 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 8137 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte)); 8138 if(statusByte >> 4) { 8139 GetBaseStatus(chan, statusByte); 8140 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 8141 return MapError(deviceExtension, Srb); 8142 } 8143 } 8144 8145 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) { 8146 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); 8147 } 8148 8149 InterlockedExchange(&(chan->CheckIntr), 8150 CHECK_INTR_IDLE); 8151 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR; 8152 8153 KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt)); 8154 8155 KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (3)\n")); 8156 return SRB_STATUS_PENDING; 8157 8158 } // end AtapiSendCommand() 8159 8160 8161 #ifndef UNIATA_CORE 8162 8163 /*++ 8164 8165 Routine Description: 8166 Program ATA registers for IDE disk transfer. 8167 8168 Arguments: 8169 HwDeviceExtension - ATAPI driver storage. 8170 Srb - System request block. 8171 8172 Return Value: 8173 SRB status (pending if all goes well). 8174 8175 --*/ 8176 8177 #ifdef _DEBUG 8178 ULONG check_point = 0; 8179 #define SetCheckPoint(cp) { check_point = (cp) ; } 8180 #else 8181 #define SetCheckPoint(cp) 8182 #endif 8183 8184 ULONG 8185 NTAPI 8186 IdeSendCommand( 8187 IN PVOID HwDeviceExtension, 8188 IN PSCSI_REQUEST_BLOCK Srb, 8189 IN ULONG CmdAction 8190 ) 8191 { 8192 SetCheckPoint(1); 8193 KdPrint2((PRINT_PREFIX "** Ide: Command: entryway\n")); 8194 SetCheckPoint(2); 8195 8196 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 8197 SetCheckPoint(3); 8198 UCHAR lChannel; 8199 PHW_CHANNEL chan; 8200 PCDB cdb; 8201 PHW_LU_EXTENSION LunExt; 8202 8203 SetCheckPoint(4); 8204 8205 UCHAR statusByte,errorByte; 8206 ULONG status = SRB_STATUS_INVALID_REQUEST; 8207 ULONG i; 8208 ULONGLONG lba; 8209 PMODE_PARAMETER_HEADER modeData; 8210 //ULONG ldev; 8211 ULONG DeviceNumber; 8212 PATA_REQ AtaReq; 8213 UCHAR command; 8214 8215 SetCheckPoint(5); 8216 //ULONG __ebp__ = 0; 8217 8218 SetCheckPoint(0x20); 8219 KdPrint2((PRINT_PREFIX "** Ide: Command:\n\n")); 8220 /* __asm { 8221 mov eax,ebp 8222 mov __ebp__, eax 8223 }*/ 8224 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n", 8225 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0])); 8226 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n", 8227 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : "")); 8228 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n", 8229 Srb)); 8230 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n", 8231 Srb->SrbExtension)); 8232 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n", 8233 Srb->TargetId));*/ 8234 8235 SetCheckPoint(0x30); 8236 AtaReq = (PATA_REQ)(Srb->SrbExtension); 8237 8238 KdPrint2((PRINT_PREFIX "** Ide: Command &AtaReq %#x\n", 8239 &AtaReq)); 8240 KdPrint2((PRINT_PREFIX "** Ide: Command AtaReq %#x\n", 8241 AtaReq)); 8242 KdPrint2((PRINT_PREFIX "** --- **\n")); 8243 8244 lChannel = GET_CHANNEL(Srb); 8245 chan = &(deviceExtension->chan[lChannel]); 8246 //ldev = GET_LDEV(Srb); 8247 DeviceNumber = GET_CDEV(Srb); 8248 LunExt = chan->lun[DeviceNumber]; 8249 8250 SetCheckPoint(0x40); 8251 if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER) 8252 AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER; 8253 8254 cdb = (PCDB)(Srb->Cdb); 8255 8256 if(CmdAction == CMD_ACTION_PREPARE) { 8257 switch (Srb->Cdb[0]) { 8258 case SCSIOP_SERVICE_ACTION16: 8259 if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) { 8260 // ok 8261 } else { 8262 goto default_no_prep; 8263 } 8264 #ifdef NAVO_TEST 8265 case SCSIOP_INQUIRY: // now it requires device access 8266 #endif //NAVO_TEST 8267 case SCSIOP_READ_CAPACITY: 8268 case SCSIOP_READ: 8269 case SCSIOP_WRITE: 8270 case SCSIOP_READ12: 8271 case SCSIOP_WRITE12: 8272 case SCSIOP_READ16: 8273 case SCSIOP_WRITE16: 8274 case SCSIOP_REQUEST_SENSE: 8275 // all right 8276 KdPrint2((PRINT_PREFIX "** Ide: Command continue prep\n")); 8277 SetCheckPoint(50); 8278 break; 8279 default: 8280 default_no_prep: 8281 SetCheckPoint(0); 8282 KdPrint2((PRINT_PREFIX "** Ide: Command break prep\n")); 8283 return SRB_STATUS_BUSY; 8284 } 8285 } 8286 8287 SetCheckPoint(0x100 | Srb->Cdb[0]); 8288 switch (Srb->Cdb[0]) { 8289 case SCSIOP_INQUIRY: 8290 8291 KdPrint2((PRINT_PREFIX 8292 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n", 8293 Srb->PathId, Srb->Lun, Srb->TargetId)); 8294 // Filter out wrong TIDs. 8295 if ((Srb->Lun != 0) || 8296 (Srb->PathId >= deviceExtension->NumberChannels) || 8297 (Srb->TargetId >= deviceExtension->NumberLuns)) { 8298 8299 KdPrint2((PRINT_PREFIX 8300 "IdeSendCommand: SCSIOP_INQUIRY rejected\n")); 8301 // Indicate no device found at this address. 8302 status = SRB_STATUS_SELECTION_TIMEOUT; 8303 break; 8304 8305 } else { 8306 8307 KdPrint2((PRINT_PREFIX 8308 "IdeSendCommand: SCSIOP_INQUIRY ok\n")); 8309 PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer); 8310 PIDENTIFY_DATA2 identifyData = &(LunExt->IdentifyData); 8311 8312 if (!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 8313 8314 if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) { 8315 KdPrint2((PRINT_PREFIX 8316 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n")); 8317 // Indicate no device found at this address. 8318 #ifndef NAVO_TEST 8319 status = SRB_STATUS_SELECTION_TIMEOUT; 8320 break; 8321 } 8322 } else { 8323 if(!UniataAnybodyHome(HwDeviceExtension, lChannel, DeviceNumber)) { 8324 KdPrint2((PRINT_PREFIX 8325 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n")); 8326 // Indicate no device found at this address. 8327 UniataForgetDevice(chan->lun[DeviceNumber]); 8328 #endif //NAVO_TEST 8329 status = SRB_STATUS_SELECTION_TIMEOUT; 8330 break; 8331 } 8332 } 8333 8334 // Zero INQUIRY data structure. 8335 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength); 8336 8337 // Standard IDE interface only supports disks. 8338 inquiryData->DeviceType = DIRECT_ACCESS_DEVICE; 8339 8340 // Set the removable bit, if applicable. 8341 if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) { 8342 KdPrint2((PRINT_PREFIX 8343 "RemovableMedia\n")); 8344 inquiryData->RemovableMedia = 1; 8345 } 8346 // Set the Relative Addressing (LBA) bit, if applicable. 8347 if (LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) { 8348 inquiryData->RelativeAddressing = 1; 8349 KdPrint2((PRINT_PREFIX 8350 "RelativeAddressing\n")); 8351 } 8352 // Set the CommandQueue bit 8353 inquiryData->CommandQueue = 1; 8354 8355 // Fill in vendor identification fields. 8356 for (i = 0; i < 24; i += 2) { 8357 MOV_DW_SWP(inquiryData->DeviceIdentificationString[i], ((PUCHAR)identifyData->ModelNumber)[i]); 8358 } 8359 /* 8360 // Initialize unused portion of product id. 8361 for (i = 0; i < 4; i++) { 8362 inquiryData->ProductId[12+i] = ' '; 8363 } 8364 */ 8365 // Move firmware revision from IDENTIFY data to 8366 // product revision in INQUIRY data. 8367 for (i = 0; i < 4; i += 2) { 8368 MOV_DW_SWP(inquiryData->ProductRevisionLevel[i], ((PUCHAR)identifyData->FirmwareRevision)[i]); 8369 } 8370 8371 status = SRB_STATUS_SUCCESS; 8372 } 8373 8374 break; 8375 8376 case SCSIOP_REPORT_LUNS: { 8377 8378 ULONG alen; 8379 PREPORT_LUNS_INFO_HDR LunInfo; 8380 8381 KdPrint2((PRINT_PREFIX 8382 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n", 8383 Srb->PathId, Srb->Lun, Srb->TargetId)); 8384 8385 MOV_DD_SWP(alen, cdb->REPORT_LUNS.AllocationLength); 8386 8387 if(alen < 16) { 8388 goto invalid_cdb; 8389 } 8390 alen = 8; 8391 8392 LunInfo = (PREPORT_LUNS_INFO_HDR)(Srb->DataBuffer); 8393 RtlZeroMemory(LunInfo, 16); 8394 8395 MOV_DD_SWP( LunInfo->ListLength, alen ); 8396 Srb->DataTransferLength = 16; 8397 status = SRB_STATUS_SUCCESS; 8398 8399 break; } 8400 8401 case SCSIOP_MODE_SENSE: 8402 8403 KdPrint2((PRINT_PREFIX 8404 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n", 8405 Srb->PathId, Srb->Lun, Srb->TargetId)); 8406 8407 if(cdb->MODE_SENSE.PageCode == MODE_PAGE_POWER_CONDITION) { 8408 PMODE_POWER_CONDITION_PAGE modeData; 8409 8410 KdPrint2((PRINT_PREFIX "MODE_PAGE_POWER_CONDITION\n")); 8411 modeData = (PMODE_POWER_CONDITION_PAGE)(Srb->DataBuffer); 8412 if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_POWER_CONDITION_PAGE)) { 8413 status = SRB_STATUS_DATA_OVERRUN; 8414 } else { 8415 RtlZeroMemory(modeData, sizeof(MODE_POWER_CONDITION_PAGE)); 8416 modeData->PageCode = MODE_PAGE_POWER_CONDITION; 8417 #ifdef __REACTOS__ 8418 modeData->PageLength = sizeof(MODE_POWER_CONDITION_PAGE)-sizeof(MODE_PARAMETER_HEADER); 8419 #else 8420 modeData->PageLength = sizeof(MODE_PAGE_POWER_CONDITION)-sizeof(MODE_PARAMETER_HEADER); 8421 #endif 8422 modeData->Byte3.Fields.Idle = LunExt->PowerState <= StartStop_Power_Idle; 8423 modeData->Byte3.Fields.Standby = LunExt->PowerState == StartStop_Power_Standby; 8424 Srb->DataTransferLength = sizeof(MODE_POWER_CONDITION_PAGE); 8425 status = SRB_STATUS_SUCCESS; 8426 } 8427 } else 8428 if(cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) { 8429 PMODE_CACHING_PAGE modeData; 8430 8431 KdPrint2((PRINT_PREFIX "MODE_PAGE_CACHING\n")); 8432 modeData = (PMODE_CACHING_PAGE)(Srb->DataBuffer); 8433 if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) { 8434 status = SRB_STATUS_DATA_OVERRUN; 8435 } else { 8436 RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE)); 8437 modeData->PageCode = MODE_PAGE_CACHING; 8438 modeData->PageLength = sizeof(MODE_CACHING_PAGE)-sizeof(MODE_PARAMETER_HEADER); 8439 modeData->ReadDisableCache = (LunExt->DeviceFlags & DFLAGS_RCACHE_ENABLED) ? 0 : 1; 8440 modeData->WriteCacheEnable = (LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) ? 1 : 0; 8441 Srb->DataTransferLength = sizeof(MODE_CACHING_PAGE); 8442 status = SRB_STATUS_SUCCESS; 8443 } 8444 } else 8445 if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { 8446 8447 // This is used to determine if the media is write-protected. 8448 // Since IDE does not support mode sense then we will modify just the portion we need 8449 // so the higher level driver can determine if media is protected. 8450 8451 //SelectDrive(chan, DeviceNumber); 8452 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS); 8453 //statusByte = WaitOnBusy(chan); 8454 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY); 8455 8456 if (!(statusByte & IDE_STATUS_ERROR)) { 8457 8458 // no error occured return success, media is not protected 8459 UniataExpectChannelInterrupt(chan, FALSE); 8460 InterlockedExchange(&(chan->CheckIntr), 8461 CHECK_INTR_IDLE); 8462 status = SRB_STATUS_SUCCESS; 8463 8464 } else { 8465 8466 // error occured, handle it locally, clear interrupt 8467 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 8468 8469 GetBaseStatus(chan, statusByte); 8470 UniataExpectChannelInterrupt(chan, FALSE); 8471 InterlockedExchange(&(chan->CheckIntr), 8472 CHECK_INTR_IDLE); 8473 status = SRB_STATUS_SUCCESS; 8474 8475 if (errorByte & IDE_ERROR_DATA_ERROR) { 8476 8477 //media is write-protected, set bit in mode sense buffer 8478 modeData = (PMODE_PARAMETER_HEADER)Srb->DataBuffer; 8479 8480 Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER); 8481 modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; 8482 } 8483 } 8484 status = SRB_STATUS_SUCCESS; 8485 } else { 8486 status = SRB_STATUS_INVALID_REQUEST; 8487 } 8488 break; 8489 8490 case SCSIOP_TEST_UNIT_READY: 8491 8492 KdPrint2((PRINT_PREFIX 8493 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n", 8494 Srb->PathId, Srb->Lun, Srb->TargetId)); 8495 if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { 8496 8497 // Select device 0 or 1. 8498 //SelectDrive(chan, DeviceNumber); 8499 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS); 8500 // Wait for busy. If media has not changed, return success 8501 //statusByte = WaitOnBusy(chan); 8502 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY); 8503 8504 if (!(statusByte & IDE_STATUS_ERROR)){ 8505 UniataExpectChannelInterrupt(chan, FALSE); 8506 InterlockedExchange(&(chan->CheckIntr), 8507 CHECK_INTR_IDLE); 8508 status = SRB_STATUS_SUCCESS; 8509 } else { 8510 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 8511 if (errorByte == IDE_ERROR_DATA_ERROR){ 8512 8513 // Special case: If current media is write-protected, 8514 // the 0xDA command will always fail since the write-protect bit 8515 // is sticky,so we can ignore this error 8516 GetBaseStatus(chan, statusByte); 8517 UniataExpectChannelInterrupt(chan, FALSE); 8518 InterlockedExchange(&(chan->CheckIntr), 8519 CHECK_INTR_IDLE); 8520 status = SRB_STATUS_SUCCESS; 8521 8522 } else { 8523 8524 // Request sense buffer to be build 8525 UniataExpectChannelInterrupt(chan, TRUE); 8526 InterlockedExchange(&(chan->CheckIntr), 8527 CHECK_INTR_IDLE); 8528 status = SRB_STATUS_PENDING; 8529 } 8530 } 8531 } else { 8532 status = SRB_STATUS_SUCCESS; 8533 } 8534 8535 break; 8536 8537 case SCSIOP_READ_CAPACITY: 8538 8539 KdPrint2((PRINT_PREFIX 8540 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n", 8541 Srb->PathId, Srb->Lun, Srb->TargetId)); 8542 // Claim 512 byte blocks (big-endian). 8543 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000; 8544 i = DEV_BSIZE; 8545 RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY_DATA)); 8546 MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i ); 8547 8548 // Calculate last sector. 8549 if(!(i = (ULONG)LunExt->NumOfSectors)) { 8550 i = LunExt->IdentifyData.SectorsPerTrack * 8551 LunExt->IdentifyData.NumberOfHeads * 8552 LunExt->IdentifyData.NumberOfCylinders; 8553 } 8554 i--; 8555 8556 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress = 8557 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) | 8558 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3]; 8559 8560 MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress, i ); 8561 8562 KdPrint2((PRINT_PREFIX 8563 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n", 8564 Srb->TargetId, 8565 LunExt->IdentifyData.SectorsPerTrack, 8566 LunExt->IdentifyData.NumberOfHeads, 8567 LunExt->IdentifyData.NumberOfCylinders)); 8568 8569 8570 status = SRB_STATUS_SUCCESS; 8571 break; 8572 8573 case SCSIOP_SERVICE_ACTION16: 8574 8575 if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) { 8576 KdPrint2((PRINT_PREFIX 8577 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n", 8578 Srb->PathId, Srb->Lun, Srb->TargetId)); 8579 // Claim 512 byte blocks (big-endian). 8580 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000; 8581 i = DEV_BSIZE; 8582 RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY16_DATA)); 8583 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->BytesPerBlock, i ); 8584 8585 // Calculate last sector. 8586 if(!(lba = LunExt->NumOfSectors)) { 8587 lba = LunExt->IdentifyData.SectorsPerTrack * 8588 LunExt->IdentifyData.NumberOfHeads * 8589 LunExt->IdentifyData.NumberOfCylinders; 8590 } 8591 lba--; 8592 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->LogicalBlockAddress, lba ); 8593 8594 KdPrint2((PRINT_PREFIX 8595 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n", 8596 Srb->TargetId, 8597 LunExt->IdentifyData.SectorsPerTrack, 8598 LunExt->IdentifyData.NumberOfHeads, 8599 LunExt->IdentifyData.NumberOfCylinders)); 8600 8601 status = SRB_STATUS_SUCCESS; 8602 } else { 8603 goto default_abort; 8604 } 8605 break; 8606 8607 case SCSIOP_VERIFY: 8608 case SCSIOP_VERIFY12: 8609 case SCSIOP_VERIFY16: 8610 8611 KdPrint2((PRINT_PREFIX 8612 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n", 8613 Srb->PathId, Srb->Lun, Srb->TargetId)); 8614 status = IdeVerify(HwDeviceExtension,Srb); 8615 8616 break; 8617 8618 case SCSIOP_READ: 8619 case SCSIOP_WRITE: 8620 case SCSIOP_READ12: 8621 case SCSIOP_WRITE12: 8622 case SCSIOP_READ16: 8623 case SCSIOP_WRITE16: 8624 8625 KdPrint2((PRINT_PREFIX 8626 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n", 8627 (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ", 8628 Srb->PathId, Srb->Lun, Srb->TargetId)); 8629 AtaReq->Flags &= ~REQ_FLAG_RW_MASK; 8630 AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE || 8631 Srb->Cdb[0] == SCSIOP_WRITE12 || 8632 Srb->Cdb[0] == SCSIOP_WRITE16) ? REQ_FLAG_WRITE : REQ_FLAG_READ; 8633 status = IdeReadWrite(HwDeviceExtension, 8634 Srb, CmdAction); 8635 break; 8636 8637 case SCSIOP_START_STOP_UNIT: 8638 8639 KdPrint2((PRINT_PREFIX 8640 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n", 8641 cdb->START_STOP.Immediate, Srb->PathId, Srb->Lun, Srb->TargetId)); 8642 //Determine what type of operation we should perform 8643 8644 command = 0; 8645 8646 if(cdb->START_STOP.FL || 8647 cdb->START_STOP.FormatLayerNumber || 8648 cdb->START_STOP.Reserved2 || 8649 cdb->START_STOP.Reserved2_2 || 8650 cdb->START_STOP.Reserved3 || 8651 FALSE) { 8652 goto invalid_cdb; 8653 } 8654 8655 if (cdb->START_STOP.PowerConditions) { 8656 KdPrint2((PRINT_PREFIX "START_STOP Power %d\n", cdb->START_STOP.PowerConditions)); 8657 switch(cdb->START_STOP.PowerConditions) { 8658 case StartStop_Power_Idle: 8659 command = IDE_COMMAND_IDLE_IMMED; 8660 break; 8661 case StartStop_Power_Standby: 8662 command = IDE_COMMAND_STANDBY_IMMED; 8663 break; 8664 case StartStop_Power_Sleep: 8665 // TODO: we should save power state in order to know 8666 // that RESET sould be issued to revert device into 8667 // operable state 8668 8669 command = IDE_COMMAND_SLEEP; 8670 break; 8671 default: 8672 goto invalid_cdb; 8673 } 8674 LunExt->PowerState = cdb->START_STOP.PowerConditions; 8675 } else 8676 if (cdb->START_STOP.LoadEject == 1) { 8677 KdPrint2((PRINT_PREFIX "START_STOP eject\n")); 8678 // Eject media, 8679 // first select device 0 or 1. 8680 //SelectDrive(chan, DeviceNumber); 8681 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT); 8682 command = IDE_COMMAND_MEDIA_EJECT; 8683 } else 8684 if (cdb->START_STOP.Start == 0) { 8685 KdPrint2((PRINT_PREFIX "START_STOP standby\n")); 8686 command = IDE_COMMAND_STANDBY_IMMED; 8687 } else { 8688 // TODO: we may need to perform hard reset (after sleep) or 8689 // issue IDE_COMMAND_IDLE_IMMED in order to activate device 8690 KdPrint2((PRINT_PREFIX "START_STOP activate\n")); 8691 8692 if(LunExt->PowerState == StartStop_Power_Sleep) { 8693 UniataUserDeviceReset(deviceExtension, LunExt, lChannel); 8694 status = SRB_STATUS_SUCCESS; 8695 break; 8696 } else 8697 if(LunExt->PowerState > StartStop_Power_Idle) { 8698 KdPrint2((PRINT_PREFIX " issue IDLE\n")); 8699 command = IDE_COMMAND_IDLE_IMMED; 8700 } else { 8701 KdPrint2((PRINT_PREFIX " do nothing\n")); 8702 status = SRB_STATUS_SUCCESS; 8703 break; 8704 } 8705 } 8706 if(command) { 8707 statusByte = WaitOnBaseBusy(chan); 8708 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, command, 0, 0, 0, 0, 0, 8709 cdb->START_STOP.Immediate ? ATA_IMMEDIATE : ATA_WAIT_READY); 8710 status = (statusByte & IDE_STATUS_ERROR) ? SRB_STATUS_ERROR : SRB_STATUS_SUCCESS; 8711 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt 8712 8713 } else { 8714 invalid_cdb: 8715 KdPrint2((PRINT_PREFIX "START_STOP invalid\n")); 8716 if (Srb->SenseInfoBuffer) { 8717 8718 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 8719 8720 senseBuffer->ErrorCode = 0x70; 8721 senseBuffer->Valid = 1; 8722 senseBuffer->AdditionalSenseLength = 0xb; 8723 senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST; 8724 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_CDB; 8725 senseBuffer->AdditionalSenseCodeQualifier = 0; 8726 8727 Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID; 8728 Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; 8729 } 8730 status = SRB_STATUS_ERROR; 8731 } 8732 break; 8733 8734 case SCSIOP_MEDIUM_REMOVAL: 8735 8736 cdb = (PCDB)Srb->Cdb; 8737 8738 if(LunExt->IdentifyData.Removable) { 8739 statusByte = WaitOnBaseBusy(chan); 8740 8741 //SelectDrive(chan, DeviceNumber); 8742 if (cdb->MEDIA_REMOVAL.Prevent == TRUE) { 8743 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK); 8744 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_LOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE); 8745 } else { 8746 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK); 8747 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_UNLOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE); 8748 } 8749 status = SRB_STATUS_SUCCESS; 8750 } else { 8751 status = SRB_STATUS_INVALID_REQUEST; 8752 } 8753 break; 8754 8755 #if 0 8756 // Note: I don't implement this, because NTFS driver too often issues this command 8757 // It causes awful performance degrade. However, if somebody wants, I will implement 8758 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally. 8759 case SCSIOP_FLUSH_BUFFER: 8760 case SCSIOP_SYNCHRONIZE_CACHE: 8761 8762 SelectDrive(chan, DeviceNumber); 8763 AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_FLUSH_CACHE); 8764 status = SRB_STATUS_SUCCESS; 8765 // status = SRB_STATUS_PENDING; 8766 statusByte = WaitOnBusy(chan); 8767 break; 8768 #endif 8769 8770 case SCSIOP_REQUEST_SENSE: 8771 // this function makes sense buffers to report the results 8772 // of the original GET_MEDIA_STATUS command 8773 8774 KdPrint2((PRINT_PREFIX 8775 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n", 8776 Srb->PathId, Srb->Lun, Srb->TargetId)); 8777 if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { 8778 status = IdeBuildSenseBuffer(HwDeviceExtension,Srb); 8779 break; 8780 } 8781 status = SRB_STATUS_INVALID_REQUEST; 8782 break; 8783 8784 // ATA_PASSTHORUGH 8785 case SCSIOP_ATA_PASSTHROUGH: 8786 { 8787 PIDEREGS_EX regs; 8788 BOOLEAN use_dma = FALSE; 8789 ULONG to_lim; 8790 8791 regs = (PIDEREGS_EX) &(Srb->Cdb[2]); 8792 8793 if(chan->DeviceExtension->HwFlags & UNIATA_SATA) { 8794 //lChannel = Srb->TargetId >> 1; 8795 } else { 8796 DeviceNumber = max(DeviceNumber, 1); 8797 regs->bDriveHeadReg &= 0x0f; 8798 regs->bDriveHeadReg |= (UCHAR) (((DeviceNumber & 0x1) << 4) | 0xA0); 8799 } 8800 8801 if((regs->bOpFlags & 1) == 0) { // execute ATA command 8802 8803 KdPrint2((PRINT_PREFIX 8804 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n", 8805 Srb->PathId, Srb->Lun, Srb->TargetId)); 8806 8807 if((regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) == UNIATA_SPTI_EX_SPEC_TO) { 8808 to_lim = Srb->TimeOutValue; 8809 } else { 8810 if(Srb->TimeOutValue <= 2) { 8811 to_lim = Srb->TimeOutValue*900; 8812 } else { 8813 to_lim = (Srb->TimeOutValue*999) - 500; 8814 } 8815 } 8816 8817 AtapiDisableInterrupts(deviceExtension, lChannel); 8818 8819 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { 8820 // AHCI 8821 statusByte = UniataAhciSendPIOCommandDirect( 8822 deviceExtension, 8823 lChannel, 8824 DeviceNumber, 8825 Srb, 8826 regs, 8827 ATA_WAIT_INTR, 8828 to_lim 8829 ); 8830 if(statusByte == IDE_STATUS_WRONG) { 8831 goto passthrough_err; 8832 } 8833 if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) { 8834 UniataAhciAbortOperation(chan); 8835 goto passthrough_err; 8836 } 8837 goto passthrough_done; 8838 } 8839 8840 // SATA/PATA 8841 if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) { 8842 if((chan->lun[DeviceNumber]->LimitedTransferMode >= ATA_DMA)) { 8843 use_dma = TRUE; 8844 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success 8845 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, 8846 (PUCHAR)(Srb->DataBuffer), 8847 ((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) { 8848 use_dma = FALSE; 8849 } 8850 } 8851 } 8852 8853 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg); 8854 AtapiStallExecution(10); 8855 if(use_dma) { 8856 AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb); 8857 } 8858 8859 if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command 8860 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg); 8861 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg); 8862 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg); 8863 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg); 8864 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg); 8865 } else { 8866 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesRegH); 8867 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg); 8868 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountRegH); 8869 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg); 8870 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberRegH); 8871 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg); 8872 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowRegH); 8873 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg); 8874 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighRegH); 8875 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg); 8876 } 8877 AtapiWritePort1(chan, IDX_IO1_o_Command, regs->bCommandReg); 8878 8879 if(use_dma) { 8880 GetBaseStatus(chan, statusByte); 8881 if(statusByte & IDE_STATUS_ERROR) { 8882 goto passthrough_err; 8883 } 8884 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); 8885 } 8886 8887 ScsiPortStallExecution(1); // wait for busy to be set 8888 8889 for(i=0; i<to_lim;i+=2) { // 2 msec from WaitOnBaseBusy() 8890 statusByte = WaitOnBaseBusy(chan); // wait for busy to be clear, up to 2 msec 8891 GetBaseStatus(chan, statusByte); 8892 if(statusByte & IDE_STATUS_ERROR) { 8893 break; 8894 } 8895 if(!(statusByte & IDE_STATUS_BUSY)) { 8896 break; 8897 } 8898 } 8899 if(i >= to_lim) { 8900 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) { 8901 //} 8902 AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_NONE); 8903 goto passthrough_err; 8904 } 8905 8906 if(use_dma) { 8907 AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel); 8908 } 8909 AtapiDmaDone(deviceExtension, DeviceNumber, lChannel, NULL); 8910 GetBaseStatus(chan, statusByte); 8911 8912 if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) { 8913 AtapiSuckPort2(chan); 8914 passthrough_err: 8915 if (Srb->SenseInfoBuffer) { 8916 8917 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; 8918 8919 senseBuffer->ErrorCode = 0x70; 8920 senseBuffer->Valid = 1; 8921 senseBuffer->AdditionalSenseLength = 0xb; 8922 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND; 8923 senseBuffer->AdditionalSenseCode = 0; 8924 senseBuffer->AdditionalSenseCodeQualifier = 0; 8925 8926 Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID; 8927 Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; 8928 } 8929 status = SRB_STATUS_ERROR; 8930 } else { 8931 8932 if(!use_dma) { 8933 if (statusByte & IDE_STATUS_DRQ) { 8934 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) { 8935 ReadBuffer(chan, 8936 (PUSHORT) Srb->DataBuffer, 8937 Srb->DataTransferLength / 2, 8938 0); 8939 } else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { 8940 WriteBuffer(chan, 8941 (PUSHORT) Srb->DataBuffer, 8942 Srb->DataTransferLength / 2, 8943 0); 8944 } 8945 } 8946 } 8947 status = SRB_STATUS_SUCCESS; 8948 } 8949 passthrough_done:; 8950 AtapiEnableInterrupts(deviceExtension, lChannel); 8951 8952 } else { // read task register 8953 8954 BOOLEAN use48; 8955 regs = (PIDEREGS_EX) Srb->DataBuffer; 8956 8957 KdPrint2((PRINT_PREFIX 8958 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n", 8959 Srb->PathId, Srb->Lun, Srb->TargetId)); 8960 8961 if((Srb->DataTransferLength >= sizeof(IDEREGS_EX)) && 8962 (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND)) { 8963 use48 = TRUE; 8964 } else 8965 if(Srb->DataTransferLength >= sizeof(IDEREGS)) { 8966 use48 = FALSE; 8967 } else { 8968 KdPrint2((PRINT_PREFIX " buffer too small \n")); 8969 status = SRB_STATUS_DATA_OVERRUN; 8970 break; 8971 } 8972 RtlZeroMemory(regs, use48 ? sizeof(IDEREGS_EX) : sizeof(IDEREGS)); 8973 regs->bOpFlags = use48 ? ATA_FLAGS_48BIT_COMMAND : 0; 8974 UniataSnapAtaRegs(chan, 0, regs); 8975 8976 status = SRB_STATUS_SUCCESS; 8977 } 8978 break; 8979 } 8980 8981 default: 8982 default_abort: 8983 KdPrint2((PRINT_PREFIX 8984 "IdeSendCommand: Unsupported command %#x\n", 8985 Srb->Cdb[0])); 8986 8987 status = SRB_STATUS_INVALID_REQUEST; 8988 8989 } // end switch 8990 8991 if(status == SRB_STATUS_PENDING) { 8992 KdPrint2((PRINT_PREFIX "IdeSendCommand: SRB_STATUS_PENDING\n")); 8993 if(CmdAction & CMD_ACTION_EXEC) { 8994 KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_EXPECTING_INTR\n")); 8995 AtaReq->ReqState = REQ_STATE_EXPECTING_INTR; 8996 } 8997 } else { 8998 KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n")); 8999 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; 9000 } 9001 9002 return status; 9003 9004 } // end IdeSendCommand() 9005 9006 9007 /*++ 9008 9009 Routine Description: 9010 Enables disables media status notification 9011 9012 Arguments: 9013 HwDeviceExtension - ATAPI driver storage. 9014 9015 --*/ 9016 VOID 9017 NTAPI 9018 IdeMediaStatus( 9019 BOOLEAN EnableMSN, 9020 IN PVOID HwDeviceExtension, 9021 IN ULONG lChannel, 9022 IN ULONG DeviceNumber 9023 ) 9024 { 9025 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 9026 PHW_CHANNEL chan; 9027 UCHAR statusByte,errorByte; 9028 9029 chan = &(deviceExtension->chan[lChannel]); 9030 SelectDrive(chan, DeviceNumber); 9031 9032 if (EnableMSN == TRUE){ 9033 9034 // If supported enable Media Status Notification support 9035 if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE)) { 9036 9037 // enable 9038 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, 9039 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 9040 0, ATA_C_F_ENAB_MEDIASTAT, ATA_WAIT_BASE_READY); 9041 9042 if (statusByte & IDE_STATUS_ERROR) { 9043 // Read the error register. 9044 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); 9045 9046 KdPrint2((PRINT_PREFIX 9047 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n", 9048 statusByte, 9049 errorByte)); 9050 } else { 9051 chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_MEDIA_STATUS_ENABLED; 9052 KdPrint2((PRINT_PREFIX "IdeMediaStatus: Media Status Notification Supported\n")); 9053 chan->ReturningMediaStatus = 0; 9054 9055 } 9056 9057 } 9058 } else { // end if EnableMSN == TRUE 9059 9060 // disable if previously enabled 9061 if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)) { 9062 9063 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, 9064 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 9065 0, ATA_C_F_DIS_MEDIASTAT, ATA_WAIT_BASE_READY); 9066 chan->lun[DeviceNumber]->DeviceFlags &= ~DFLAGS_MEDIA_STATUS_ENABLED; 9067 } 9068 9069 9070 } 9071 9072 9073 } // end IdeMediaStatus() 9074 9075 9076 /*++ 9077 9078 Routine Description: 9079 9080 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS 9081 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE. 9082 Arguments: 9083 9084 HwDeviceExtension - ATAPI driver storage. 9085 Srb - System request block. 9086 9087 Return Value: 9088 9089 SRB status (ALWAYS SUCCESS). 9090 9091 --*/ 9092 ULONG 9093 NTAPI 9094 IdeBuildSenseBuffer( 9095 IN PVOID HwDeviceExtension, 9096 IN PSCSI_REQUEST_BLOCK Srb 9097 ) 9098 { 9099 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 9100 // ULONG status; 9101 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->DataBuffer; 9102 UCHAR ReturningMediaStatus = deviceExtension->chan[GET_CHANNEL(Srb)].ReturningMediaStatus; 9103 9104 if (senseBuffer){ 9105 9106 if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE) { 9107 9108 senseBuffer->ErrorCode = 0x70; 9109 senseBuffer->Valid = 1; 9110 senseBuffer->AdditionalSenseLength = 0xb; 9111 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION; 9112 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED; 9113 senseBuffer->AdditionalSenseCodeQualifier = 0; 9114 } else if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE_REQ) { 9115 9116 senseBuffer->ErrorCode = 0x70; 9117 senseBuffer->Valid = 1; 9118 senseBuffer->AdditionalSenseLength = 0xb; 9119 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION; 9120 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED; 9121 senseBuffer->AdditionalSenseCodeQualifier = 0; 9122 } else if(ReturningMediaStatus & IDE_ERROR_END_OF_MEDIA) { 9123 9124 senseBuffer->ErrorCode = 0x70; 9125 senseBuffer->Valid = 1; 9126 senseBuffer->AdditionalSenseLength = 0xb; 9127 senseBuffer->SenseKey = SCSI_SENSE_NOT_READY; 9128 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE; 9129 senseBuffer->AdditionalSenseCodeQualifier = 0; 9130 } else if(ReturningMediaStatus & IDE_ERROR_DATA_ERROR) { 9131 9132 senseBuffer->ErrorCode = 0x70; 9133 senseBuffer->Valid = 1; 9134 senseBuffer->AdditionalSenseLength = 0xb; 9135 senseBuffer->SenseKey = SCSI_SENSE_DATA_PROTECT; 9136 senseBuffer->AdditionalSenseCode = 0; 9137 senseBuffer->AdditionalSenseCodeQualifier = 0; 9138 } 9139 return SRB_STATUS_SUCCESS; 9140 } 9141 return SRB_STATUS_ERROR; 9142 9143 }// End of IdeBuildSenseBuffer 9144 9145 VOID 9146 NTAPI 9147 UniataUserDeviceReset( 9148 PHW_DEVICE_EXTENSION deviceExtension, 9149 PHW_LU_EXTENSION LunExt, 9150 ULONG lChannel 9151 ) 9152 { 9153 ULONG i; 9154 AtapiDisableInterrupts(deviceExtension, lChannel); 9155 if ((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) && 9156 (LunExt->PowerState != StartStop_Power_Sleep)) { 9157 KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n")); 9158 AtapiSoftReset(&(deviceExtension->chan[lChannel]), LunExt->Lun); 9159 } else { 9160 KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n")); 9161 AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_NONE); 9162 for(i=0; i<deviceExtension->NumberLuns; i++) { 9163 deviceExtension->chan[lChannel].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA; 9164 } 9165 } 9166 LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit 9167 AtapiEnableInterrupts(deviceExtension, lChannel); 9168 return; 9169 } // end UniataUserDeviceReset() 9170 9171 BOOLEAN 9172 NTAPI 9173 UniataNeedQueueing( 9174 PHW_DEVICE_EXTENSION deviceExtension, 9175 PHW_CHANNEL chan, 9176 BOOLEAN TopLevel 9177 ) 9178 { 9179 BOOLEAN PostReq = FALSE; 9180 if(TopLevel) { 9181 KdPrint3((PRINT_PREFIX "UniataNeedQueueing: TopLevel, qd=%x\n", chan->queue_depth)); 9182 if(chan->queue_depth > 0) { 9183 #if 0 9184 if(atapiDev && 9185 ((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY)/* || 9186 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) { 9187 KdPrint2((PRINT_PREFIX "spec: SCSIOP_TEST_UNIT_READY\n")); 9188 //PostReq = FALSE; 9189 status = SRB_STATUS_BUSY; 9190 goto skip_exec; 9191 } else { 9192 PostReq = TRUE; 9193 } 9194 #else 9195 PostReq = TRUE; 9196 #endif 9197 } else 9198 if(deviceExtension->simplexOnly && deviceExtension->queue_depth > 0) { 9199 PostReq = TRUE; 9200 } 9201 } else { 9202 KdPrint3((PRINT_PREFIX "UniataNeedQueueing: qd=%x\n", chan->queue_depth)); 9203 } 9204 return PostReq; 9205 } // end UniataNeedQueueing() 9206 9207 /*++ 9208 9209 Routine Description: 9210 9211 This routine is called from the SCSI port driver synchronized 9212 with the kernel to start an IO request. 9213 ->HwStartIo 9214 9215 Arguments: 9216 9217 HwDeviceExtension - HBA miniport driver's adapter data storage 9218 Srb - IO request packet 9219 9220 Return Value: 9221 9222 TRUE 9223 9224 --*/ 9225 BOOLEAN 9226 NTAPI 9227 AtapiStartIo( 9228 IN PVOID HwDeviceExtension, 9229 IN PSCSI_REQUEST_BLOCK Srb 9230 ) 9231 { 9232 return AtapiStartIo__(HwDeviceExtension, Srb, TRUE); 9233 } // end AtapiStartIo() 9234 9235 BOOLEAN 9236 NTAPI 9237 AtapiStartIo__( 9238 IN PVOID HwDeviceExtension, 9239 IN PSCSI_REQUEST_BLOCK Srb, 9240 IN BOOLEAN TopLevel 9241 ) 9242 { 9243 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 9244 UCHAR lChannel; 9245 PHW_CHANNEL chan; 9246 PHW_LU_EXTENSION LunExt; 9247 ULONG status; 9248 //ULONG ldev; 9249 ULONG DeviceNumber; 9250 UCHAR PathId; 9251 UCHAR TargetId; 9252 UCHAR Lun; 9253 PATA_REQ AtaReq; 9254 PSCSI_REQUEST_BLOCK tmpSrb; 9255 BOOLEAN PostReq = FALSE; 9256 BOOLEAN atapiDev; 9257 BOOLEAN commPort = FALSE; 9258 9259 // deviceExtension->Isr2DevObj must always be NULL for non-PCI 9260 if(deviceExtension->Isr2DevObj && !BMList[deviceExtension->DevIndex].Isr2Enable) { 9261 KdPrint2((PRINT_PREFIX "Isr2Enable -> 1\n")); 9262 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE; 9263 } 9264 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql()); 9265 9266 /* KeBugCheckEx(0xc000000e, 9267 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun), 9268 Srb->Function, 9269 TopLevel, 0x80000001); 9270 */ 9271 if(TopLevel && Srb && Srb->SrbExtension) { 9272 KdPrint2((PRINT_PREFIX "TopLevel\n")); 9273 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ)); 9274 UniAtaClearAtaReq(Srb->SrbExtension); 9275 } 9276 9277 do { // fetch all queued commands for the channel (if valid) 9278 9279 lChannel = GET_CHANNEL(Srb); 9280 //ldev = GET_LDEV(Srb); 9281 chan = NULL; 9282 LunExt = NULL; 9283 DeviceNumber = GET_CDEV(Srb); 9284 commPort = FALSE; 9285 9286 //ASSERT(deviceExtension); 9287 //ASSERT(chan); 9288 9289 KdPrint2((PRINT_PREFIX 9290 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n", 9291 Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId)); 9292 KdPrint2((PRINT_PREFIX " DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID)); 9293 9294 if(lChannel == deviceExtension->NumberChannels && 9295 !Srb->Lun && !Srb->TargetId && 9296 ((Srb->Function == SRB_FUNCTION_IO_CONTROL) || 9297 (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Cdb[0] == SCSIOP_INQUIRY)) 9298 ) { 9299 // This is our virtual device 9300 KdPrint2((PRINT_PREFIX 9301 "AtapiStartIo: Communication port\n")); 9302 if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) { 9303 9304 if(Srb->DataTransferLength < sizeof(PINQUIRYDATA)) { 9305 KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", Srb->DataTransferLength, 9306 sizeof(PINQUIRYDATA) )); 9307 wrong_buffer_size: 9308 status = SRB_STATUS_DATA_OVERRUN; 9309 goto complete_req; 9310 } 9311 9312 PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer); 9313 9314 KdPrint2((PRINT_PREFIX 9315 " INQUIRY\n")); 9316 // Zero INQUIRY data structure. 9317 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength); 9318 9319 inquiryData->DeviceType = COMMUNICATION_DEVICE; 9320 9321 // Fill in vendor identification fields. 9322 RtlCopyMemory(&inquiryData->VendorId, &uniata_comm_name, 28); 9323 9324 status = SRB_STATUS_SUCCESS; 9325 goto complete_req; 9326 } 9327 commPort = TRUE; 9328 /* Pass IOCTL request down */ 9329 } else 9330 if(lChannel >= deviceExtension->NumberChannels || 9331 Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns || 9332 Srb->Lun) { 9333 9334 if(lChannel >= deviceExtension->NumberChannels) { 9335 chan = NULL; 9336 } 9337 9338 reject_srb: 9339 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) { 9340 KdPrint3((PRINT_PREFIX 9341 "AtapiStartIo: SRB rejected\n")); 9342 // Indicate no device found at this address. 9343 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n")); 9344 status = SRB_STATUS_SELECTION_TIMEOUT; 9345 goto complete_req; 9346 //} 9347 } else 9348 if((deviceExtension->HwFlags & UNIATA_AHCI) && 9349 !UniataAhciChanImplemented(deviceExtension, lChannel)) { 9350 chan = NULL; 9351 } 9352 9353 if(!commPort) { 9354 chan = &(deviceExtension->chan[lChannel]); 9355 LunExt = chan->lun[DeviceNumber]; 9356 if(!LunExt) { 9357 goto reject_srb; 9358 } 9359 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE; 9360 } else { 9361 atapiDev = FALSE; 9362 } 9363 9364 #ifdef _DEBUG 9365 if(!commPort && !LunExt) { 9366 #if 0 9367 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n", 9368 deviceExtension, 9369 chan, DeviceNumber, 9370 deviceExtension->NumberChannels); 9371 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n", 9372 lChannel, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]); 9373 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n", 9374 Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId); 9375 #endif //0 9376 /* 9377 int i; 9378 for(i=0; i<1000; i++) { 9379 AtapiStallExecution(3*1000); 9380 } 9381 */ 9382 goto reject_srb; 9383 } 9384 #endif //_DEBUG 9385 9386 // Determine which function. 9387 switch (Srb->Function) { 9388 9389 case SRB_FUNCTION_EXECUTE_SCSI: 9390 9391 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 9392 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) { 9393 // let passthrough go 9394 } else 9395 if(Srb->Cdb[0] == SCSIOP_INQUIRY) { 9396 // let INQUIRY go 9397 } else { 9398 9399 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) { 9400 KdPrint2((PRINT_PREFIX 9401 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n")); 9402 // Indicate no device found at this address. 9403 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n")); 9404 status = SRB_STATUS_SELECTION_TIMEOUT; 9405 break; 9406 //} 9407 } 9408 } else { 9409 KdPrint2((PRINT_PREFIX 9410 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb, &(Srb->Cdb), Srb->SrbExtension, Srb->Cdb[0])); 9411 } 9412 /* 9413 __try { 9414 if(Srb->DataTransferLength) { 9415 UCHAR a; 9416 a = ((PUCHAR)(Srb->DataBuffer))[0]; 9417 g_foo += a; 9418 } 9419 } __except(EXCEPTION_EXECUTE_HANDLER) { 9420 KdPrint3((PRINT_PREFIX 9421 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n")); 9422 // Indicate no device found at this address. 9423 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n")); 9424 status = SRB_STATUS_ERROR; 9425 KdPrint2((PRINT_PREFIX " *** Exception...\n")); 9426 ASSERT(FALSE); 9427 break; 9428 } 9429 */ 9430 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel); 9431 9432 if(PostReq) { 9433 9434 KdPrint3((PRINT_PREFIX "Non-empty queue\n")); 9435 if (atapiDev && 9436 (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) { 9437 KdPrint3((PRINT_PREFIX "Try ATAPI prepare\n")); 9438 9439 status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE); 9440 } else { 9441 KdPrint2((PRINT_PREFIX "Try IDE prepare\n")); 9442 status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE); 9443 } 9444 /*KeBugCheckEx(0xc000000e, 9445 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun), 9446 Srb->Function, 9447 status, 0x80000001);*/ 9448 if(status == SRB_STATUS_BUSY) 9449 status = SRB_STATUS_PENDING; 9450 // Insert requests AFTER they have been initialized on 9451 // CMD_ACTION_PREPARE stage 9452 // we should not check TopLevel here (it is always TRUE) 9453 //ASSERT(chan->lun[GET_CDEV(Srb)]); 9454 UniataQueueRequest(chan, Srb); 9455 9456 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth)); 9457 9458 } else { 9459 9460 // Send command to device. 9461 KdPrint2((PRINT_PREFIX "Send to device %x\n", Srb->Cdb[0])); 9462 if(TopLevel) { 9463 KdPrint2((PRINT_PREFIX "TopLevel (2), srb %#x\n", Srb)); 9464 AtaReq = (PATA_REQ)(Srb->SrbExtension); 9465 KdPrint2((PRINT_PREFIX "TopLevel (3), AtaReq %#x\n", AtaReq)); 9466 //ASSERT(!AtaReq->Flags); 9467 //ASSERT(chan->lun[GET_CDEV(Srb)]); 9468 UniataQueueRequest(chan, Srb); 9469 // AtaReq = (PATA_REQ)(Srb->SrbExtension); 9470 //ASSERT(!AtaReq->Flags); 9471 AtaReq->ReqState = REQ_STATE_QUEUED; 9472 //ASSERT(!AtaReq->Flags); 9473 } 9474 9475 #ifndef NAVO_TEST 9476 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 9477 if(!LunExt) { 9478 goto reject_srb; 9479 } 9480 if(Srb->Cdb[0] == SCSIOP_INQUIRY) { 9481 if(UniataAnybodyHome(deviceExtension, chan->lChannel, DeviceNumber)) { 9482 if(!CheckDevice(HwDeviceExtension, chan->lChannel, DeviceNumber, TRUE)) { 9483 goto reject_srb; 9484 } 9485 } 9486 if(!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 9487 goto reject_srb; 9488 } 9489 } else 9490 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) { 9491 // allow 9492 } else { 9493 goto reject_srb; 9494 } 9495 } 9496 #endif //NAVO_TEST 9497 9498 if(atapiDev && 9499 (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)/* && 9500 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) { 9501 KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0])); 9502 status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL); 9503 } else { 9504 KdPrint2((PRINT_PREFIX "Try IDE send\n")); 9505 /* { 9506 ULONG __ebp__ = 0; 9507 ULONG __esp__ = 0; 9508 9509 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n")); 9510 __asm { 9511 mov eax,ebp 9512 mov __ebp__, eax 9513 mov eax,esp 9514 mov __esp__, eax 9515 } 9516 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__)); 9517 }*/ 9518 status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL); 9519 } 9520 /* KeBugCheckEx(0xc000000e, 9521 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun), 9522 Srb->Function, 9523 status, 0x80000002);*/ 9524 9525 } 9526 //skip_exec: 9527 TopLevel = FALSE; 9528 9529 break; 9530 9531 case SRB_FUNCTION_ABORT_COMMAND: 9532 9533 tmpSrb = ScsiPortGetSrb(HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun, 9534 Srb->QueueTag); 9535 // Verify that SRB to abort is still outstanding. 9536 if((tmpSrb != Srb->NextSrb) || 9537 !chan->queue_depth) { 9538 9539 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB to abort already completed\n")); 9540 9541 // Complete abort SRB. 9542 status = SRB_STATUS_ABORT_FAILED; 9543 break; 9544 } 9545 9546 AtaReq = (PATA_REQ)(tmpSrb->SrbExtension); 9547 if(AtaReq->ReqState > REQ_STATE_READY_TO_TRANSFER) { 9548 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_CURRENT)) { 9549 KdPrint2((PRINT_PREFIX "AtapiStartIo: Abort command failed\n")); 9550 // Log reset failure. 9551 KdPrint3((PRINT_PREFIX 9552 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n", 9553 HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8 9554 )); 9555 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8); 9556 status = SRB_STATUS_ERROR; 9557 9558 } else { 9559 status = SRB_STATUS_SUCCESS; 9560 } 9561 } else { 9562 KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove aborted srb %#x\n", tmpSrb)); 9563 if (tmpSrb->SenseInfoBuffer && 9564 tmpSrb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) { 9565 9566 PSENSE_DATA senseBuffer = (PSENSE_DATA)tmpSrb->SenseInfoBuffer; 9567 9568 senseBuffer->ErrorCode = 0; 9569 senseBuffer->Valid = 1; 9570 senseBuffer->AdditionalSenseLength = 0xb; 9571 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND; 9572 senseBuffer->AdditionalSenseCode = 0; 9573 senseBuffer->AdditionalSenseCodeQualifier = 0; 9574 9575 tmpSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; 9576 } 9577 AtapiDmaDBSync(chan, tmpSrb); 9578 UniataRemoveRequest(chan, tmpSrb); 9579 // Indicate command complete. 9580 ScsiPortNotification(RequestComplete, 9581 deviceExtension, 9582 tmpSrb); 9583 status = SRB_STATUS_SUCCESS; 9584 } 9585 break; 9586 9587 // Abort function indicates that a request timed out. 9588 // Call reset routine. Card will only be reset if 9589 // status indicates something is wrong. 9590 // Fall through to reset code. 9591 9592 case SRB_FUNCTION_RESET_DEVICE: 9593 case SRB_FUNCTION_RESET_LOGICAL_UNIT: 9594 9595 // Reset single device. 9596 // For now we support only Lun=0 9597 9598 // Note: reset is immediate command, it cannot be queued since it is usually used to 9599 // revert not-responding device to operational state 9600 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device request received\n")); 9601 UniataUserDeviceReset(deviceExtension, LunExt, lChannel); 9602 status = SRB_STATUS_SUCCESS; 9603 break; 9604 9605 case SRB_FUNCTION_RESET_BUS: 9606 do_bus_reset: 9607 // Reset Atapi and SCSI bus. 9608 9609 // Note: reset is immediate command, it cannot be queued since it is usually used to 9610 // revert not- responding device to operational state 9611 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus request received\n")); 9612 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_ALL)) { 9613 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus failed\n")); 9614 // Log reset failure. 9615 KdPrint3((PRINT_PREFIX 9616 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n", 9617 HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8 9618 )); 9619 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8); 9620 status = SRB_STATUS_ERROR; 9621 9622 } else { 9623 status = SRB_STATUS_SUCCESS; 9624 } 9625 9626 break; 9627 9628 case SRB_FUNCTION_SHUTDOWN: 9629 9630 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown\n")); 9631 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 9632 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - no such device\n")); 9633 } else 9634 if(atapiDev) { 9635 // FLUSH ATAPI device - do nothing 9636 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - ATAPI device\n")); 9637 } else { 9638 // FLUSH IDE/ATA device 9639 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - IDE device\n")); 9640 AtapiDisableInterrupts(deviceExtension, lChannel); 9641 status = AtaCommand(deviceExtension, DeviceNumber, GET_CHANNEL(Srb), 9642 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_IDLE); 9643 // If supported & allowed, reset write cacheing 9644 if(LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) { 9645 9646 // Disable write cache 9647 status = AtaCommand(deviceExtension, DeviceNumber, lChannel, 9648 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 9649 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY); 9650 // Check for errors. 9651 if (status & IDE_STATUS_ERROR) { 9652 KdPrint2((PRINT_PREFIX 9653 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n", 9654 DeviceNumber)); 9655 } 9656 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; 9657 9658 // Re-enable write cache 9659 status = AtaCommand(deviceExtension, DeviceNumber, lChannel, 9660 IDE_COMMAND_SET_FEATURES, 0, 0, 0, 9661 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY); 9662 // Check for errors. 9663 if (status & IDE_STATUS_ERROR) { 9664 KdPrint2((PRINT_PREFIX 9665 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n", 9666 DeviceNumber)); 9667 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; 9668 } else { 9669 LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED; 9670 } 9671 } 9672 9673 AtapiEnableInterrupts(deviceExtension, lChannel); 9674 } 9675 status = SRB_STATUS_SUCCESS; 9676 9677 break; 9678 9679 case SRB_FUNCTION_FLUSH: 9680 9681 KdPrint2((PRINT_PREFIX "AtapiStartIo: Flush (do nothing)\n")); 9682 status = SRB_STATUS_SUCCESS; 9683 break; 9684 9685 case SRB_FUNCTION_IO_CONTROL: { 9686 9687 ULONG len; 9688 9689 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n")); 9690 9691 len = Srb->DataTransferLength; 9692 9693 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) { 9694 9695 ULONG targetId = (ULONG)(-1); 9696 9697 if(len < sizeof(SRB_IO_CONTROL)) { 9698 goto wrong_buffer_size; 9699 } 9700 9701 // extract bogus bus address 9702 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) { 9703 case IOCTL_SCSI_MINIPORT_SMART_VERSION: { 9704 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 9705 9706 if(len < sizeof(SRB_IO_CONTROL)+sizeof(GETVERSIONINPARAMS)) { 9707 goto wrong_buffer_size; 9708 } 9709 9710 targetId = versionParameters->bIDEDeviceMap; 9711 KdPrint2((PRINT_PREFIX "targetId (smart ver) %d\n", targetId)); 9712 break; } 9713 case IOCTL_SCSI_MINIPORT_IDENTIFY: 9714 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS: 9715 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS: 9716 case IOCTL_SCSI_MINIPORT_ENABLE_SMART: 9717 case IOCTL_SCSI_MINIPORT_DISABLE_SMART: 9718 case IOCTL_SCSI_MINIPORT_RETURN_STATUS: 9719 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE: 9720 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES: 9721 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS: 9722 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE: 9723 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG: 9724 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG: 9725 { 9726 PSENDCMDINPARAMS cmdInParameters = (PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 9727 9728 if(len < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS) - 1) { 9729 goto wrong_buffer_size; 9730 } 9731 9732 targetId = cmdInParameters->bDriveNumber; 9733 KdPrint2((PRINT_PREFIX "targetId (smart/ident) %d\n", targetId)); 9734 break; } 9735 default: 9736 invalid_request: 9737 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n", 9738 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode )); 9739 status = SRB_STATUS_INVALID_REQUEST; 9740 goto complete_req; 9741 } // end switch() 9742 9743 // adjust (if necessary) bus address 9744 if(targetId != (ULONG)(-1)) { 9745 9746 // This is done because of how the IOCTL_SCSI_MINIPORT 9747 // determines 'targetid's'. Disk.sys places the real target id value 9748 // in the DeviceMap field. Once we do some parameter checking, the value passed 9749 // back to the application will be determined. 9750 9751 if (deviceExtension->NumberChannels == 1) { 9752 // do this for legacy controllers and legacy callers 9753 KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call\n")); 9754 DeviceNumber = (targetId & 0x01); 9755 lChannel = 0; 9756 } else 9757 if(commPort) { 9758 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d 9759 // due to DISK.SYS design bug, we have invalid SCSI address in SRB 9760 KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call (2)\n")); 9761 if(deviceExtension->HwFlags & UNIATA_AHCI) { 9762 lChannel = (UCHAR)targetId / 2; 9763 DeviceNumber = 0; 9764 } else { 9765 lChannel = (UCHAR)(targetId / 2); 9766 DeviceNumber = targetId & 0x01; 9767 } 9768 } else { 9769 // otherwise assume lChannel and DeviceNumber from Srb are ok 9770 } 9771 if(lChannel >= deviceExtension->NumberChannels || 9772 DeviceNumber >= deviceExtension->NumberLuns) { 9773 KdPrint2((PRINT_PREFIX 9774 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n", 9775 targetId)); 9776 // Indicate no device found at this address. 9777 goto reject_srb; 9778 } 9779 targetId = lChannel*deviceExtension->NumberLuns+DeviceNumber; 9780 chan = &(deviceExtension->chan[lChannel]); 9781 LunExt = chan->lun[DeviceNumber]; 9782 if(!LunExt) { 9783 goto reject_srb; 9784 } 9785 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE; 9786 9787 if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { 9788 goto reject_srb; 9789 } 9790 } 9791 9792 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) { 9793 case IOCTL_SCSI_MINIPORT_SMART_VERSION: { 9794 9795 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 9796 UCHAR deviceNumberMap; 9797 9798 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n")); 9799 9800 // Version and revision per SMART 1.03 9801 9802 versionParameters->bVersion = 1; 9803 versionParameters->bRevision = 1; 9804 versionParameters->bReserved = 0; 9805 9806 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands. 9807 versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD); 9808 9809 if (atapiDev) { 9810 goto invalid_request; 9811 } 9812 9813 // NOTE: This will only set the bit 9814 // corresponding to this drive's target id. 9815 // The bit mask is as follows: 9816 // 9817 // -Sec Pri 9818 // S M S M 9819 // 3 2 1 0 9820 9821 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { 9822 deviceNumberMap = 1 << lChannel; 9823 DeviceNumber = 0; 9824 } else 9825 if (deviceExtension->NumberChannels == 1) { 9826 if (chan->PrimaryAddress) { 9827 deviceNumberMap = 1 << DeviceNumber; 9828 } else { 9829 deviceNumberMap = 4 << DeviceNumber; 9830 } 9831 } else { 9832 deviceNumberMap = 1 << (DeviceNumber+lChannel*2); 9833 } 9834 9835 versionParameters->bIDEDeviceMap = deviceNumberMap; 9836 9837 status = SRB_STATUS_SUCCESS; 9838 break; 9839 } 9840 9841 case IOCTL_SCSI_MINIPORT_IDENTIFY: { 9842 9843 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 9844 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); 9845 9846 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n")); 9847 // Extract the target. 9848 KdPrint2((PRINT_PREFIX "targetId %d\n", targetId)); 9849 9850 switch(cmdInParameters.irDriveRegs.bCommandReg) { 9851 case ID_CMD: 9852 if(atapiDev) { 9853 KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n")); 9854 goto invalid_request; 9855 } 9856 /* FALL THROUGH */ 9857 case ATAPI_ID_CMD: 9858 9859 if(!atapiDev && 9860 (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) { 9861 KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n")); 9862 goto invalid_request; 9863 } 9864 9865 len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE); 9866 // Zero the output buffer 9867 RtlZeroMemory(cmdOutParameters, len); 9868 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) { 9869 ((PUCHAR)cmdOutParameters)[i] = 0; 9870 }*/ 9871 9872 // Build status block. 9873 cmdOutParameters->cBufferSize = min(IDENTIFY_BUFFER_SIZE, len - sizeof(SENDCMDOUTPARAMS) + 1); 9874 cmdOutParameters->DriverStatus.bDriverError = 0; 9875 cmdOutParameters->DriverStatus.bIDEError = 0; 9876 9877 // Extract the identify data from the device extension. 9878 ScsiPortMoveMemory (cmdOutParameters->bBuffer, &(LunExt->IdentifyData), 9879 cmdOutParameters->cBufferSize); 9880 9881 if((cmdOutParameters->cBufferSize == IDENTIFY_BUFFER_SIZE) && 9882 (LunExt->IdentifyData.ChecksumValid == ATA_ChecksumValid)) { 9883 // adjust checksum if it is possible 9884 CHAR csum = 0; 9885 ULONG i; 9886 9887 for(i=0; i < IDENTIFY_BUFFER_SIZE-1; i++) { 9888 csum += (CHAR)(cmdOutParameters->bBuffer[i]); 9889 } 9890 cmdOutParameters->bBuffer[i] = -csum; 9891 KdPrint2((PRINT_PREFIX "AtapiStartIo: adjust checksum %d\n")); 9892 } 9893 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n")); 9894 9895 status = SRB_STATUS_SUCCESS; 9896 9897 break; 9898 default: 9899 KdPrint2((PRINT_PREFIX "AtapiStartIo: not supported ID code %x\n", 9900 cmdInParameters.irDriveRegs.bCommandReg)); 9901 status = SRB_STATUS_INVALID_REQUEST; 9902 break; 9903 } 9904 break; 9905 } 9906 /* 9907 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS: 9908 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS: 9909 case IOCTL_SCSI_MINIPORT_ENABLE_SMART: 9910 case IOCTL_SCSI_MINIPORT_DISABLE_SMART: 9911 case IOCTL_SCSI_MINIPORT_RETURN_STATUS: 9912 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE: 9913 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES: 9914 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS: 9915 */ 9916 default: 9917 // *all* IOCTLs here are SMART 9918 if(commPort) { 9919 KdPrint2((PRINT_PREFIX 9920 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n")); 9921 } 9922 if (atapiDev) { 9923 goto invalid_request; 9924 } 9925 9926 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel); 9927 9928 if(PostReq || TopLevel) { 9929 UniataQueueRequest(chan, Srb); 9930 AtaReq = (PATA_REQ)(Srb->SrbExtension); 9931 AtaReq->ReqState = REQ_STATE_QUEUED; 9932 } 9933 9934 if(PostReq) { 9935 9936 KdPrint2((PRINT_PREFIX "Non-empty queue (SMART)\n")); 9937 status = SRB_STATUS_PENDING; 9938 9939 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth)); 9940 } else { 9941 9942 status = IdeSendSmartCommand(HwDeviceExtension, Srb, targetId); 9943 } 9944 break; 9945 9946 // we should not get here, checked above 9947 /* default : 9948 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n", 9949 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode )); 9950 status = SRB_STATUS_INVALID_REQUEST; 9951 break; 9952 */ 9953 } 9954 } else 9955 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) { 9956 9957 PUNIATA_CTL AtaCtl = (PUNIATA_CTL)(Srb->DataBuffer); 9958 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0); 9959 ULONG DeviceNumber = AtaCtl->addr.TargetId; 9960 BOOLEAN bad_ldev; 9961 ULONG i, pos; 9962 9963 pos = FIELD_OFFSET(UNIATA_CTL, RawData); 9964 //chan = &(deviceExtension->chan[lChannel]); 9965 if(len < pos) { 9966 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 9967 FIELD_OFFSET(UNIATA_CTL, RawData) )); 9968 goto wrong_buffer_size; 9969 } 9970 9971 if(AtaCtl->addr.Lun || 9972 AtaCtl->addr.TargetId >= deviceExtension->NumberLuns || 9973 AtaCtl->addr.PathId >= deviceExtension->NumberChannels) { 9974 9975 chan = NULL; 9976 bad_ldev = TRUE; 9977 LunExt = NULL; 9978 9979 } else { 9980 bad_ldev = FALSE; 9981 lChannel = AtaCtl->addr.PathId; 9982 chan = &(deviceExtension->chan[lChannel]); 9983 LunExt = chan->lun[DeviceNumber]; 9984 } 9985 9986 KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl->hdr.ControlCode, DeviceNumber)); 9987 9988 /* check for valid LUN */ 9989 switch (AtaCtl->hdr.ControlCode) { 9990 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES: 9991 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: 9992 // this would be BUS reset 9993 if(bad_ldev && 9994 (AtaCtl->addr.PathId >= deviceExtension->NumberChannels || 9995 AtaCtl->addr.TargetId != 0xff || 9996 AtaCtl->addr.Lun != 0 9997 )) { 9998 if(AtaCtl->hdr.ControlCode == IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES && 9999 DeviceNumber < deviceExtension->NumberLuns) { // AtaCtl->addr.TargetId != 0xff 10000 lChannel = AtaCtl->addr.PathId; 10001 chan = &(deviceExtension->chan[lChannel]); 10002 LunExt = chan->lun[DeviceNumber]; 10003 // OK 10004 } else { 10005 goto handle_bad_ldev; 10006 } 10007 } else { 10008 lChannel = AtaCtl->addr.PathId; 10009 chan = &(deviceExtension->chan[lChannel]); 10010 } 10011 break; 10012 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: 10013 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: 10014 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE: 10015 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: 10016 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO: 10017 if(bad_ldev) { 10018 handle_bad_ldev: 10019 KdPrint2((PRINT_PREFIX 10020 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n")); 10021 // Indicate no device found at this address. 10022 goto reject_srb; 10023 } 10024 } 10025 10026 /* check if queueing is necessary */ 10027 switch (AtaCtl->hdr.ControlCode) { 10028 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: 10029 if(!LunExt->nBadBlocks) { 10030 break; 10031 } 10032 goto uata_ctl_queue; 10033 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: 10034 if(len < pos+sizeof(AtaCtl->SetMode)) { 10035 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10036 pos+sizeof(AtaCtl->SetMode) )); 10037 goto wrong_buffer_size; 10038 } 10039 if(!AtaCtl->SetMode.ApplyImmediately) { 10040 break; 10041 } 10042 goto uata_ctl_queue; 10043 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES: 10044 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately 10045 uata_ctl_queue: 10046 KdPrint2((PRINT_PREFIX "put to queue (UNIATA)\n")); 10047 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel); 10048 10049 if(PostReq || TopLevel) { 10050 UniataQueueRequest(chan, Srb); 10051 AtaReq = (PATA_REQ)(Srb->SrbExtension); 10052 AtaReq->ReqState = REQ_STATE_QUEUED; 10053 } 10054 if(PostReq) { 10055 KdPrint2((PRINT_PREFIX "Non-empty queue (UNIATA)\n")); 10056 status = SRB_STATUS_PENDING; 10057 10058 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth)); 10059 goto complete_req; 10060 } 10061 } // end switch (AtaCtl->hdr.ControlCode) 10062 10063 /* process request */ 10064 switch (AtaCtl->hdr.ControlCode) { 10065 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES: 10066 10067 KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n")); 10068 10069 if(len < pos+sizeof(AtaCtl->FindDelDev)) { 10070 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10071 pos+sizeof(AtaCtl->FindDelDev) )); 10072 goto wrong_buffer_size; 10073 } 10074 if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) { 10075 KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n")); 10076 if(AtaCtl->addr.TargetId != 0xff) { 10077 LunExt->DeviceFlags &= ~DFLAGS_HIDDEN; 10078 } else { 10079 } 10080 } 10081 10082 for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) { 10083 AtapiStallExecution(1000 * 1000); 10084 } 10085 10086 FindDevices(HwDeviceExtension, 10087 ((AtaCtl->addr.TargetId == 0xff) && (AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE)) 10088 ? UNIATA_FIND_DEV_UNHIDE : 0, 10089 AtaCtl->addr.PathId); 10090 status = SRB_STATUS_SUCCESS; 10091 10092 break; 10093 10094 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: { 10095 10096 KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId)); 10097 10098 if(len < pos+sizeof(AtaCtl->FindDelDev)) { 10099 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10100 pos+sizeof(AtaCtl->FindDelDev) )); 10101 goto wrong_buffer_size; 10102 } 10103 LunExt->DeviceFlags = 0; 10104 if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) { 10105 KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n")); 10106 //LunExt->DeviceFlags |= DFLAGS_HIDDEN; 10107 UniataForgetDevice(LunExt); 10108 } 10109 10110 for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) { 10111 AtapiStallExecution(1000 * 1000); 10112 } 10113 10114 status = SRB_STATUS_SUCCESS; 10115 break; 10116 } 10117 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: { 10118 10119 KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n")); 10120 10121 if(len < pos+sizeof(AtaCtl->SetMode)) { 10122 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10123 pos+sizeof(AtaCtl->SetMode) )); 10124 goto wrong_buffer_size; 10125 } 10126 if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) { 10127 LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode); 10128 } 10129 if(AtaCtl->SetMode.MaxMode != IOMODE_NOT_SPECIFIED) { 10130 LunExt->LimitedTransferMode = (UCHAR)(AtaCtl->SetMode.MaxMode); 10131 if(LunExt->LimitedTransferMode > 10132 LunExt->OrigTransferMode) { 10133 // check for incorrect value 10134 LunExt->LimitedTransferMode = 10135 LunExt->OrigTransferMode; 10136 } 10137 } 10138 LunExt->TransferMode = min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode); 10139 10140 LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit 10141 if(AtaCtl->SetMode.ApplyImmediately) { 10142 AtapiDmaInit__(deviceExtension, LunExt); 10143 } 10144 /* LunExt->TransferMode = 10145 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/ 10146 status = SRB_STATUS_SUCCESS; 10147 break; 10148 } 10149 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE: { 10150 10151 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get transfer mode\n")); 10152 10153 if(len < pos+sizeof(AtaCtl->GetMode)) { 10154 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10155 pos+sizeof(AtaCtl->GetMode) )); 10156 goto wrong_buffer_size; 10157 } 10158 AtaCtl->GetMode.OrigMode = LunExt->OrigTransferMode; 10159 AtaCtl->GetMode.MaxMode = LunExt->LimitedTransferMode; 10160 AtaCtl->GetMode.CurrentMode = LunExt->TransferMode; 10161 AtaCtl->GetMode.PhyMode = LunExt->PhyTransferMode; 10162 10163 status = SRB_STATUS_SUCCESS; 10164 break; 10165 } 10166 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION: { 10167 10168 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n")); 10169 10170 if(len < pos+sizeof(AtaCtl->Version)) { 10171 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10172 pos+sizeof(AtaCtl->Version) )); 10173 goto wrong_buffer_size; 10174 } 10175 AtaCtl->Version.Length = sizeof(GETDRVVERSION); 10176 AtaCtl->Version.VersionMj = UNIATA_VER_MJ; 10177 AtaCtl->Version.VersionMn = UNIATA_VER_MN; 10178 AtaCtl->Version.SubVerMj = UNIATA_VER_SUB_MJ; 10179 AtaCtl->Version.SubVerMn = UNIATA_VER_SUB_MN; 10180 10181 status = SRB_STATUS_SUCCESS; 10182 break; 10183 } 10184 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO: { 10185 10186 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n")); 10187 10188 if(len < pos+sizeof(AtaCtl->AdapterInfo)) { 10189 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, 10190 pos+sizeof(AtaCtl->AdapterInfo) )); 10191 goto wrong_buffer_size; 10192 } 10193 AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO); 10194 10195 AtaCtl->AdapterInfo.DevID = deviceExtension->DevID; 10196 AtaCtl->AdapterInfo.RevID = deviceExtension->RevID; 10197 AtaCtl->AdapterInfo.slotNumber = deviceExtension->slotNumber; 10198 AtaCtl->AdapterInfo.SystemIoBusNumber = deviceExtension->SystemIoBusNumber; 10199 AtaCtl->AdapterInfo.DevIndex = deviceExtension->DevIndex; 10200 AtaCtl->AdapterInfo.Channel = deviceExtension->Channel; 10201 AtaCtl->AdapterInfo.HbaCtrlFlags = deviceExtension->HbaCtrlFlags; 10202 AtaCtl->AdapterInfo.simplexOnly= deviceExtension->simplexOnly; 10203 AtaCtl->AdapterInfo.MemIo = FALSE;/*deviceExtension->MemIo;*/ 10204 AtaCtl->AdapterInfo.UnknownDev = deviceExtension->UnknownDev; 10205 AtaCtl->AdapterInfo.MasterDev = deviceExtension->MasterDev; 10206 AtaCtl->AdapterInfo.MaxTransferMode = deviceExtension->MaxTransferMode; 10207 AtaCtl->AdapterInfo.HwFlags = deviceExtension->HwFlags; 10208 AtaCtl->AdapterInfo.OrigAdapterInterfaceType = deviceExtension->OrigAdapterInterfaceType; 10209 AtaCtl->AdapterInfo.BusInterruptLevel = deviceExtension->BusInterruptLevel; 10210 AtaCtl->AdapterInfo.InterruptMode = deviceExtension->InterruptMode; 10211 AtaCtl->AdapterInfo.BusInterruptVector = deviceExtension->BusInterruptVector; 10212 AtaCtl->AdapterInfo.NumberChannels = deviceExtension->NumberChannels; 10213 AtaCtl->AdapterInfo.NumberLuns = (UCHAR)deviceExtension->NumberLuns; 10214 AtaCtl->AdapterInfo.AdapterInterfaceType = deviceExtension->AdapterInterfaceType; 10215 if(deviceExtension->FullDevName) { 10216 strncpy(AtaCtl->AdapterInfo.DeviceName, deviceExtension->FullDevName, 64); 10217 } 10218 AtaCtl->AdapterInfo.ChanInfoValid = FALSE; 10219 AtaCtl->AdapterInfo.LunInfoValid = FALSE; 10220 AtaCtl->AdapterInfo.ChanHeaderLengthValid = TRUE; 10221 10222 pos += AtaCtl->AdapterInfo.HeaderLength; 10223 10224 // zero tail 10225 RtlZeroMemory(((PCHAR)AtaCtl)+pos, 10226 len-pos); 10227 10228 if(len >= pos+AtaCtl->AdapterInfo.NumberChannels*sizeof(CHANINFO)) { 10229 PCHANINFO ChanInfo = (PCHANINFO)( ((PCHAR)AtaCtl)+pos ); 10230 PHW_CHANNEL cur_chan; 10231 KdPrint2((PRINT_PREFIX "AtapiStartIo: Fill channel info\n")); 10232 for(i=0;i<AtaCtl->AdapterInfo.NumberChannels;i++) { 10233 KdPrint2((PRINT_PREFIX "chan[%d] %x\n", i, cur_chan)); 10234 cur_chan = &(deviceExtension->chan[i]); 10235 ChanInfo->MaxTransferMode = cur_chan->MaxTransferMode; 10236 ChanInfo->ChannelCtrlFlags = cur_chan->ChannelCtrlFlags; 10237 RtlCopyMemory(&(ChanInfo->QueueStat), &(cur_chan->QueueStat), sizeof(ChanInfo->QueueStat)); 10238 ChanInfo->ReorderCount = cur_chan->ReorderCount; 10239 ChanInfo->IntersectCount = cur_chan->IntersectCount; 10240 ChanInfo->TryReorderCount = cur_chan->TryReorderCount; 10241 ChanInfo->TryReorderHeadCount = cur_chan->TryReorderHeadCount; 10242 ChanInfo->TryReorderTailCount = cur_chan->TryReorderTailCount; 10243 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode; 10244 ChanInfo++; 10245 } 10246 AtaCtl->AdapterInfo.ChanInfoValid = TRUE; 10247 AtaCtl->AdapterInfo.ChanHeaderLength = sizeof(*ChanInfo); 10248 } 10249 10250 status = SRB_STATUS_SUCCESS; 10251 break; 10252 } 10253 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: { 10254 10255 KdPrint2((PRINT_PREFIX "AtapiStartIo: Forget BB list\n")); 10256 10257 ForgetBadBlocks(LunExt); 10258 10259 status = SRB_STATUS_SUCCESS; 10260 break; 10261 } 10262 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: { 10263 10264 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device\n")); 10265 10266 if(bad_ldev) { 10267 goto do_bus_reset; 10268 } else { 10269 UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId); 10270 } 10271 10272 status = SRB_STATUS_SUCCESS; 10273 break; 10274 } 10275 default : 10276 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n", 10277 AtaCtl->hdr.ControlCode )); 10278 status = SRB_STATUS_INVALID_REQUEST; 10279 break; 10280 } 10281 10282 } else { 10283 KdPrint2((PRINT_PREFIX "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n", 10284 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature, 10285 "SCSIDISK", "-UNIATA-")); 10286 10287 status = SRB_STATUS_INVALID_REQUEST; 10288 break; 10289 } 10290 10291 break; 10292 } // end SRB_FUNCTION_IO_CONTROL 10293 default: 10294 10295 KdPrint2((PRINT_PREFIX "AtapiStartIo: Unknown IOCTL\n")); 10296 // Indicate unsupported command. 10297 status = SRB_STATUS_INVALID_REQUEST; 10298 10299 // break; 10300 10301 } // end switch 10302 10303 complete_req: 10304 10305 PathId = Srb->PathId; 10306 TargetId = Srb->TargetId; 10307 Lun = Srb->Lun; 10308 10309 if (status != SRB_STATUS_PENDING) { 10310 10311 KdPrint2((PRINT_PREFIX 10312 "AtapiStartIo: Srb %#x complete with status %#x\n", 10313 Srb, 10314 status)); 10315 10316 // Set status in SRB. 10317 Srb->SrbStatus = (UCHAR)status; 10318 10319 if(chan && Srb) { 10320 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb)); 10321 AtapiDmaDBSync(chan, Srb); 10322 } 10323 KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan, Srb)); 10324 UniataRemoveRequest(chan, Srb); 10325 // Indicate command complete. 10326 KdPrint2((PRINT_PREFIX "AtapiStartIo: ScsiPortNotification\n")); 10327 ScsiPortNotification(RequestComplete, 10328 deviceExtension, 10329 Srb); 10330 10331 KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataGetCurRequest\n")); 10332 // Remove current Srb & get next one 10333 if((Srb = UniataGetCurRequest(chan))) { 10334 AtaReq = (PATA_REQ)(Srb->SrbExtension); 10335 if(AtaReq->ReqState > REQ_STATE_QUEUED) { 10336 // current request is under precessing, thus 10337 // we should do nothing here 10338 Srb = NULL; 10339 } 10340 } 10341 KdPrint2((PRINT_PREFIX "AtapiStartIo: chan %x, Src %x\n", chan, Srb)); 10342 if(!chan) { 10343 //ASSERT(TopLevel); 10344 } 10345 } 10346 KdPrint2((PRINT_PREFIX "AtapiStartIo: next Srb %x\n", Srb)); 10347 10348 } while (Srb && (status != SRB_STATUS_PENDING)); 10349 10350 KdPrint2((PRINT_PREFIX "AtapiStartIo: query PORT for next request\n")); 10351 // Indicate ready for next request. 10352 ScsiPortNotification(NextRequest, 10353 deviceExtension, 10354 NULL); 10355 10356 ScsiPortNotification(NextLuRequest, 10357 deviceExtension, 10358 PathId, 10359 TargetId, 10360 Lun); 10361 10362 return TRUE; 10363 10364 } // end AtapiStartIo__() 10365 10366 #if 0 10367 void 10368 NTAPI 10369 UniataInitAtaCommands() 10370 { 10371 int i; 10372 UCHAR command; 10373 UCHAR flags; 10374 10375 KdPrint2((PRINT_PREFIX "UniataInitAtaCommands:\n")); 10376 10377 for(i=0; i<256; i++) { 10378 10379 flags = 0; 10380 command = i; 10381 10382 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command)); 10383 10384 switch(command) { 10385 case IDE_COMMAND_READ_DMA48: 10386 case IDE_COMMAND_READ_DMA_Q48: 10387 case IDE_COMMAND_READ_STREAM_DMA48: 10388 case IDE_COMMAND_READ_STREAM48: 10389 case IDE_COMMAND_WRITE_DMA48: 10390 case IDE_COMMAND_WRITE_DMA_Q48: 10391 case IDE_COMMAND_READ_DMA_Q: 10392 case IDE_COMMAND_READ_DMA: 10393 case IDE_COMMAND_WRITE_DMA: 10394 case IDE_COMMAND_WRITE_DMA_Q: 10395 case IDE_COMMAND_WRITE_STREAM_DMA48: 10396 case IDE_COMMAND_WRITE_STREAM48: 10397 case IDE_COMMAND_WRITE_FUA_DMA48: 10398 case IDE_COMMAND_WRITE_FUA_DMA_Q48: 10399 case IDE_COMMAND_READ_LOG_DMA48: 10400 case IDE_COMMAND_WRITE_LOG_DMA48: 10401 case IDE_COMMAND_TRUSTED_RCV_DMA: 10402 case IDE_COMMAND_TRUSTED_SEND_DMA: 10403 case IDE_COMMAND_DATA_SET_MGMT: // TRIM 10404 //KdPrint2((PRINT_PREFIX "DMA ")); 10405 flags |= ATA_CMD_FLAG_DMA; 10406 } 10407 10408 switch(command) { 10409 case IDE_COMMAND_WRITE_FUA_DMA48: 10410 case IDE_COMMAND_WRITE_FUA_DMA_Q48: 10411 case IDE_COMMAND_WRITE_MUL_FUA48: 10412 10413 flags |= ATA_CMD_FLAG_FUA; 10414 /* FALL THROUGH */ 10415 10416 case IDE_COMMAND_READ48: 10417 case IDE_COMMAND_READ_DMA48: 10418 case IDE_COMMAND_READ_DMA_Q48: 10419 case IDE_COMMAND_READ_MUL48: 10420 case IDE_COMMAND_READ_STREAM_DMA48: 10421 case IDE_COMMAND_READ_STREAM48: 10422 case IDE_COMMAND_WRITE48: 10423 case IDE_COMMAND_WRITE_DMA48: 10424 case IDE_COMMAND_WRITE_DMA_Q48: 10425 case IDE_COMMAND_WRITE_MUL48: 10426 case IDE_COMMAND_WRITE_STREAM_DMA48: 10427 case IDE_COMMAND_WRITE_STREAM48: 10428 case IDE_COMMAND_FLUSH_CACHE48: 10429 case IDE_COMMAND_VERIFY48: 10430 10431 //KdPrint2((PRINT_PREFIX "48 ")); 10432 flags |= ATA_CMD_FLAG_48; 10433 /* FALL THROUGH */ 10434 10435 case IDE_COMMAND_READ: 10436 case IDE_COMMAND_READ_MULTIPLE: 10437 case IDE_COMMAND_READ_DMA: 10438 case IDE_COMMAND_READ_DMA_Q: 10439 case IDE_COMMAND_WRITE: 10440 case IDE_COMMAND_WRITE_MULTIPLE: 10441 case IDE_COMMAND_WRITE_DMA: 10442 case IDE_COMMAND_WRITE_DMA_Q: 10443 case IDE_COMMAND_FLUSH_CACHE: 10444 case IDE_COMMAND_VERIFY: 10445 10446 //KdPrint2((PRINT_PREFIX "LBA ")); 10447 flags |= ATA_CMD_FLAG_LBAIOsupp; 10448 } 10449 10450 switch(command) { 10451 case IDE_COMMAND_READ_NATIVE_SIZE48: 10452 case IDE_COMMAND_SET_NATIVE_SIZE48: 10453 // we cannot set LBA flag for these commands to avoid BadBlock handling 10454 //flags |= ATA_CMD_FLAG_LBAIOsupp; 10455 flags |= ATA_CMD_FLAG_48; 10456 10457 case IDE_COMMAND_READ_NATIVE_SIZE: 10458 case IDE_COMMAND_SET_NATIVE_SIZE: 10459 10460 flags |= ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_FUA; 10461 } 10462 10463 flags |= ATA_CMD_FLAG_48supp; 10464 10465 switch (command) { 10466 case IDE_COMMAND_READ: 10467 command = IDE_COMMAND_READ48; break; 10468 case IDE_COMMAND_READ_MULTIPLE: 10469 command = IDE_COMMAND_READ_MUL48; break; 10470 case IDE_COMMAND_READ_DMA: 10471 command = IDE_COMMAND_READ_DMA48; break; 10472 case IDE_COMMAND_READ_DMA_Q: 10473 command = IDE_COMMAND_READ_DMA_Q48; break; 10474 case IDE_COMMAND_WRITE: 10475 command = IDE_COMMAND_WRITE48; break; 10476 case IDE_COMMAND_WRITE_MULTIPLE: 10477 command = IDE_COMMAND_WRITE_MUL48; break; 10478 case IDE_COMMAND_WRITE_DMA: 10479 command = IDE_COMMAND_WRITE_DMA48; break; 10480 case IDE_COMMAND_WRITE_DMA_Q: 10481 command = IDE_COMMAND_WRITE_DMA_Q48; break; 10482 case IDE_COMMAND_FLUSH_CACHE: 10483 command = IDE_COMMAND_FLUSH_CACHE48; break; 10484 // case IDE_COMMAND_READ_NATIVE_SIZE: 10485 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break; 10486 case IDE_COMMAND_SET_NATIVE_SIZE: 10487 command = IDE_COMMAND_SET_NATIVE_SIZE48; break; 10488 case IDE_COMMAND_VERIFY: 10489 command = IDE_COMMAND_VERIFY48; break; 10490 default: 10491 //KdPrint2((PRINT_PREFIX "!28->48 ")); 10492 flags &= ~ATA_CMD_FLAG_48supp; 10493 } 10494 10495 switch (command) { 10496 case IDE_COMMAND_READ: 10497 case IDE_COMMAND_READ_MULTIPLE: 10498 case IDE_COMMAND_READ_DMA48: 10499 case IDE_COMMAND_READ_DMA_Q48: 10500 case IDE_COMMAND_READ_STREAM_DMA48: 10501 case IDE_COMMAND_READ_STREAM48: 10502 case IDE_COMMAND_READ_DMA_Q: 10503 case IDE_COMMAND_READ_DMA: 10504 case IDE_COMMAND_READ_LOG_DMA48: 10505 case IDE_COMMAND_TRUSTED_RCV_DMA: 10506 case IDE_COMMAND_IDENTIFY: 10507 case IDE_COMMAND_ATAPI_IDENTIFY: 10508 //KdPrint2((PRINT_PREFIX "RD ")); 10509 flags |= ATA_CMD_FLAG_In; 10510 break; 10511 case IDE_COMMAND_WRITE: 10512 case IDE_COMMAND_WRITE_MULTIPLE: 10513 case IDE_COMMAND_WRITE_DMA48: 10514 case IDE_COMMAND_WRITE_DMA_Q48: 10515 case IDE_COMMAND_WRITE_DMA: 10516 case IDE_COMMAND_WRITE_DMA_Q: 10517 case IDE_COMMAND_WRITE_STREAM_DMA48: 10518 case IDE_COMMAND_WRITE_STREAM48: 10519 case IDE_COMMAND_WRITE_FUA_DMA48: 10520 case IDE_COMMAND_WRITE_FUA_DMA_Q48: 10521 //KdPrint2((PRINT_PREFIX "WR ")); 10522 flags |= ATA_CMD_FLAG_Out; 10523 break; 10524 } 10525 10526 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags)); 10527 AtaCommands48[i] = command; 10528 AtaCommandFlags[i] = flags; 10529 } 10530 } // end UniataInitAtaCommands() 10531 #endif 10532 10533 /*++ 10534 10535 Routine Description: 10536 10537 Installable driver initialization entry point for system. 10538 10539 Arguments: 10540 10541 Driver Object 10542 10543 Return Value: 10544 10545 Status from ScsiPortInitialize() 10546 10547 --*/ 10548 extern "C" 10549 ULONG 10550 NTAPI 10551 DriverEntry( 10552 IN PVOID DriverObject, 10553 IN PVOID Argument2 10554 ) 10555 { 10556 HW_INITIALIZATION_DATA_COMMON hwInitializationData; 10557 ULONG adapterCount; 10558 ULONG i, c, alt, pref_alt; 10559 ULONG statusToReturn, newStatus; 10560 PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2; 10561 BOOLEAN ReEnter = FALSE; 10562 // WCHAR a; 10563 #ifndef USE_REACTOS_DDK 10564 NTSTATUS status; 10565 #endif 10566 10567 PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation(); 10568 BOOLEAN PrimaryClaimed = FALSE; 10569 BOOLEAN SecondaryClaimed = FALSE; 10570 BOOLEAN IgnoreIsaCompatiblePci = FALSE; 10571 BOOLEAN IgnoreNativePci = FALSE; 10572 10573 LARGE_INTEGER t0, t1; 10574 10575 KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string)); 10576 //a = (WCHAR)strlen(ver_string); 10577 10578 statusToReturn = 0xffffffff; 10579 10580 // Zero out structure. 10581 RtlZeroMemory(((PCHAR)&hwInitializationData), sizeof(hwInitializationData)); 10582 10583 // Set size of hwInitializationData. 10584 hwInitializationData.comm.HwInitializationDataSize = 10585 sizeof(hwInitializationData.comm) + 10586 // sizeof(hwInitializationData.nt4) + 10587 ((WinVer_Id() <= WinVer_NT) ? 0 : sizeof(hwInitializationData.w2k)); 10588 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData.comm.HwInitializationDataSize)); 10589 10590 // Set entry points. 10591 hwInitializationData.comm.HwInitialize = (PHW_INITIALIZE)AtapiHwInitialize; 10592 hwInitializationData.comm.HwResetBus = (PHW_RESET_BUS)AtapiResetController; 10593 hwInitializationData.comm.HwStartIo = (PHW_STARTIO)AtapiStartIo; 10594 hwInitializationData.comm.HwInterrupt = (PHW_INTERRUPT)AtapiInterrupt; 10595 10596 // Specify size of extensions. 10597 hwInitializationData.comm.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); 10598 hwInitializationData.comm.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION); 10599 hwInitializationData.comm.SrbExtensionSize = sizeof(ATA_REQ); 10600 10601 // Indicate PIO device. 10602 hwInitializationData.comm.MapBuffers = TRUE; 10603 10604 // Request and parse arument string. 10605 KdPrint2((PRINT_PREFIX "\n\nUniATA: parse ArgumentString\n")); 10606 // Zero out structure. 10607 hwInitializationData.comm.NumberOfAccessRanges = 2; 10608 hwInitializationData.comm.HwFindAdapter = AtapiReadArgumentString; 10609 ScsiPortInitialize(DriverObject, 10610 Argument2, 10611 &hwInitializationData.comm, 10612 &adapterCount); 10613 10614 if(!g_Dump) { 10615 Connect_DbgPrint(); 10616 g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0); 10617 if(g_opt_Verbose) { 10618 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR "\n"); 10619 } 10620 IgnoreIsaCompatiblePci = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", IgnoreIsaCompatiblePci) ? TRUE : FALSE; 10621 IgnoreNativePci = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", IgnoreNativePci) ? TRUE : FALSE; 10622 } else { 10623 KdPrint(("crashdump mode\n")); 10624 } 10625 10626 if(!SavedDriverObject) { 10627 SavedDriverObject = (PDRIVER_OBJECT)DriverObject; 10628 #ifdef USE_REACTOS_DDK 10629 KdPrint(("UniATA Init: OS should be ReactOS\n")); 10630 MajorVersion=0x04; 10631 MinorVersion=0x01; 10632 BuildNumber=1; 10633 CPU_num = KeNumberProcessors; 10634 #else 10635 // we are here for the 1st time 10636 // init CrossNT and get OS version 10637 if(!NT_SUCCESS(status = CrNtInit(SavedDriverObject, RegistryPath))) { 10638 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status)); 10639 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n"); 10640 return status; 10641 } 10642 CPU_num = *KeNumberProcessors; 10643 #endif // USE_REACTOS_DDK 10644 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, CPU_num)); 10645 10646 KeQuerySystemTime(&t0); 10647 do { 10648 KeQuerySystemTime(&t1); 10649 } while(t0.QuadPart == t1.QuadPart); 10650 t0=t1; 10651 g_Perf=0; 10652 do { 10653 KeQuerySystemTime(&t1); 10654 g_Perf++; 10655 } while(t0.QuadPart == t1.QuadPart); 10656 g_PerfDt = (ULONG)((t1.QuadPart - t0.QuadPart)/10); 10657 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt, g_Perf )); 10658 } else { 10659 KdPrint(("UniATA Init: ReEnter\n")); 10660 ReEnter = TRUE; 10661 } 10662 10663 // (re)read bad block list 10664 InitBadBlocks(NULL); 10665 10666 if(!ReEnter) { 10667 // init ATA command translation table 10668 //UniataInitAtaCommands(); 10669 10670 // get registry path to settings 10671 RtlCopyMemory(&SavedRegPath, RegistryPath, sizeof(UNICODE_STRING)); 10672 SavedRegPath.Buffer = (PWCHAR)&SavedRegPathBuffer; 10673 SavedRegPath.Length = min(RegistryPath->Length, 255*sizeof(WCHAR)); 10674 SavedRegPath.MaximumLength = 255*sizeof(WCHAR); 10675 RtlCopyMemory(SavedRegPath.Buffer, RegistryPath->Buffer, SavedRegPath.Length); 10676 SavedRegPath.Buffer[SavedRegPath.Length/sizeof(WCHAR)] = 0; 10677 } 10678 10679 if(WinVer_Id() >= WinVer_2k) { 10680 if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"1", 0)) { 10681 KdPrint(("UniATA: Behave as WDM, mlia (1)\n")); 10682 WinVer_WDM_Model = TRUE; 10683 } 10684 if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"5", 0)) { 10685 KdPrint(("UniATA: Behave as WDM, mlia (5)\n")); 10686 WinVer_WDM_Model = TRUE; 10687 } 10688 } 10689 10690 SkipRaids = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"SkipRaids", 1); 10691 ForceSimplex = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"ForceSimplex", 0); 10692 #ifdef _DEBUG 10693 g_LogToDisplay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"LogToDisplay", 0); 10694 #endif //_DEBUG 10695 10696 // Set PnP-specific API 10697 if(WinVer_Id() > WinVer_NT) { 10698 KdPrint(("set NeedPhysicalAddresses = TRUE\n")); 10699 hwInitializationData.comm.NeedPhysicalAddresses = TRUE; 10700 KdPrint(("set AtapiAdapterControl() ptr\n")); 10701 hwInitializationData.w2k.HwAdapterControl = (PHW_ADAPTER_CONTROL)AtapiAdapterControl; 10702 } 10703 10704 KdPrint2((PRINT_PREFIX "\n\nUniATA init... (%d)\n", ReEnter)); 10705 if(!ReEnter) { 10706 10707 g_opt_VirtualMachine = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualMachineType", g_opt_VirtualMachine); 10708 if(g_opt_VirtualMachine > VM_MAX_KNOWN) { 10709 g_opt_VirtualMachine = 0; 10710 } 10711 if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualBox", (g_opt_VirtualMachine == VM_VBOX))) { 10712 g_opt_VirtualMachine = VM_VBOX; 10713 } 10714 // Pre-scan PCI bus, also check if we are under VM 10715 // But do not perform scan if PCI bus is claimed as unused 10716 if(!IgnoreIsaCompatiblePci || !IgnoreNativePci) { 10717 KdPrint2((PRINT_PREFIX "\nATAPI IDE enum supported PCI BusMaster Devices\n")); 10718 UniataEnumBusMasterController(DriverObject, Argument2); 10719 } 10720 10721 switch(g_opt_VirtualMachine) { 10722 case VM_VBOX: 10723 KdPrint2((PRINT_PREFIX "adjust options for VirtualBox\n")); 10724 // adjust options for VirtualBox 10725 g_opt_WaitBusyCount = 20000; 10726 g_opt_WaitBusyDelay = 150; 10727 g_opt_WaitDrqDelay = 100; 10728 g_opt_WaitBusyLongCount = 20000; 10729 g_opt_MaxIsrWait = 200; 10730 g_opt_AtapiSendDisableIntr = FALSE; 10731 g_opt_AtapiDmaRawRead = FALSE; 10732 break; 10733 case VM_BOCHS: 10734 KdPrint2((PRINT_PREFIX "adjust options for Bochs\n")); 10735 g_opt_AtapiNoDma = TRUE; 10736 } 10737 10738 if(!hasPCI) { 10739 KdPrint2((PRINT_PREFIX "old slow machine, adjust timings\n")); 10740 // old slow machine, adjust timings (us) 10741 g_opt_WaitBusyResetCount = 20000; 10742 g_opt_WaitBusyCount = 20000; 10743 g_opt_WaitBusyDelay = 150; 10744 g_opt_WaitDrqDelay = 100; 10745 g_opt_WaitBusyLongCount = 20000; 10746 g_opt_MaxIsrWait = 200; 10747 g_opt_DriveSelectNanoDelay = 400; 10748 } 10749 if(g_opt_VirtualMachine > VM_NONE) { 10750 g_opt_DriveSelectNanoDelay = 0; 10751 } 10752 if(CPU_num > 1) { 10753 g_opt_AtapiSendDisableIntr = TRUE; 10754 } 10755 10756 g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000 10757 g_opt_WaitBusyDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyDelay", g_opt_WaitBusyDelay); // 10 vs 150 10758 g_opt_WaitDrqDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay", g_opt_WaitDrqDelay); // 10 vs 100 10759 g_opt_WaitBusyLongCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongCount", g_opt_WaitBusyLongCount); // 2000 vs 20000 10760 g_opt_WaitBusyLongDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongDelay", g_opt_WaitBusyLongDelay); // 250 vs 250 10761 g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr) ? TRUE : FALSE; // 1 vs 0 10762 g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead) ? TRUE : FALSE; // 1 vs 0 10763 g_opt_AtapiNoDma = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiNoDma", g_opt_AtapiNoDma) ? TRUE : FALSE; // 1 vs 0 10764 g_opt_MaxIsrWait = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"MaxIsrWait", g_opt_MaxIsrWait); // 40 vs xxx 10765 g_opt_DriveSelectNanoDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"DriveSelectNanoDelay", g_opt_DriveSelectNanoDelay); 10766 } // end !re-enter 10767 10768 // Look for legacy ISA-bridged PCI IDE controller (onboard) 10769 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n")); 10770 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: BMListLen %d\n", BMListLen)); 10771 for (i=0; i <BMListLen; i++) { 10772 10773 if(!BMList[i].MasterDev) { 10774 KdPrint2((PRINT_PREFIX "!BMList[i].MasterDev\n")); 10775 break; 10776 } 10777 if(IgnoreIsaCompatiblePci) { 10778 break; 10779 } 10780 if(ReEnter) { 10781 KdPrint2((PRINT_PREFIX "ReEnter, skip it\n")); 10782 if(BMList[i].ChanInitOk & 0x03) { 10783 KdPrint2((PRINT_PREFIX "Already initialized, skip it\n")); 10784 statusToReturn = 10785 newStatus = STATUS_SUCCESS; 10786 } 10787 continue; 10788 } 10789 //BMList[i].AltInitMasterDev = (UCHAR)0xff; 10790 10791 if(GlobalConfig->AtDiskPrimaryAddressClaimed) 10792 PrimaryClaimed = TRUE; 10793 if(GlobalConfig->AtDiskSecondaryAddressClaimed) 10794 SecondaryClaimed = TRUE; 10795 pref_alt = 0; 10796 10797 if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed && !g_Dump && 10798 !(BMList[i].ChanInitOk & 0x80)) { 10799 10800 // We just want to claim our PCI device in compatible mode, since we shall not 10801 // tell system that we use it inside HwInitialize 10802 // Even more, we shall cheat system, that work with ISA 10803 // Note: this call may (but not 'must' or 'can') cause IO resource 10804 // reallocation and switch to native mode if HAL supports this 10805 newStatus = (ULONG)UniataClaimLegacyPCIIDE(i); 10806 // Special check for NT3.51/NT4 (not ReactOS !!!) 10807 if(((NTSTATUS)newStatus == STATUS_CONFLICTING_ADDRESSES) && 10808 //(BMList[i].ChanInitOk & 0x40) && 10809 /*CPU_num > 1 &&*/ 10810 (WinVer_Id() <= WinVer_NT)) { 10811 // Some NT3/4 SMP (but not only) HALs cannot reallocate IO resources of 10812 // BusMaster PCI controller 10813 // Since nobody claimed Primary/Secondary yet, try init and claim them 10814 // However it is not 100% safe way, especially under ReactOS, which doesn't resolve 10815 // conflicts yet. 10816 // We relay on ScsiPort internal checks 10817 KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster on SMP NT3/4 system, try init anyway.\n")); 10818 newStatus = STATUS_SUCCESS; 10819 // Prefer alternative init method (try to change Isa -> PCI in ConfigInfo first) 10820 pref_alt = 1; 10821 } 10822 if(newStatus != STATUS_SUCCESS) { 10823 KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster, try as pure ISA later.\n")); 10824 break; 10825 } 10826 } 10827 10828 if(g_opt_Verbose) { 10829 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:"); 10830 } 10831 10832 for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) { 10833 10834 for(c=0; c<2; c++) { 10835 // check is channel is manually excluded 10836 if(AtapiRegCheckDevValue(NULL, c, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) { 10837 break; 10838 } 10839 if(c==0) { 10840 if(PrimaryClaimed) { 10841 KdPrint2((PRINT_PREFIX "Primary already claimed\n")); 10842 continue; 10843 } 10844 } else 10845 if(c==1) { 10846 if(SecondaryClaimed) { 10847 KdPrint2((PRINT_PREFIX "Secondary already claimed\n")); 10848 continue; 10849 } 10850 } 10851 10852 if((WinVer_Id() < WinVer_2k)) { 10853 // do not even try if already claimed 10854 if(c==0) { 10855 GlobalConfig->AtDiskPrimaryAddressClaimed = FALSE; 10856 } else 10857 if(c==1) { 10858 GlobalConfig->AtDiskSecondaryAddressClaimed = FALSE; 10859 } 10860 } 10861 if(!WinVer_WDM_Model) { 10862 hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController; 10863 } else { 10864 // in WDM model things are different.... 10865 hwInitializationData.comm.HwFindAdapter = (c == 0) ? 10866 UniataFindCompatBusMasterController1 : UniataFindCompatBusMasterController2; 10867 } 10868 hwInitializationData.comm.NumberOfAccessRanges = 6; 10869 hwInitializationData.comm.AdapterInterfaceType = Isa; 10870 10871 if(!WinVer_WDM_Model) { 10872 BMList[i].channel = (UCHAR)c; 10873 } 10874 10875 KdPrint2((PRINT_PREFIX "Try init channel %d, method %d\n", c, alt)); 10876 newStatus = ScsiPortInitialize(DriverObject, 10877 Argument2, 10878 &hwInitializationData.comm, 10879 UlongToPtr(i | ((alt ^ pref_alt) ? 0x80000000 : 0))); 10880 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus)); 10881 if (newStatus < statusToReturn) { 10882 statusToReturn = newStatus; 10883 } 10884 if (newStatus == STATUS_SUCCESS) { 10885 if(WinVer_Id() < WinVer_2k) { 10886 // This should be done in HwInitialize under w2k+ to ensure that 10887 // channel is actually initialized 10888 BMList[i].ChanInitOk |= 0x01 << c; 10889 } else { 10890 if(BMList[i].ChanInitOk & (0x01 << c)) { 10891 KdPrint2((PRINT_PREFIX "HwInit passed\n")); 10892 } 10893 } 10894 /* 10895 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) { 10896 c = 1; // this will break our for() 10897 BMList[i].ChanInitOk |= 0x01 << c; 10898 } 10899 */ 10900 } 10901 } 10902 /* if(WinVer_Id() >= WinVer_2k) { 10903 // the following didn't work under higher OSes, 10904 // until we move setting of FLAGS to HwInit 10905 KdPrint2((PRINT_PREFIX "make still one attempt\n")); 10906 continue; 10907 }*/ 10908 if(BMList[i].ChanInitOk & 0x03) { 10909 // Under NT we receive status immediately, so 10910 // we can omit alternative init method if STATUS_SUCCESS returned. 10911 // Under w2k+ we relay on flags, set in HwInitialize. 10912 KdPrint2((PRINT_PREFIX "Ok, no more retries required\n")); 10913 break; 10914 } else 10915 if(WinVer_Id() >= WinVer_2k) { 10916 // try AltInit if HwInit was not called immediately under w2k+ 10917 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n")); 10918 } else { 10919 // if (WinVer_Id() == WinVer_NT) and some error occured 10920 // try alternative init method 10921 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n")); 10922 } 10923 } // for(alt...) 10924 if(g_opt_Verbose) { 10925 if(BMList[i].ChanInitOk & 0x03) { 10926 _PrintNtConsole(" OK\n"); 10927 } else { 10928 _PrintNtConsole(" failed\n"); 10929 } 10930 } 10931 10932 } 10933 10934 /* KeBugCheckEx(0xc000000e, 10935 (i << 16) | BMList[0].ChanInitOk, 10936 c, 10937 newStatus, statusToReturn);*/ 10938 10939 // Look for PCI IDE controller 10940 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for PCI IDE controller\n")); 10941 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: i %d, BMListLen %d\n", i, BMListLen)); 10942 for (; i <BMListLen; i++) { 10943 10944 if(IgnoreNativePci) { 10945 break; 10946 } 10947 /* if(BMList[i].MasterDev) 10948 continue;*/ 10949 if(g_opt_Verbose) { 10950 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d", 10951 BMList[i].VendorId, BMList[i].DeviceId, 10952 BMList[i].busNumber, 10953 BMList[i].slotNumber % PCI_MAX_FUNCTION, 10954 (BMList[i].slotNumber / PCI_MAX_FUNCTION) % PCI_MAX_DEVICES); 10955 } 10956 10957 hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController; 10958 hwInitializationData.comm.NumberOfAccessRanges = 6; 10959 hwInitializationData.comm.AdapterInterfaceType = PCIBus; 10960 10961 hwInitializationData.comm.VendorId = (PVOID)BMList[i].VendorId; 10962 hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength; 10963 hwInitializationData.comm.DeviceId = (PVOID)BMList[i].DeviceId; 10964 hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength; 10965 10966 BMList[i].channel = 0/*(UCHAR)c*/; 10967 10968 KdPrint2((PRINT_PREFIX "Try init %4.4s %4.4s \n", 10969 hwInitializationData.comm.VendorId, 10970 hwInitializationData.comm.DeviceId)); 10971 newStatus = ScsiPortInitialize(DriverObject, 10972 Argument2, 10973 &hwInitializationData.comm, 10974 UlongToPtr(i)); 10975 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus)); 10976 if(newStatus == (ULONG)STATUS_DEVICE_DOES_NOT_EXIST && BMList[i].NeedAltInit) { 10977 // Note: this is actually a BUG in scsiport.sys 10978 // It stops scanning PCI bus when reaches empty PCI Function inside Slot 10979 // However, this PCI Slot may have higher non-empty Functions 10980 // UniATA will perform all staff instead of ScsiPort under NT, 10981 // but for ReactOS it is better to patch ScsiPort. 10982 KdPrint2((PRINT_PREFIX "STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n")); 10983 hwInitializationData.comm.AdapterInterfaceType = Isa; 10984 newStatus = ScsiPortInitialize(DriverObject, 10985 Argument2, 10986 &hwInitializationData.comm, 10987 UlongToPtr(i | 0x80000000)); 10988 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x (2)\n", newStatus)); 10989 } 10990 if (newStatus < statusToReturn) 10991 statusToReturn = newStatus; 10992 10993 if(g_opt_Verbose) { 10994 if(newStatus == STATUS_SUCCESS) { 10995 _PrintNtConsole(" OK\n"); 10996 } else { 10997 _PrintNtConsole(" failed\n"); 10998 } 10999 } 11000 11001 } 11002 11003 /* KeBugCheckEx(0xc000000e, 11004 i, 11005 c, 11006 newStatus, statusToReturn);*/ 11007 11008 // -------------- 11009 11010 hwInitializationData.comm.VendorId = 0; 11011 hwInitializationData.comm.VendorIdLength = 0; 11012 hwInitializationData.comm.DeviceId = 0; 11013 hwInitializationData.comm.DeviceIdLength = 0; 11014 11015 if(!BMListLen) { 11016 hwInitializationData.comm.SrbExtensionSize = //FIELD_OFFSET(ATA_REQ, ata); 11017 sizeof(ATA_REQ); 11018 KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", hwInitializationData.comm.SrbExtensionSize)); 11019 } 11020 11021 // The adapter count is used by the find adapter routine to track how 11022 // which adapter addresses have been tested. 11023 11024 // Indicate 2 access ranges and reset FindAdapter. 11025 hwInitializationData.comm.NumberOfAccessRanges = 2; 11026 hwInitializationData.comm.HwFindAdapter = AtapiFindIsaController; 11027 11028 if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsa", 0)) { 11029 // Indicate ISA bustype. 11030 hwInitializationData.comm.AdapterInterfaceType = Isa; 11031 adapterCount = 0; 11032 11033 // Call initialization for ISA bustype. 11034 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for ISA Controllers\n")); 11035 newStatus = ScsiPortInitialize(DriverObject, 11036 Argument2, 11037 &hwInitializationData.comm, 11038 &adapterCount); 11039 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus)); 11040 if (newStatus < statusToReturn) 11041 statusToReturn = newStatus; 11042 } 11043 if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreMca", 0)) { 11044 // Set up for MCA 11045 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for MCA Controllers\n")); 11046 hwInitializationData.comm.AdapterInterfaceType = MicroChannel; 11047 adapterCount = 0; 11048 11049 newStatus = ScsiPortInitialize(DriverObject, 11050 Argument2, 11051 &hwInitializationData.comm, 11052 &adapterCount); 11053 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus)); 11054 if (newStatus < statusToReturn) 11055 statusToReturn = newStatus; 11056 } 11057 InDriverEntry = FALSE; 11058 11059 KdPrint2((PRINT_PREFIX "\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn)); 11060 11061 return statusToReturn; 11062 11063 } // end DriverEntry() 11064 11065 11066 PSCSI_REQUEST_BLOCK 11067 NTAPI 11068 BuildMechanismStatusSrb( 11069 IN PVOID HwDeviceExtension, 11070 IN PSCSI_REQUEST_BLOCK Srb 11071 ) 11072 { 11073 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 11074 PSCSI_REQUEST_BLOCK srb; 11075 PCDB cdb; 11076 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 11077 11078 srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb); 11079 11080 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK)); 11081 11082 srb->PathId = (UCHAR)(Srb->PathId); 11083 srb->TargetId = (UCHAR)(Srb->TargetId); 11084 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 11085 srb->Length = sizeof(SCSI_REQUEST_BLOCK); 11086 11087 // Set flags to disable synchronous negociation. 11088 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 11089 11090 // Set timeout to 4 seconds. 11091 srb->TimeOutValue = 4; 11092 11093 srb->CdbLength = 6; 11094 srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusData); 11095 srb->DataTransferLength = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER); 11096 srb->SrbExtension = AtaReq; 11097 11098 // Set CDB operation code. 11099 cdb = (PCDB)srb->Cdb; 11100 cdb->MECH_STATUS.OperationCode = SCSIOP_MECHANISM_STATUS; 11101 cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER); 11102 11103 KdPrint2((PRINT_PREFIX " MechanismStatusSrb %#x\n", srb)); 11104 11105 return srb; 11106 } // end BuildMechanismStatusSrb() 11107 11108 #endif //UNIATA_CORE 11109 11110 PSCSI_REQUEST_BLOCK 11111 NTAPI 11112 BuildRequestSenseSrb ( 11113 IN PVOID HwDeviceExtension, 11114 IN PSCSI_REQUEST_BLOCK Srb 11115 ) 11116 { 11117 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 11118 PSCSI_REQUEST_BLOCK srb; 11119 PCDB cdb; 11120 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 11121 11122 srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb); 11123 11124 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK)); 11125 11126 srb->PathId = (UCHAR)(Srb->PathId); 11127 srb->TargetId = (UCHAR)(Srb->TargetId); 11128 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 11129 srb->Length = sizeof(SCSI_REQUEST_BLOCK); 11130 11131 // Set flags to disable synchronous negociation. 11132 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 11133 11134 // Set timeout to 2 seconds. 11135 srb->TimeOutValue = 4; 11136 11137 srb->CdbLength = 6; 11138 srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusSense); 11139 srb->DataTransferLength = sizeof(SENSE_DATA); 11140 srb->SrbExtension = AtaReq; 11141 11142 // Set CDB operation code. 11143 cdb = (PCDB)srb->Cdb; 11144 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE; 11145 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA); 11146 11147 KdPrint2((PRINT_PREFIX " RequestSenseSrb %#x\n", srb)); 11148 11149 return srb; 11150 } // end BuildRequestSenseSrb() 11151 11152 #ifndef UNIATA_CORE 11153 11154 ULONG 11155 NTAPI 11156 AtapiRegCheckDevLunValue( 11157 IN PVOID HwDeviceExtension, 11158 IN PCWCH NamePrefix, 11159 IN ULONG chan, 11160 IN ULONG dev, 11161 IN PCWSTR Name, 11162 IN ULONG Default 11163 ) 11164 { 11165 WCHAR namex[160]; 11166 ULONG val = Default; 11167 11168 val = AtapiRegCheckParameterValue( 11169 HwDeviceExtension, NamePrefix, Name, val); 11170 11171 if(chan != CHAN_NOT_SPECIFIED) { 11172 swprintf(namex, L"%s\\Chan_%1.1d", NamePrefix, chan); 11173 val = AtapiRegCheckParameterValue( 11174 HwDeviceExtension, namex, Name, val); 11175 if(dev != DEVNUM_NOT_SPECIFIED) { 11176 swprintf(namex, L"%s\\Chan_%1.1d\\%s", NamePrefix, chan, (dev & 0x01) ? L"Lun_1" : L"Lun_0"); 11177 val = AtapiRegCheckParameterValue( 11178 HwDeviceExtension, namex, Name, val); 11179 } 11180 } 11181 return val; 11182 } // end AtapiRegCheckDevLunValue() 11183 11184 ULONG 11185 NTAPI 11186 EncodeVendorStr( 11187 OUT PWCHAR Buffer, 11188 IN PUCHAR Str, 11189 IN ULONG Length 11190 ) 11191 { 11192 ULONG i,j; 11193 WCHAR a; 11194 11195 for(i=0, j=0; i<Length; i++, j++) { 11196 // fix byte-order 11197 a = Str[i ^ 0x01]; 11198 if(!a) { 11199 Buffer[j] = 0; 11200 return j; 11201 } else 11202 if(a == ' ') { 11203 Buffer[j] = '_'; 11204 } else 11205 if((a == '_') || 11206 (a == '#') || 11207 (a == '\\') || 11208 (a == '\"') || 11209 (a == '\'') || 11210 (a < ' ') || 11211 (a >= 127)) { 11212 Buffer[j] = '#'; 11213 j++; 11214 swprintf(Buffer+j, L"%2.2x", a); 11215 j++; 11216 } else { 11217 Buffer[j] = a; 11218 } 11219 } 11220 Buffer[j] = 0; 11221 return j; 11222 } // end EncodeVendorStr() 11223 11224 ULONG 11225 NTAPI 11226 AtapiRegCheckDevValue( 11227 IN PVOID HwDeviceExtension, 11228 IN ULONG chan, 11229 IN ULONG dev, 11230 IN PCWSTR Name, 11231 IN ULONG Default 11232 ) 11233 { 11234 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 11235 // WCHAR name0[11]; 11236 // WCHAR name1[11+4+5]; 11237 // WCHAR name2[11+4+4+10]; 11238 // WCHAR name3[11+4+4+5+20]; 11239 // WCHAR name3[11+4+4+5+20+1]; 11240 WCHAR namex[160]; 11241 11242 WCHAR namev[16]; 11243 WCHAR named[16]; 11244 WCHAR names[20]; 11245 11246 IN ULONG VendorID; 11247 IN ULONG DeviceID; 11248 IN ULONG SlotNumber; 11249 IN ULONG HwFlags; 11250 11251 ULONG val = Default; 11252 11253 KdPrint(( " Parameter %ws\n", Name)); 11254 11255 if(deviceExtension) { 11256 VendorID = deviceExtension->DevID & 0xffff; 11257 DeviceID = (deviceExtension->DevID >> 16) & 0xffff; 11258 SlotNumber = deviceExtension->slotNumber; 11259 HwFlags = deviceExtension->HwFlags; 11260 } else { 11261 VendorID = 0xffff; 11262 DeviceID = 0xffff; 11263 SlotNumber = 0xffffffff; 11264 HwFlags = 0; 11265 } 11266 11267 val = AtapiRegCheckDevLunValue( 11268 HwDeviceExtension, L"Parameters", chan, dev, Name, val); 11269 11270 if(deviceExtension) { 11271 11272 if(HwFlags & UNIATA_SATA) { 11273 swprintf(namev, L"\\SATA"); 11274 swprintf(namex, L"Parameters%s", namev); 11275 val = AtapiRegCheckDevLunValue( 11276 HwDeviceExtension, namex, chan, dev, Name, val); 11277 } 11278 if(HwFlags & UNIATA_AHCI) { 11279 swprintf(namev, L"\\AHCI"); 11280 swprintf(namex, L"Parameters%s", namev); 11281 val = AtapiRegCheckDevLunValue( 11282 HwDeviceExtension, namex, chan, dev, Name, val); 11283 } 11284 if(!(HwFlags & (UNIATA_SATA | UNIATA_AHCI))) { 11285 swprintf(namev, L"\\PATA"); 11286 swprintf(namex, L"Parameters%s", namev); 11287 val = AtapiRegCheckDevLunValue( 11288 HwDeviceExtension, namex, chan, dev, Name, val); 11289 } 11290 11291 if(deviceExtension->AdapterInterfaceType == PCIBus) { 11292 // PCI 11293 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex); 11294 swprintf(namex, L"Parameters%s", namev); 11295 val = AtapiRegCheckDevLunValue( 11296 HwDeviceExtension, namex, chan, dev, Name, val); 11297 11298 11299 swprintf(namev, L"\\Ven_%4.4x", VendorID); 11300 swprintf(named, L"\\Dev_%4.4x", DeviceID); 11301 swprintf(names, L"\\Slot_%8.8x", SlotNumber); 11302 11303 swprintf(namex, L"Parameters%s", namev); 11304 val = AtapiRegCheckDevLunValue( 11305 HwDeviceExtension, namex, chan, dev, Name, val); 11306 11307 swprintf(namex, L"Parameters%s%s", namev, named); 11308 val = AtapiRegCheckDevLunValue( 11309 HwDeviceExtension, namex, chan, dev, Name, val); 11310 11311 swprintf(namex, L"Parameters%s%s%s", namev, named, names); 11312 val = AtapiRegCheckDevLunValue( 11313 HwDeviceExtension, namex, chan, dev, Name, val); 11314 } else 11315 if(deviceExtension->AdapterInterfaceType == Isa) { 11316 // Isa 11317 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen); 11318 swprintf(namex, L"Parameters%s", namev); 11319 val = AtapiRegCheckDevLunValue( 11320 HwDeviceExtension, namex, chan, dev, Name, val); 11321 11322 swprintf(namev, L"\\ISA_%d", deviceExtension->DevIndex); 11323 swprintf(namex, L"Parameters%s", namev); 11324 val = AtapiRegCheckDevLunValue( 11325 HwDeviceExtension, namex, chan, dev, Name, val); 11326 11327 } else 11328 if(deviceExtension->AdapterInterfaceType == MicroChannel) { 11329 // MicroChannel 11330 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen+IsaCount); 11331 swprintf(namex, L"Parameters%s", namev); 11332 val = AtapiRegCheckDevLunValue( 11333 HwDeviceExtension, namex, chan, dev, Name, val); 11334 11335 swprintf(namev, L"\\MCA_%d", deviceExtension->DevIndex); 11336 swprintf(namex, L"Parameters%s", namev); 11337 val = AtapiRegCheckDevLunValue( 11338 HwDeviceExtension, namex, chan, dev, Name, val); 11339 11340 } 11341 } 11342 11343 KdPrint(( " Parameter %ws = %#x\n", Name, val)); 11344 return val; 11345 11346 } // end AtapiRegCheckDevValue() 11347 11348 /* 11349 The user must specify that Xxx is to run on the platform 11350 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\ 11351 Services\UniATA\Xxx:REG_DWORD:Zzz. 11352 11353 The user can override the global setting to enable or disable Xxx on a 11354 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\ 11355 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero. 11356 11357 If this registry value does not exist or contains the value zero then 11358 the timer to check for media change does not run. 11359 11360 Arguments: 11361 11362 RegistryPath - pointer to the unicode string inside 11363 ...\CurrentControlSet\Services\UniATA 11364 DeviceNumber - The number of the HBA device object 11365 11366 Returns: Registry Key value 11367 */ 11368 ULONG 11369 NTAPI 11370 AtapiRegCheckParameterValue( 11371 IN PVOID HwDeviceExtension, 11372 IN PCWSTR PathSuffix, 11373 IN PCWSTR Name, 11374 IN ULONG Default 11375 ) 11376 { 11377 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched 11378 11379 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 11380 NTSTATUS status; 11381 LONG zero = Default; 11382 11383 RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY]; 11384 11385 // LONG tmp = 0; 11386 LONG doRun = Default; 11387 11388 PUNICODE_STRING RegistryPath = &SavedRegPath; 11389 11390 UNICODE_STRING paramPath; 11391 11392 if(g_Dump) { 11393 goto failed; 11394 } 11395 11396 // <SavedRegPath>\<PathSuffix> -> <Name> 11397 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name)); 11398 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer)); 11399 11400 paramPath.Length = 0; 11401 paramPath.MaximumLength = RegistryPath->Length + 11402 (wcslen(PathSuffix)+2)*sizeof(WCHAR); 11403 paramPath.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, paramPath.MaximumLength); 11404 if(!paramPath.Buffer) { 11405 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n")); 11406 return Default; 11407 } 11408 11409 RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength); 11410 RtlAppendUnicodeToString(¶mPath, RegistryPath->Buffer); 11411 RtlAppendUnicodeToString(¶mPath, L"\\"); 11412 RtlAppendUnicodeToString(¶mPath, REGRTL_STR_PTYPE PathSuffix); 11413 11414 // Check for the Xxx value. 11415 RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY)); 11416 11417 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 11418 parameters[0].Name = REGRTL_STR_PTYPE Name; 11419 parameters[0].EntryContext = &doRun; 11420 parameters[0].DefaultType = REG_DWORD; 11421 parameters[0].DefaultData = &zero; 11422 parameters[0].DefaultLength = sizeof(ULONG); 11423 11424 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/, 11425 paramPath.Buffer, parameters, NULL, NULL); 11426 if(NT_SUCCESS(status)) { 11427 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun)); 11428 } 11429 11430 ExFreePool(paramPath.Buffer); 11431 11432 if(!NT_SUCCESS(status)) { 11433 failed: 11434 doRun = Default; 11435 } 11436 11437 return doRun; 11438 11439 #undef ITEMS_TO_QUERY 11440 11441 } // end AtapiRegCheckParameterValue() 11442 11443 11444 SCSI_ADAPTER_CONTROL_STATUS 11445 NTAPI 11446 AtapiAdapterControl( 11447 IN PVOID HwDeviceExtension, 11448 IN SCSI_ADAPTER_CONTROL_TYPE ControlType, 11449 IN PVOID Parameters 11450 ) 11451 { 11452 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 11453 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList; 11454 ULONG numberChannels = deviceExtension->NumberChannels; 11455 ULONG c; 11456 NTSTATUS status; 11457 11458 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType)); 11459 11460 switch(ControlType) { 11461 case ScsiQuerySupportedControlTypes: { 11462 BOOLEAN supportedTypes[ScsiAdapterControlMax] = { 11463 TRUE, // ScsiQuerySupportedControlTypes 11464 TRUE, // ScsiStopAdapter 11465 TRUE, // ScsiRestartAdapter 11466 FALSE, // ScsiSetBootConfig 11467 FALSE // ScsiSetRunningConfig 11468 }; 11469 11470 ULONG lim = ScsiAdapterControlMax; 11471 ULONG i; 11472 11473 pControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST) Parameters; 11474 11475 if(pControlTypeList->MaxControlType < lim) { 11476 lim = pControlTypeList->MaxControlType; 11477 } 11478 11479 for(i = 0; i < lim; i++) { 11480 pControlTypeList->SupportedTypeList[i] = supportedTypes[i]; 11481 } 11482 11483 break; 11484 11485 } 11486 case ScsiStopAdapter: { 11487 11488 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n")); 11489 // Shut down all interrupts on the adapter. They'll get re-enabled 11490 // by the initialization routines. 11491 for (c = 0; c < numberChannels; c++) { 11492 AtapiResetController(deviceExtension, c); 11493 AtapiDisableInterrupts(deviceExtension, c); 11494 } 11495 if(deviceExtension->AdapterInterfaceType == PCIBus) { 11496 // we must never get here for non-PCI 11497 /*status =*/ UniataDisconnectIntr2(HwDeviceExtension); 11498 BMList[deviceExtension->DevIndex].Isr2Enable = FALSE; 11499 } 11500 break; 11501 } 11502 case ScsiRestartAdapter: { 11503 11504 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n")); 11505 // Enable all the interrupts on the adapter while port driver call 11506 // for power up an HBA that was shut down for power management 11507 11508 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED); 11509 status = UniataConnectIntr2(HwDeviceExtension); 11510 if(NT_SUCCESS(status)) { 11511 for (c = 0; c < numberChannels; c++) { 11512 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c); 11513 FindDevices(HwDeviceExtension, 0, c); 11514 AtapiEnableInterrupts(deviceExtension, c); 11515 AtapiHwInitialize__(deviceExtension, c); 11516 } 11517 if(deviceExtension->Isr2DevObj) { 11518 // we must never get here for non-PCI 11519 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE; 11520 } 11521 } 11522 11523 break; 11524 } 11525 11526 default: { 11527 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n")); 11528 return ScsiAdapterControlUnsuccessful; 11529 } 11530 } 11531 11532 return ScsiAdapterControlSuccess; 11533 } // end AtapiAdapterControl() 11534 11535 #endif //UNIATA_CORE 11536 11537 extern "C" 11538 NTHALAPI 11539 VOID 11540 NTAPI 11541 HalDisplayString ( 11542 PUCHAR String 11543 ); 11544 11545 #define DEBUG_MSG_BUFFER_SIZE 512 11546 11547 extern "C" 11548 VOID 11549 _cdecl 11550 _PrintNtConsole( 11551 PCCH DebugMessage, 11552 ... 11553 ) 11554 { 11555 //int len; 11556 UCHAR dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE]; 11557 // UNICODE_STRING msgBuff; 11558 va_list ap; 11559 va_start(ap, DebugMessage); 11560 11561 /*len =*/ _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], DEBUG_MSG_BUFFER_SIZE-1, DebugMessage, ap); 11562 11563 dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE-1] = 0; 11564 11565 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro 11566 HalDisplayString(dbg_print_tmp_buff); 11567 11568 #ifdef _DEBUG 11569 if(g_LogToDisplay > 1) { 11570 AtapiStallExecution(g_LogToDisplay*1000); 11571 } 11572 #endif // _DEBUG 11573 11574 va_end(ap); 11575 11576 } // end PrintNtConsole() 11577 11578