ReactOS  0.4.15-dev-3446-g30010a5
id_ata.cpp
Go to the documentation of this file.
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 
68 
71 
72 #endif //UNIATA_CORE
73 
74 //UCHAR AtaCommands48[256];
75 //UCHAR AtaCommandFlags[256];
76 
79 
82 
83 #ifdef _DEBUG
85 #endif //_DEBUG
86 
88 
90 ULONG g_opt_WaitBusyCount = 200; // 20000
96 
98 
104 
106 
109 
111 
114 
115 //UCHAR EnableDma = FALSE;
116 //UCHAR EnableReorder = FALSE;
117 
119 
120 BOOLEAN
121 NTAPI
123  IN PVOID HwDeviceExtension,
124  IN ULONG PathId,
125  IN UCHAR CompleteType
126  );
127 
128 VOID
129 NTAPI
131  IN PHW_DEVICE_EXTENSION deviceExtension,
132  IN ULONG lChannel
133  );
134 
135 VOID
136 NTAPI
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
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 
164 NTAPI
166  IN PVOID HwDeviceExtension
167  );
168 
170 NTAPI
172  IN PVOID HwDeviceExtension
173  );
174 
175 VOID
176 NTAPI
178  IN PVOID HwDeviceExtension,
179  IN ULONG lChannel,
180  IN PHW_TIMER HwScsiTimer,
181  IN ULONG MiniportTimerValue
182  );
183 
185 NTAPI
187  IN PVOID HwDeviceExtension,
188  IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
190  );
191 
192 #endif //UNIATA_CORE
193 
194 #ifndef UNIATA_CORE
195 
196 BOOLEAN
197 NTAPI
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
208  UNICODE_STRING ustr;
209 
210  ustr.Buffer = Str;
211  ustr.Length =
212  ustr.MaximumLength = (USHORT)MaxLen;
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
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 
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 
331 //AtapiWritePortExN_template(USHORT, Ushort, 2);
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 
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 
401 //AtapiReadPortExN_template(USHORT, Ushort, 2);
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 
496 
499 
500 
501 UCHAR
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.
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
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.
550  (*Buffer) = data;
551  Count--;
552  Buffer++;
554  retry = FALSE;
555  } else {
556  if(i<Count && !retry) {
557  KdPrint2((PRINT_PREFIX " wait...\n"));
558  WaitForDrq(chan);
559  retry = TRUE;
560  }
561  break;
562  }
563  }
564  if(i) {
565  KdPrint2((PRINT_PREFIX "AtapiSuckPortBuffer2: %#x words\n", i ));
566  if(i==Count) {
567  AtapiSuckPort2(chan);
568  }
569  }
570  return i;
571 } // AtapiSuckPortBuffer2()
572 
573 #ifdef __REACTOS__
574 VOID
576 FillDeviceIdentificationString(
577  IN OUT PINQUIRYDATA InquiryData,
578  IN PIDENTIFY_DATA2 IdentifyData)
579 {
580  ULONG i;
581  ULONG IdentifierLen, FirstWordLen;
582 
583  /* We need to copy a field which is 20 chars long to two fields which are 8+16 bytes long (VendorId + ProductId)
584  * Note that a space will be added between those fields when displaying them.
585  * => Try to split identifier on space char.
586  */
587 
588 #define IDENTIFIER_LETTER(Identifier, i) (((PUCHAR)Identifier)[(i) ^ 1])
589 
590  for (IdentifierLen = 20; IdentifierLen > 0 && IDENTIFIER_LETTER(IdentifyData->ModelNumber, IdentifierLen - 1) == ' '; IdentifierLen--)
591  ;
592 
593  /* Strategy 1: copy first word to VendorId if len <= 8. Copy other chars to ProductId */
594  for (FirstWordLen = 0; IDENTIFIER_LETTER(IdentifyData->ModelNumber, FirstWordLen) != ' ' && FirstWordLen < IdentifierLen; FirstWordLen++)
595  ;
596  if (FirstWordLen <= 8)
597  {
598  for (i = 0; i < FirstWordLen; i++)
599  InquiryData->VendorId[i] = IDENTIFIER_LETTER(IdentifyData->ModelNumber, i);
600  for (i = FirstWordLen + 1; i < IdentifierLen; i++)
601  InquiryData->ProductId[i - FirstWordLen - 1] = IDENTIFIER_LETTER(IdentifyData->ModelNumber, i);
602  return;
603  }
604 
605  /* Strategy 2: copy everything to ProductId */
606  if (IdentifierLen <= 16)
607  {
608  for (i = 0; i < IdentifierLen; i++)
609  InquiryData->ProductId[i] = IDENTIFIER_LETTER(IdentifyData->ModelNumber, i);
610  return;
611  }
612 
613  /* Strategy 3: copy first to VendorId, then to ProductId */
614  for (i = 0; i < 24; i += 2)
615  MOV_DW_SWP(InquiryData->DeviceIdentificationString[i], ((PUCHAR)IdentifyData->ModelNumber)[i]);
616 }
617 #endif
618 
619 UCHAR
622  IN PHW_CHANNEL chan,
624  )
625 {
626  if(!chan) {
627  return 0;
628  }
629 /*
630  if(chan->lun[DeviceNumber] &&
631  (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_CHANGER)) {
632  KdPrint3((" Select %d\n", DeviceNumber));
633  }
634 */
635  if(chan->last_devsel == DeviceNumber) {
636  //KdPrint3((" Selected %d\n", DeviceNumber));
637  return 1;
638  }
640  chan->last_devsel = DeviceNumber ? 1 : 0;
642  //KdPrint3((" Select %d\n", DeviceNumber));
643  return 2;
644  }
645  //KdPrint3((" Select %d (%d ns)\n", DeviceNumber, g_opt_DriveSelectNanoDelay));
647  return 2;
648 } // end SelectDrive()
649 
650 UCHAR
653  IN PHW_CHANNEL chan
654  )
655 {
656  ULONG i;
657  UCHAR Status;
658 
659  GetStatus(chan, Status);
660  for (i=0; i<g_opt_WaitBusyCount; i++) {
661  if (Status & IDE_STATUS_BUSY) {
663  GetStatus(chan, Status);
664  continue;
665  } else {
666  break;
667  }
668  }
669  return Status;
670 } // end WaitOnBusy()
671 
672 UCHAR
675  IN PHW_CHANNEL chan
676  )
677 {
678  ULONG i;
679  UCHAR Status;
680 
681  Status = WaitOnBusy(chan);
682  if(!(Status & IDE_STATUS_BUSY))
683  return Status;
684  for (i=0; i<g_opt_WaitBusyLongCount; i++) {
685  GetStatus(chan, Status);
686  if (Status & IDE_STATUS_BUSY) {
688  continue;
689  } else {
690  break;
691  }
692  }
693  return Status;
694 } // end WaitOnBusyLong()
695 
696 UCHAR
699  IN PHW_CHANNEL chan
700  )
701 {
702  ULONG i;
704  for (i=0; i<g_opt_WaitBusyCount; i++) {
705  GetBaseStatus(chan, Status);
706  if (Status & IDE_STATUS_BUSY) {
708  continue;
709  } else {
710  break;
711  }
712  }
713  return Status;
714 } // end WaitOnBaseBusy()
715 
716 UCHAR
719  IN PHW_CHANNEL chan
720  )
721 {
722  ULONG i;
723  UCHAR Status;
724 
725  Status = WaitOnBaseBusy(chan);
726  if(!(Status & IDE_STATUS_BUSY))
727  return Status;
728  for (i=0; i<2000; i++) {
729  GetBaseStatus(chan, Status);
730  if (Status & IDE_STATUS_BUSY) {
731  AtapiStallExecution(250);
732  continue;
733  } else {
734  break;
735  }
736  }
737  return Status;
738 } // end WaitOnBaseBusyLong()
739 
740 UCHAR
743  IN struct _HW_DEVICE_EXTENSION* deviceExtension,
744  IN UCHAR Status
745  )
746 {
747  UCHAR Status2;
748 
749  if(Status == IDE_STATUS_WRONG) {
750  return IDE_STATUS_WRONG;
751  }
752  if(Status & IDE_STATUS_BUSY) {
753  return Status;
754  }
755 // if(deviceExtension->HwFlags & UNIATA_SATA) {
756  if(UniataIsSATARangeAvailable(deviceExtension, 0)) {
758  return Status;
759  }
760  } else {
761  Status2 = Status & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX);
762  if ((Status & IDE_STATUS_BUSY) ||
763  (Status2 != IDE_STATUS_IDLE && Status2 != IDE_STATUS_DRDY)) {
764  return Status;
765  }
766  }
767  return IDE_STATUS_IDLE;
768 } // end UniataIsIdle()
769 
770 UCHAR
773  IN PHW_CHANNEL chan
774  )
775 {
776  ULONG i;
777  UCHAR Status;
778  UCHAR Status2;
779  for (i=0; i<20000; i++) {
780  GetStatus(chan, Status);
781  Status2 = UniataIsIdle(chan->DeviceExtension, Status);
782  if(Status2 == IDE_STATUS_WRONG) {
783  // no drive ?
784  break;
785  } else
786  if(Status2 & IDE_STATUS_BUSY) {
788  continue;
789  } else {
790  break;
791  }
792  }
793  return Status;
794 } // end WaitForIdleLong()
795 
796 UCHAR
799  IN PHW_CHANNEL chan
800  )
801 {
802  ULONG i;
803  UCHAR Status;
804  for (i=0; i<1000; i++) {
805  GetStatus(chan, Status);
806  if (Status & IDE_STATUS_BUSY) {
808  } else if (Status & IDE_STATUS_DRQ) {
809  break;
810  } else {
812  }
813  }
814  return Status;
815 } // end WaitForDrq()
816 
817 UCHAR
820  IN PHW_CHANNEL chan
821  )
822 {
823  ULONG i;
824  UCHAR Status;
825  for (i=0; i<2; i++) {
826  GetStatus(chan, Status);
827  if (Status & IDE_STATUS_BUSY) {
829  } else if (Status & IDE_STATUS_DRQ) {
830  break;
831  } else {
833  }
834  }
835  return Status;
836 } // end WaitShortForDrq()
837 
838 VOID
841  IN PHW_CHANNEL chan,
843  )
844 {
845  //ULONG c = chan->lChannel;
846  ULONG i = 30 * 1000;
847  UCHAR dma_status = 0;
848  KdPrint2((PRINT_PREFIX "AtapiSoftReset:\n"));
849  UCHAR statusByte0, statusByte2;
850 
851  if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
852  UniataAhciSoftReset(chan->DeviceExtension, chan->lChannel, DeviceNumber);
853  return;
854  }
855 
856  GetBaseStatus(chan, statusByte2);
857  KdPrint2((PRINT_PREFIX " statusByte2 %x:\n", statusByte2));
858  SelectDrive(chan, DeviceNumber);
859  if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MANUAL_CHS) {
860  // For ESDI/MFM
861  KdPrint2((PRINT_PREFIX " ESDI/MFM\n"));
862  AtapiStallExecution(10000);
863  for (i = 0; i < 1000; i++) {
864  AtapiStallExecution(999);
865  }
866 /* } else
867  // Seems to be unnecessary, verified by KtP
868  if(!hasPCI) {
869  // original atapi.sys behavior for old ISA-only hardware
870  AtapiStallExecution(10000);
871  AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
872  for (i = 0; i < 1000; i++) {
873  AtapiStallExecution(999);
874  } */
875  } else {
876  AtapiStallExecution(500);
877  GetBaseStatus(chan, statusByte2);
878  statusByte0 = statusByte2;
880 
881  // Do not wait for BUSY assertion if it was initially set, jump to
882  // BUSY release wait loop
883  if(!(statusByte0 & IDE_STATUS_BUSY)) {
884  // Wait for BUSY assertion, in some cases delay may occure
885  // 100ms should be enough
887  i = 100;
888  } else {
889  i = 10*1000;
890  }
891  statusByte2 = AtapiReadPort1(chan, IDX_IO1_i_Status);
892  while (!(statusByte2 & IDE_STATUS_BUSY) &&
893  i--)
894  {
895  if(!(statusByte0 & IDE_STATUS_ERROR) && (statusByte2 & IDE_STATUS_ERROR)) {
896  KdPrint2((PRINT_PREFIX " Command aborted, statusByte2 %x:\n", statusByte2));
897  break;
898  }
900  }
901  }
902 
903  i = 30 * 1000;
904  // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
905  // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
906  // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
907  // implementation. (which is around 1 second)
908  while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
909  i--)
910  {
912  }
913  KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n"));
914  chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_REINIT_DMA;
915  }
916 
917  chan->last_devsel = -1; // make sure proper drive would be selected
918  SelectDrive(chan, DeviceNumber);
919  WaitOnBusy(chan);
920  GetBaseStatus(chan, statusByte2);
921  AtapiStallExecution(500);
922 
923  GetBaseStatus(chan, statusByte2);
924  if(chan && chan->DeviceExtension) {
925  dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
926  KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
927  } else {
928  KdPrint2((PRINT_PREFIX " can't get DMA status\n"));
929  }
930  if(dma_status & BM_STATUS_INTR) {
931  // bullshit, we have DMA interrupt, but had never initiate DMA operation
932  KdPrint2((PRINT_PREFIX " clear unexpected DMA intr on ATAPI reset\n"));
933  AtapiDmaDone(chan->DeviceExtension, DeviceNumber, chan->lChannel, NULL);
934  GetBaseStatus(chan, statusByte2);
935  }
936  if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
937  UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, DeviceNumber);
938 /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
939  UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
940  }*/
941  }
942  return;
943 
944 } // end AtapiSoftReset()
945 
946 VOID
949  IN struct _HW_CHANNEL* chan,
950  IN BOOLEAN DisableInterrupts,
951  IN ULONG Delay
952  )
953 {
954  KdPrint2((PRINT_PREFIX "AtapiHardReset: %d, dis=%d\n", Delay, DisableInterrupts));
956  (DisableInterrupts ? IDE_DC_DISABLE_INTERRUPTS : 0));
957  chan->last_devsel = -1;
958  AtapiStallExecution(Delay);
960 } // end AtapiHardReset()
961 
962 /*
963  Send command to device.
964  Translate to 48-Lba form if required
965 */
966 UCHAR
967 NTAPI
969  IN PHW_DEVICE_EXTENSION deviceExtension,
971  IN ULONG lChannel,
972  IN UCHAR command,
973  IN ULONGLONG lba,
974  IN USHORT count,
975  IN USHORT feature,
976  IN ULONG wait_flags
977  )
978 {
979  PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
980  UCHAR statusByte;
981  ULONG i;
982  PUCHAR plba;
983 
984  KdPrint2((PRINT_PREFIX "AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
985  deviceExtension->DevIndex, deviceExtension->Channel, DeviceNumber, command, lba, count, feature ));
986 
987  if(deviceExtension->HwFlags & UNIATA_AHCI) {
988  //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
989 
990  KdPrint3((" (ahci)\n"));
991 
992  statusByte = UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
994  NULL,
995  0,
996  command,
997  lba, count,
998  feature,
999  0 /* ahci flags */ ,
1000  wait_flags,
1001  1000 /* timeout 1 sec */
1002  );
1003 
1004  return statusByte;
1005  }
1006 
1007  SelectDrive(chan, DeviceNumber);
1008 
1009  statusByte = WaitOnBusy(chan);
1010 
1011  /* ready to issue command ? */
1012  if (statusByte & IDE_STATUS_BUSY) {
1013  KdPrint2((PRINT_PREFIX " Returning BUSY status\n"));
1014  return statusByte;
1015  }
1016  // !!! We should not check ERROR condition here
1017  // ERROR bit may be asserted durring previous operation
1018  // and not cleared after SELECT
1019 
1020  //>>>>>> NV: 2006/08/03
1023  KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
1024  return IDE_STATUS_ERROR;
1025  //return SRB_STATUS_ERROR;
1026  }
1027  //<<<<<< NV: 2006/08/03
1028 
1029  /* only use 48bit addressing if needed because of the overhead */
1031  chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48)) {
1032 
1033  KdPrint2((PRINT_PREFIX " dev %#x USE_LBA_48\n", DeviceNumber ));
1034  /* translate command into 48bit version */
1037  } else {
1038  KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n"));
1039  return (UCHAR)-1;
1040  }
1041 
1043  plba = (PUCHAR)&lba;
1044 
1049  AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[3]));
1050  AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[0]));
1051  AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[4]));
1052  AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[1]));
1053  AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[5]));
1054  AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[2]));
1055 
1056  //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
1058  } else {
1059 
1060  plba = (PUCHAR)&lba; //ktp
1061  chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
1062 
1063  //if(feature ||
1064  // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
1066  //}
1068  AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)plba[0]);
1069  AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)plba[1]);
1070  AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)plba[2]);
1071  if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) {
1072  //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
1074  } else {
1075  //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
1077  }
1078  }
1079 
1080  // write command code to device
1082 
1083  switch (wait_flags) {
1084  case ATA_WAIT_INTR:
1085 
1086  // caller requested wait for interrupt
1087  for(i=0;i<4;i++) {
1088  WaitOnBusy(chan);
1089  statusByte = WaitForDrq(chan);
1090  if (statusByte & IDE_STATUS_DRQ)
1091  break;
1092  AtapiStallExecution(500);
1093  KdPrint2((PRINT_PREFIX " retry waiting DRQ, status %#x\n", statusByte));
1094  }
1095 
1096  return statusByte;
1097 
1098  case ATA_WAIT_IDLE:
1099 
1100  // caller requested wait for entering Wait state
1101  for (i=0; i<30 * 1000; i++) {
1102 
1103  GetStatus(chan, statusByte);
1104  statusByte = UniataIsIdle(deviceExtension, statusByte);
1105  if(statusByte == IDE_STATUS_WRONG) {
1106  // no drive ?
1107  break;
1108  } else
1109  if(statusByte & IDE_STATUS_ERROR) {
1110  break;
1111  } else
1112  if(statusByte & IDE_STATUS_BUSY) {
1113  AtapiStallExecution(100);
1114  continue;
1115  } else
1116  if((statusByte & ~IDE_STATUS_INDEX) == IDE_STATUS_IDLE) {
1117  break;
1118  } else {
1119  //if(deviceExtension->HwFlags & UNIATA_SATA) {
1120  if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1121  break;
1122  }
1123  AtapiStallExecution(100);
1124  }
1125  }
1126  //statusByte |= IDE_STATUS_BUSY;
1127  break;
1128 
1129  case ATA_WAIT_READY:
1130  statusByte = WaitOnBusyLong(chan);
1131  break;
1132  case ATA_WAIT_BASE_READY:
1133  statusByte = WaitOnBaseBusyLong(chan);
1134  break;
1135  case ATA_IMMEDIATE:
1136  GetStatus(chan, statusByte);
1137  if (statusByte & IDE_STATUS_ERROR) {
1138  KdPrint2((PRINT_PREFIX " Warning: Immed Status %#x :(\n", statusByte));
1139  if(statusByte == (IDE_STATUS_IDLE | IDE_STATUS_ERROR)) {
1140  break;
1141  }
1142  KdPrint2((PRINT_PREFIX " try to continue\n"));
1143  statusByte &= ~IDE_STATUS_ERROR;
1144 
1145  } else {
1146  //KdPrint2((PRINT_PREFIX " send Status %#x\n", statusByte));
1147  }
1149  // !!!!!
1150  InterlockedExchange(&(chan->CheckIntr),
1151  CHECK_INTR_IDLE);
1152 
1153  statusByte = IDE_STATUS_SUCCESS;
1154  break;
1155  }
1156 
1157  //KdPrint2((PRINT_PREFIX " Status %#x\n", statusByte));
1158 
1159  return statusByte;
1160 } // end AtaCommand48()
1161 
1162 /*
1163  Send command to device.
1164  This is simply wrapper for AtaCommand48()
1165 */
1166 UCHAR
1167 NTAPI
1169  IN PHW_DEVICE_EXTENSION deviceExtension,
1171  IN ULONG lChannel,
1172  IN UCHAR command,
1173  IN USHORT cylinder,
1174  IN UCHAR head,
1175  IN UCHAR sector,
1176  IN UCHAR count,
1177  IN UCHAR feature,
1178  IN ULONG wait_flags
1179  )
1180 {
1181  if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
1182  return AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1183  command,
1184  (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
1185  count, feature, wait_flags);
1186  } else {
1187  return UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
1189  NULL,
1190  0,
1191  command,
1192  (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
1193  count,
1194  feature,
1195  0 /* ahci flags */ ,
1196  wait_flags,
1197  1000 /* timeout 1 sec */
1198  );
1199 
1200  }
1201 } // end AtaCommand()
1202 
1203 LONG
1204 NTAPI
1206 {
1207  switch (pio) {
1208  default: return ATA_PIO;
1209  case 0: return ATA_PIO0;
1210  case 1: return ATA_PIO1;
1211  case 2: return ATA_PIO2;
1212  case 3: return ATA_PIO3;
1213  case 4: return ATA_PIO4;
1214  case 5: return ATA_PIO5;
1215  }
1216 } // end AtaPio2Mode()
1217 
1218 LONG
1219 NTAPI
1221 {
1222  if (ident->PioTimingsValid) {
1223  if (ident->AdvancedPIOModes & AdvancedPIOModes_5)
1224  return 5;
1225  if (ident->AdvancedPIOModes & AdvancedPIOModes_4)
1226  return 4;
1227  if (ident->AdvancedPIOModes & AdvancedPIOModes_3)
1228  return 3;
1229  }
1230  if (ident->PioCycleTimingMode == 2)
1231  return 2;
1232  if (ident->PioCycleTimingMode == 1)
1233  return 1;
1234  if (ident->PioCycleTimingMode == 0)
1235  return 0;
1236  return IOMODE_NOT_SPECIFIED;
1237 } // end AtaPioMode()
1238 
1239 LONG
1240 NTAPI
1242 {
1243  if (ident->MultiWordDMASupport & 0x04)
1244  return 2;
1245  if (ident->MultiWordDMASupport & 0x02)
1246  return 1;
1247  if (ident->MultiWordDMASupport & 0x01)
1248  return 0;
1249  return IOMODE_NOT_SPECIFIED;
1250 } // end AtaWmode()
1251 
1252 LONG
1253 NTAPI
1255 {
1256  if (!ident->UdmaModesValid)
1257  return IOMODE_NOT_SPECIFIED;
1258  if (ident->UltraDMASupport & 0x40)
1259  return 6;
1260  if (ident->UltraDMASupport & 0x20)
1261  return 5;
1262  if (ident->UltraDMASupport & 0x10)
1263  return 4;
1264  if (ident->UltraDMASupport & 0x08)
1265  return 3;
1266  if (ident->UltraDMASupport & 0x04)
1267  return 2;
1268  if (ident->UltraDMASupport & 0x02)
1269  return 1;
1270  if (ident->UltraDMASupport & 0x01)
1271  return 0;
1272  return IOMODE_NOT_SPECIFIED;
1273 } // end AtaUmode()
1274 
1275 LONG
1276 NTAPI
1278  if(!ident->SataCapabilities ||
1279  ident->SataCapabilities == 0xffff) {
1280  return IOMODE_NOT_SPECIFIED;
1281  }
1282  if(ident->SataCapabilities & ATA_SATA_GEN3) {
1283  return ATA_SA600;
1284  } else
1285  if(ident->SataCapabilities & ATA_SATA_GEN2) {
1286  return ATA_SA300;
1287  } else
1288  if(ident->SataCapabilities & ATA_SATA_GEN1) {
1289  return ATA_SA150;
1290  }
1291  return IOMODE_NOT_SPECIFIED;
1292 } // end AtaSAmode()
1293 
1294 #ifndef UNIATA_CORE
1295 
1296 VOID
1297 NTAPI
1299  IN PVOID HwDeviceExtension
1300  )
1301 {
1302  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1303  PHW_TIMER HwScsiTimer;
1305  ULONG MiniportTimerValue;
1306  BOOLEAN recall = FALSE;
1307  ULONG lChannel;
1308  PHW_CHANNEL chan;
1309 
1310  KdPrint2((PRINT_PREFIX "AtapiTimerDpc:\n"));
1311 
1312  lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
1313  if(lChannel == CHAN_NOT_SPECIFIED) {
1314  KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no items\n"));
1315  return;
1316  }
1317  chan = &(deviceExtension->chan[lChannel]);
1318 
1319  while(TRUE) {
1320 
1321  HwScsiTimer = chan->HwScsiTimer;
1322  chan->HwScsiTimer = NULL;
1323 
1324  deviceExtension->FirstDpcChan = chan->NextDpcChan;
1325  if(deviceExtension->FirstDpcChan != CHAN_NOT_SPECIFIED) {
1326  recall = TRUE;
1327  }
1328 
1329  HwScsiTimer(HwDeviceExtension);
1330 
1332 
1333  lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
1334  if(lChannel == CHAN_NOT_SPECIFIED) {
1335  KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no more items\n"));
1336  deviceExtension->FirstDpcChan =
1337  deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
1338  return;
1339  }
1340 
1342  KdPrint2((PRINT_PREFIX "AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
1343 
1344  chan = &deviceExtension->chan[lChannel];
1345  if(time.QuadPart >= chan->DpcTime - 10) {
1346  // call now
1347  KdPrint2((PRINT_PREFIX "AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1348  (ULONG)(chan->DpcTime >> 32), (ULONG)(chan->DpcTime)));
1349  continue;
1350  }
1351  break;
1352  }
1353 
1354  if(recall) {
1355  deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
1356  MiniportTimerValue = (ULONG)(time.QuadPart - chan->DpcTime)/10;
1357  if(!MiniportTimerValue)
1358  MiniportTimerValue = 1;
1359 
1360  KdPrint2((PRINT_PREFIX "AtapiTimerDpc: recall AtapiTimerDpc\n"));
1361  ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
1362  AtapiTimerDpc,
1363  MiniportTimerValue
1364  );
1365  }
1366  return;
1367 
1368 } // end AtapiTimerDpc()
1369 
1370 /*
1371  Wrapper for ScsiPort, that implements smart Dpc
1372  queueing. We need it to allow parallel functioning
1373  of IDE channels with shared interrupt. Standard Dpc mechanism
1374  cancels previous Dpc request (if any), but we need Dpc queue.
1375 */
1376 VOID
1377 NTAPI
1379  IN PVOID HwDeviceExtension,
1380  IN ULONG lChannel,
1381  IN PHW_TIMER HwScsiTimer,
1382  IN ULONG MiniportTimerValue
1383  )
1384 {
1385  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1387  LARGE_INTEGER time2;
1388  ULONG i;
1389  PHW_CHANNEL prev_chan;
1390  PHW_CHANNEL chan;
1391 // BOOLEAN UseRequestTimerCall = TRUE;
1392 
1393  KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
1395  time2 = time;
1396  KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
1397  time.QuadPart += MiniportTimerValue*10;
1398  KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time.HighPart, time.LowPart));
1399 
1400  KdPrint2((PRINT_PREFIX " ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension->ActiveDpcChan, deviceExtension->FirstDpcChan));
1401 
1402  i = deviceExtension->FirstDpcChan;
1403  chan = prev_chan = NULL;
1404  while(i != CHAN_NOT_SPECIFIED) {
1405  prev_chan = chan;
1406  chan = &(deviceExtension->chan[i]);
1407  if(chan->DpcTime > time.QuadPart) {
1408  break;
1409  }
1410  i = chan->NextDpcChan;
1411  }
1412  chan = &(deviceExtension->chan[lChannel]);
1413  if(!prev_chan) {
1414  deviceExtension->FirstDpcChan = lChannel;
1415  } else {
1416  prev_chan->NextDpcChan = lChannel;
1417  }
1418  chan->NextDpcChan = i;
1419  chan->HwScsiTimer = HwScsiTimer;
1420  chan->DpcTime = time.QuadPart;
1421 
1422  KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2.HighPart, time2.LowPart));
1423  if(time.QuadPart <= time2.QuadPart) {
1424  MiniportTimerValue = 1;
1425  } else {
1426  MiniportTimerValue = (ULONG)((time.QuadPart - time2.QuadPart) / 10);
1427  }
1428 
1429  KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
1430  ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
1431  AtapiTimerDpc,
1432  MiniportTimerValue);
1433 
1434 } // end AtapiQueueTimerDpc()
1435 
1436 #endif //UNIATA_CORE
1437 
1438 #ifdef _DEBUG
1439 VOID
1440 NTAPI
1442  IN PHW_CHANNEL chan
1443  )
1444 {
1445  ULONG j;
1446  UCHAR statusByteAlt;
1447 
1448  GetStatus(chan, statusByteAlt);
1449  KdPrint2((PRINT_PREFIX " AltStatus (%#x)\n", statusByteAlt));
1450 
1451  for(j=1; j<IDX_IO1_SZ; j++) {
1452  statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1454  " Reg_%#x (%#x) = %#x\n",
1455  j,
1456  chan->RegTranslation[IDX_IO1+j].Addr,
1457  statusByteAlt));
1458  }
1459  if(!chan->RegTranslation[IDX_BM_IO].Addr) {
1460  return;
1461  }
1462  for(j=0; j<IDX_BM_IO_SZ-1; j++) {
1463  statusByteAlt = AtapiReadPort1(chan, IDX_BM_IO+j);
1465  " BM_%#x (%#x) = %#x\n",
1466  j,
1467  chan->RegTranslation[IDX_BM_IO+j].Addr,
1468  statusByteAlt));
1469  }
1470  return;
1471 } // end UniataDumpATARegs()
1472 #endif //_DEBUG
1473 
1474 VOID
1475 NTAPI
1477  IN PHW_CHANNEL chan,
1480  )
1481 {
1482  if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
1483  // AHCI
1485  } else {
1486  // SATA/PATA, assume drive is selected
1487  ULONG j;
1488  UCHAR statusByteAlt;
1489 
1490  if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {
1491  for(j=IDX_IO1_i_Error; j<=IDX_IO1_i_Status; j++) {
1492  statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1493  ((PUCHAR)regs)[j-1] = statusByteAlt;
1494  }
1495  regs->bOpFlags = 0;
1496  } else {
1497  regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
1499  statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1500  ((PUCHAR)regs)[j-1] = statusByteAlt;
1501  statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1502  ((PUCHAR)regs)[j+8-1] = statusByteAlt;
1503  }
1504  regs->bCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status);
1505  }
1506  }
1507  return;
1508 } // end UniataSnapAtaRegs()
1509 
1510 /*++
1511 
1512 Routine Description:
1513 
1514  Issue IDENTIFY command to a device.
1515 
1516 Arguments:
1517 
1518  HwDeviceExtension - HBA miniport driver's adapter data storage
1519  DeviceNumber - Indicates which device.
1520  Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1521 
1522 Return Value:
1523 
1524  TRUE if all goes well.
1525 
1526 --*/
1527 BOOLEAN
1528 NTAPI
1530  IN PVOID HwDeviceExtension,
1532  IN ULONG lChannel,
1533  IN UCHAR Command,
1534  IN BOOLEAN NoSetup
1535  )
1536 {
1537  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1538  PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
1539  ULONG waitCount = 50000;
1540  ULONG j;
1541  UCHAR statusByte;
1542  //UCHAR statusByte2;
1543  UCHAR signatureLow,
1544  signatureHigh;
1545  BOOLEAN atapiDev = FALSE;
1546  BOOLEAN use_ahci = FALSE;
1547  PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
1548 
1549  use_ahci = UniataIsSATARangeAvailable(deviceExtension, lChannel) &&
1550  (deviceExtension->HwFlags & UNIATA_AHCI);
1551 
1552  if(chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) {
1553  if(chan->PmLunMap & (1 << DeviceNumber)) {
1554  // OK
1555  } else {
1556  KdPrint2((PRINT_PREFIX "IssueIdentify: PM empty port\n"));
1557  return FALSE;
1558  }
1559  } else
1561  KdPrint2((PRINT_PREFIX "IssueIdentify: NO SLAVE\n"));
1562  return FALSE;
1563  }
1564  if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
1565  KdPrint2((PRINT_PREFIX "IssueIdentify: HIDDEN\n"));
1566  return FALSE;
1567  }
1568 
1569  if(use_ahci) {
1570  statusByte = WaitOnBusyLong(chan);
1571 #ifdef _DEBUG
1572  if(!chan->AhciInternalAtaReq) {
1573  KdPrint2((PRINT_PREFIX "!AhciInternalAtaReq\n"));
1574  }
1575 #endif
1576  } else {
1577  SelectDrive(chan, DeviceNumber);
1578  AtapiStallExecution(10);
1579  statusByte = WaitOnBusyLong(chan);
1580  // Check that the status register makes sense.
1581  GetBaseStatus(chan, statusByte);
1582  /*
1583  // unnecessary
1584  if(!hasPCI) {
1585  // original atapi.sys behavior for old ISA-only hardware
1586  AtapiStallExecution(100);
1587  }
1588  */
1589  }
1590 
1591  if (Command == IDE_COMMAND_IDENTIFY) {
1592  // Mask status byte ERROR bits.
1593  statusByte = UniataIsIdle(deviceExtension, statusByte & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX));
1594  KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte));
1595  // Check if register value is reasonable.
1596 
1597  if(statusByte != IDE_STATUS_IDLE) {
1598 
1599  // No reset here !!!
1600  KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1601 
1602  //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1603  if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1604  SelectDrive(chan, DeviceNumber);
1605  WaitOnBusyLong(chan);
1606 
1607  signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1608  signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1609 
1610  if (signatureLow == ATAPI_MAGIC_LSB &&
1611  signatureHigh == ATAPI_MAGIC_MSB) {
1612  // Device is Atapi.
1613  KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber));
1614  return FALSE;
1615  }
1616 
1617  // We really should wait up to 31 seconds
1618  // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1619  // (30 seconds for device 1)
1620  do {
1621  // Wait for Busy to drop.
1622  AtapiStallExecution(100);
1623  GetStatus(chan, statusByte);
1624  if(statusByte == IDE_STATUS_WRONG) {
1625  KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber));
1626  return FALSE;
1627  }
1628 
1629  } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
1630  GetBaseStatus(chan, statusByte);
1631 
1632  SelectDrive(chan, DeviceNumber);
1633  } else {
1634  GetBaseStatus(chan, statusByte);
1635  }
1636  // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1637  // a soft reset.
1638  signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1639  signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1640 
1641  if (signatureLow == ATAPI_MAGIC_LSB &&
1642  signatureHigh == ATAPI_MAGIC_MSB) {
1643  KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber));
1644  // Device is Atapi.
1645  return FALSE;
1646  }
1647 
1648  statusByte = UniataIsIdle(deviceExtension, statusByte) & ~IDE_STATUS_INDEX;
1649  if (statusByte != IDE_STATUS_IDLE) {
1650  // Give up on this.
1651  KdPrint2((PRINT_PREFIX "IssueIdentify: no dev (dev %d)\n", DeviceNumber));
1652  return FALSE;
1653  }
1654  }
1655  } else {
1656  KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte));
1657  if(statusByte == IDE_STATUS_WRONG) {
1658  return FALSE;
1659  }
1660  //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1661  if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1662  statusByte = WaitForIdleLong(chan);
1663  KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte));
1664  }
1665  atapiDev = TRUE;
1666  }
1667 
1668 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1669  if(use_ahci) {
1670  statusByte = UniataAhciSendPIOCommand(HwDeviceExtension, lChannel, DeviceNumber,
1672  (PUCHAR)(&deviceExtension->FullIdentifyData),
1673  DEV_BSIZE,
1674  Command,
1675  0, 0,
1676  0,
1677  0 /* ahci flags */ ,
1678  ATA_WAIT_INTR,
1679  1000 /* timeout 1 sec */
1680  );
1681  j = 9; // AHCI is rather different, skip loop at all
1682  } else
1683  if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
1684  j = 9; // don't send IDENTIFY, assume it is not supported
1685  KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS\n"));
1686  RtlZeroMemory(&(deviceExtension->FullIdentifyData), sizeof(deviceExtension->FullIdentifyData));
1687  RtlCopyMemory(&(deviceExtension->FullIdentifyData), &(LunExt->IdentifyData), sizeof(LunExt->IdentifyData));
1688  } else
1689  if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1690  j = 4; // skip old-style checks
1691  } else {
1692  j = 0;
1693  }
1694  for (; j < 4*2; j++) {
1695  // Send IDENTIFY command.
1696 
1697  // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
1698 
1699  statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, (j < 4) ? DEV_BSIZE : 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR);
1700  // Clear interrupt
1701 
1702  if (!statusByte) {
1703  KdPrint2((PRINT_PREFIX "IssueIdentify: 0-status, not present\n"));
1704  return FALSE;
1705  } else
1706  if (statusByte & IDE_STATUS_DRQ) {
1707  // Read status to acknowledge any interrupts generated.
1708  KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte));
1709  GetBaseStatus(chan, statusByte);
1710  // One last check for Atapi.
1711  if (Command == IDE_COMMAND_IDENTIFY) {
1712  signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1713  signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1714 
1715  if (signatureLow == ATAPI_MAGIC_LSB &&
1716  signatureHigh == ATAPI_MAGIC_MSB) {
1717  KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber));
1718  // Device is Atapi.
1719  return FALSE;
1720  }
1721  }
1722  break;
1723  } else {
1724  KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte));
1725  if (Command == IDE_COMMAND_IDENTIFY) {
1726  // Check the signature. If DRQ didn't come up it's likely Atapi.
1727  signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1728  signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1729 
1730  if (signatureLow == ATAPI_MAGIC_LSB &&
1731  signatureHigh == ATAPI_MAGIC_MSB) {
1732  // Device is Atapi.
1733  KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber));
1734  return FALSE;
1735  }
1736  } else {
1737  if(!(statusByte & IDE_STATUS_ERROR) && (statusByte & IDE_STATUS_BUSY)) {
1738  KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1739  break;
1740  }
1741  }
1742  // Device didn't respond correctly. It will be given one more chance.
1743  KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1744  statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error)));
1745  GetBaseStatus(chan, statusByte);
1747 
1748  AtapiDisableInterrupts(deviceExtension, lChannel);
1749  AtapiEnableInterrupts(deviceExtension, lChannel);
1750 
1751  GetBaseStatus(chan, statusByte);
1752  //GetStatus(chan, statusByte);
1753  KdPrint2((PRINT_PREFIX "IssueIdentify: Status after soft reset (%#x)\n", statusByte));
1754  }
1755  }
1756  // Check for error on really stupid master devices that assert random
1757  // patterns of bits in the status register at the slave address.
1758  if ((Command == IDE_COMMAND_IDENTIFY) && (statusByte & IDE_STATUS_ERROR)) {
1759  KdPrint2((PRINT_PREFIX "IssueIdentify: Exit on error (%#x)\n", statusByte));
1760  return FALSE;
1761  }
1762 
1763  if(use_ahci) {
1764  // everything should already be done by controller
1765  } else
1766  if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
1767  j = 9; // don't send IDENTIFY, assume it is not supported
1768  KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS (2)\n"));
1769  statusByte = WaitForDrq(chan);
1770  statusByte = WaitOnBusyLong(chan);
1771  KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1772  GetBaseStatus(chan, statusByte);
1773  } else {
1774 
1775  KdPrint2((PRINT_PREFIX "IssueIdentify: Status before read words %#x\n", statusByte));
1776  // Suck out 256 words. After waiting for one model that asserts busy
1777  // after receiving the Packet Identify command.
1778  statusByte = WaitForDrq(chan);
1779  statusByte = WaitOnBusyLong(chan);
1780  KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1781 
1782  if (!(statusByte & IDE_STATUS_DRQ)) {
1783  KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte));
1784  GetBaseStatus(chan, statusByte);
1785  return FALSE;
1786  }
1787  GetBaseStatus(chan, statusByte);
1788  KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte));
1789 
1790 #ifdef _DEBUG
1791  if(atapiDev) {
1793  KdPrint3((PRINT_PREFIX "IssueIdentify: iReason %x\n", j));
1794 
1795  j =
1797 
1798  j |=
1800  KdPrint3((PRINT_PREFIX "IssueIdentify: wCount %x\n", j));
1801 
1802  }
1803 #endif //_DEBUG
1804 
1805  if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) ) {
1806 
1807  KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
1808  // ATI/SII chipsets with memory-mapped IO hangs when
1809  // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1810  // Unfortunately, I don't know yet how to workaround it except
1811  // spacifying manual delay in the way you see below.
1812  ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
1813 
1814  // Work around for some IDE and one model Atapi that will present more than
1815  // 256 bytes for the Identify data.
1816  KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
1817  statusByte = AtapiSuckPort2(chan);
1818  } else {
1819  KdPrint2((PRINT_PREFIX " use 32bit IO\n"));
1820  ReadBuffer2(chan, (PULONG)&deviceExtension->FullIdentifyData, 256/2, PIO0_TIMING);
1821  }
1822 
1823  KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1824  statusByte = WaitForDrq(chan);
1825  KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1826  GetBaseStatus(chan, statusByte);
1827  }
1828  KdPrint2((PRINT_PREFIX "IssueIdentify: Status after read words %#x\n", statusByte));
1829 
1830  if(NoSetup) {
1831  KdPrint2((PRINT_PREFIX "IssueIdentify: no setup, exiting\n"));
1832  return TRUE;
1833  }
1834 
1835  KdPrint2((PRINT_PREFIX "Model: %20.20s\n", deviceExtension->FullIdentifyData.ModelNumber));
1836  KdPrint2((PRINT_PREFIX "FW: %4.4s\n", deviceExtension->FullIdentifyData.FirmwareRevision));
1837  KdPrint2((PRINT_PREFIX "S/N: %20.20s\n", deviceExtension->FullIdentifyData.SerialNumber));
1838  if(g_opt_VirtualMachine == VM_AUTO) {
1839  if((deviceExtension->FullIdentifyData.FirmwareRevision[0] == 0 ||
1840  deviceExtension->FullIdentifyData.FirmwareRevision[0] == ' ') &&
1841  (deviceExtension->FullIdentifyData.FirmwareRevision[1] == 0 ||
1842  deviceExtension->FullIdentifyData.FirmwareRevision[1] == ' ')) {
1843  // Check for BOCHS VM signature. If no additional PCI devices (e.g. VGA)
1844  // are declared BOCHS looks like regular PC
1845  if (!atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDH00", 6)) {
1846  KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS HDD\n"));
1848  } else
1849  if (atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDC00", 6)) {
1850  KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS CD\n"));
1852  }
1853  }
1854  }
1855 
1856  KdPrint2((PRINT_PREFIX "Pio: %x\n", deviceExtension->FullIdentifyData.PioCycleTimingMode));
1857  if(deviceExtension->FullIdentifyData.PioTimingsValid) {
1858  KdPrint2((PRINT_PREFIX "APio: %x\n", deviceExtension->FullIdentifyData.AdvancedPIOModes));
1859  }
1860  KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive));
1861  KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive));
1862  if(deviceExtension->FullIdentifyData.UdmaModesValid) {
1863  KdPrint2((PRINT_PREFIX "UDMA: %x/%x\n", deviceExtension->FullIdentifyData.UltraDMAActive, deviceExtension->FullIdentifyData.UltraDMASupport));
1864  }
1865  KdPrint2((PRINT_PREFIX "SATA: %x\n", deviceExtension->FullIdentifyData.SataEnable));
1866  KdPrint2((PRINT_PREFIX "SATA support: %x, CAPs %#x\n",
1867  deviceExtension->FullIdentifyData.SataSupport,
1868  deviceExtension->FullIdentifyData.SataCapabilities));
1869 
1870  LunExt->LimitedTransferMode =
1871  LunExt->OrigTransferMode =
1873  LunExt->TransferMode =
1875 
1876  KdPrint2((PRINT_PREFIX "OrigTransferMode: %x, Active: %x\n", LunExt->OrigTransferMode, LunExt->TransferMode));
1877  KdPrint2((PRINT_PREFIX "Accoustic %d, cur %d\n",
1878  deviceExtension->FullIdentifyData.VendorAcoustic,
1879  deviceExtension->FullIdentifyData.CurrentAcoustic
1880  ));
1881  KdPrint2((PRINT_PREFIX "AdvPowerMode %d\n",
1882  deviceExtension->FullIdentifyData.CfAdvPowerMode
1883  ));
1884 
1885  KdPrint2((PRINT_PREFIX "PowerMngt %d/%d, APM %d/%d\n",
1886  deviceExtension->FullIdentifyData.FeaturesEnabled.PowerMngt,
1887  deviceExtension->FullIdentifyData.FeaturesSupport.PowerMngt,
1888  deviceExtension->FullIdentifyData.FeaturesEnabled.APM,
1889  deviceExtension->FullIdentifyData.FeaturesSupport.APM
1890  ));
1891 
1892  // Check out a few capabilities / limitations of the device.
1893  if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
1894  // Determine if this drive supports the MSN functions.
1895  KdPrint2((PRINT_PREFIX "IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1896  DeviceNumber,
1897  deviceExtension->FullIdentifyData.RemovableStatus));
1899  }
1900  if(use_ahci) {
1901  // AHCI doesn't recommend using PIO and multiblock
1902  LunExt->MaximumBlockXfer = 0;
1903  } else
1904  if (deviceExtension->FullIdentifyData.MaximumBlockTransfer) {
1905  // Determine max. block transfer for this device.
1906  LunExt->MaximumBlockXfer =
1907  (UCHAR)(deviceExtension->FullIdentifyData.MaximumBlockTransfer & 0xFF);
1908  }
1909  LunExt->NumOfSectors = 0;
1910  if (Command == IDE_COMMAND_IDENTIFY) {
1911  ULONGLONG NumOfSectors=0;
1912  ULONGLONG NativeNumOfSectors=0;
1913  ULONGLONG cylinders=0;
1914  ULONGLONG tmp_cylinders=0;
1915 
1916  KdPrint2((PRINT_PREFIX "PhysLogSectorSize %#x, %#x, offset %#x\n",
1917  deviceExtension->FullIdentifyData.PhysLogSectorSize,
1918  deviceExtension->FullIdentifyData.LargeSectorSize,
1919  deviceExtension->FullIdentifyData.LogicalSectorOffset
1920  ));
1921 
1922  KdPrint2((PRINT_PREFIX "NV PM_Sup %d, PM_En %d, En %d, PM ver %#x ver %#x\n",
1923  deviceExtension->FullIdentifyData.NVCache_PM_Supported,
1924  deviceExtension->FullIdentifyData.NVCache_PM_Enabled,
1925  deviceExtension->FullIdentifyData.NVCache_Enabled,
1926  deviceExtension->FullIdentifyData.NVCache_PM_Version,
1927  deviceExtension->FullIdentifyData.NVCache_Version
1928  ));
1929 
1930  KdPrint2((PRINT_PREFIX "R-rate %d\n",
1932  ));
1933  KdPrint2((PRINT_PREFIX "WC %d/%d, LA %d/%d, WB %d/%d, RB %d/%d, Q %d/%d\n",
1934  deviceExtension->FullIdentifyData.FeaturesEnabled.WriteCache,
1935  deviceExtension->FullIdentifyData.FeaturesSupport.WriteCache,
1936  deviceExtension->FullIdentifyData.FeaturesEnabled.LookAhead,
1937  deviceExtension->FullIdentifyData.FeaturesSupport.LookAhead,
1938  deviceExtension->FullIdentifyData.FeaturesEnabled.WriteBuffer,
1939  deviceExtension->FullIdentifyData.FeaturesSupport.WriteBuffer,
1940  deviceExtension->FullIdentifyData.FeaturesEnabled.ReadBuffer,
1941  deviceExtension->FullIdentifyData.FeaturesSupport.ReadBuffer,
1942  deviceExtension->FullIdentifyData.FeaturesEnabled.Queued,
1943  deviceExtension->FullIdentifyData.FeaturesSupport.Queued
1944  ));
1945 
1946  KdPrint2((PRINT_PREFIX "Protected %d/%d status %#x, rev %#x\n",
1947  deviceExtension->FullIdentifyData.FeaturesEnabled.Protected,
1948  deviceExtension->FullIdentifyData.FeaturesSupport.Protected,
1949  deviceExtension->FullIdentifyData.SecurityStatus,
1950  deviceExtension->FullIdentifyData.MasterPasswdRevision
1951  ));
1952 
1953  // Read very-old-style drive geometry
1954  KdPrint2((PRINT_PREFIX "CHS %#x:%#x:%#x\n",
1955  deviceExtension->FullIdentifyData.NumberOfCylinders,
1956  deviceExtension->FullIdentifyData.NumberOfHeads,
1957  deviceExtension->FullIdentifyData.SectorsPerTrack
1958  ));
1959  NumOfSectors = deviceExtension->FullIdentifyData.NumberOfCylinders *
1960  deviceExtension->FullIdentifyData.NumberOfHeads *
1961  deviceExtension->FullIdentifyData.SectorsPerTrack;
1962  KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
1963  // Check for HDDs > 8Gb
1964  if ((deviceExtension->FullIdentifyData.NumberOfCylinders == 0x3fff) &&
1965 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1966  deviceExtension->FullIdentifyData.NumberOfHeads &&
1967  deviceExtension->FullIdentifyData.SectorsPerTrack &&
1968  (NumOfSectors < deviceExtension->FullIdentifyData.UserAddressableSectors)) {
1969  KdPrint2((PRINT_PREFIX "NumberOfCylinders == 0x3fff\n"));
1970  cylinders =
1971  (deviceExtension->FullIdentifyData.UserAddressableSectors /
1972  (deviceExtension->FullIdentifyData.NumberOfHeads *
1973  deviceExtension->FullIdentifyData.SectorsPerTrack));
1974 
1975  KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
1976 
1977  NumOfSectors = cylinders *
1978  deviceExtension->FullIdentifyData.NumberOfHeads *
1979  deviceExtension->FullIdentifyData.SectorsPerTrack;
1980 
1981  KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
1982  } else {
1983 
1984  }
1985  // Check for LBA mode
1986  KdPrint2((PRINT_PREFIX "SupportLba flag %#x\n", deviceExtension->FullIdentifyData.SupportLba));
1987  KdPrint2((PRINT_PREFIX "SupportDMA flag %#x\n", deviceExtension->FullIdentifyData.SupportDma));
1988  KdPrint2((PRINT_PREFIX "SoftReset %#x\n", deviceExtension->FullIdentifyData.SoftReset));
1989  KdPrint2((PRINT_PREFIX "SupportIordy %#x, DisableIordy %#x\n",
1990  deviceExtension->FullIdentifyData.SupportIordy,
1991  deviceExtension->FullIdentifyData.DisableIordy
1992  ));
1993  KdPrint2((PRINT_PREFIX "MajorRevision %#x\n", deviceExtension->FullIdentifyData.MajorRevision));
1994  KdPrint2((PRINT_PREFIX "UserAddressableSectors %#x\n", deviceExtension->FullIdentifyData.UserAddressableSectors));
1995  if ( deviceExtension->FullIdentifyData.SupportLba
1996  ||
1997  (deviceExtension->FullIdentifyData.MajorRevision &&
1998 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1999  deviceExtension->FullIdentifyData.UserAddressableSectors)) {
2000  KdPrint2((PRINT_PREFIX "LBA mode\n"));
2001  LunExt->DeviceFlags |= DFLAGS_LBA_ENABLED;
2002  } else {
2003  KdPrint2((PRINT_PREFIX "Keep orig geometry\n"));
2004  LunExt->DeviceFlags |= DFLAGS_ORIG_GEOMETRY;
2005  goto skip_lba_staff;
2006  }
2007  // Check for LBA48 support
2008  if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
2009  if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48 &&
2010  deviceExtension->FullIdentifyData.FeaturesEnabled.Address48 &&
2011  deviceExtension->FullIdentifyData.NumberOfHeads &&
2012  deviceExtension->FullIdentifyData.SectorsPerTrack &&
2013  (deviceExtension->FullIdentifyData.UserAddressableSectors48 > NumOfSectors)
2014  ) {
2015  KdPrint2((PRINT_PREFIX "LBA48\n"));
2016  cylinders =
2017  (deviceExtension->FullIdentifyData.UserAddressableSectors48 /
2018  (deviceExtension->FullIdentifyData.NumberOfHeads *
2019  deviceExtension->FullIdentifyData.SectorsPerTrack));
2020 
2021  KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
2022 
2023  NativeNumOfSectors = cylinders *
2024  deviceExtension->FullIdentifyData.NumberOfHeads *
2025  deviceExtension->FullIdentifyData.SectorsPerTrack;
2026 
2027  KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
2028 
2029  if(NativeNumOfSectors > NumOfSectors) {
2030  KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
2031  NumOfSectors = NativeNumOfSectors;
2032  }
2033  }
2034 
2035  // Check drive capacity report for LBA48-capable drives.
2036  if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48) {
2037  ULONG hNativeNumOfSectors;
2038  KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
2039 
2040  statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
2042 
2043  if(!(statusByte & IDE_STATUS_ERROR)) {
2044  if(use_ahci) {
2045  NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
2046  } else {
2047  NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
2048  ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
2049  ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) ;
2050 
2052  IDE_DC_USE_HOB );
2053 
2054  KdPrint2((PRINT_PREFIX "Read high order bytes\n"));
2055  NativeNumOfSectors |=
2056  (ULONG)((ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24 );
2057  hNativeNumOfSectors=
2060  ((PULONG)&NativeNumOfSectors)[1] = hNativeNumOfSectors;
2061  }
2062  KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
2063 
2064  // Some drives report LBA48 capability while has capacity below 128Gb
2065  // Probably they support large block-counters.
2066  // But the problem is that some of them reports higher part of Max LBA equal to lower part.
2067  // Here we check this
2068  if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
2069  KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!!\n"));
2070 
2071  statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
2073 
2074  if(!(statusByte & IDE_STATUS_ERROR)) {
2075  if(use_ahci) {
2076  NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
2077  } else {
2078  NativeNumOfSectors = (ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
2084  ;
2085  }
2086  }
2087 
2088  if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
2089  KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!! (2)\n"));
2090  NativeNumOfSectors = 0;
2091  }
2092  }
2093 
2094  if(NumOfSectors <= ATA_MAX_LBA28 &&
2095  NativeNumOfSectors > NumOfSectors) {
2096 
2097  KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
2098  KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
2099 
2100  statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
2101  IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
2102  if(!(statusByte & IDE_STATUS_ERROR)) {
2103  NumOfSectors = NativeNumOfSectors;
2104  }
2105  }
2106  } // !error
2107  }
2108 
2109  if(NumOfSectors < 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
2110  // check for native LBA size
2111  // some drives report ~32Gb in Identify Block
2112  KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
2113 
2114  statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_READ_NATIVE_SIZE,
2115  0, IDE_USE_LBA, 0, 0, 0, ATA_WAIT_READY);
2116 
2117  if(!(statusByte & IDE_STATUS_ERROR)) {
2118  if(use_ahci) {
2119  NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
2120  } else {
2121  NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
2122  ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
2123  ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
2124  (((ULONG)AtapiReadPort1(chan, IDX_IO1_i_DriveSelect) & 0xf) << 24);
2125  }
2126  KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
2127 
2128  if(NativeNumOfSectors > NumOfSectors) {
2129 
2130  KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
2131  KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
2132 
2133  statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
2134  IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
2135  if(!(statusByte & IDE_STATUS_ERROR)) {
2136  NumOfSectors = NativeNumOfSectors;
2137  }
2138  }
2139  }
2140  }
2141 
2142  if(NumOfSectors > ATA_MAX_IOLBA28) {
2143  KdPrint2((PRINT_PREFIX "2TB threshold, force LBA64 WRITE requirement\n"));
2144  LunExt->DeviceFlags |= DFLAGS_LBA32plus;
2145  }
2146  } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
2147 
2148  // fill IdentifyData with bogus geometry
2149  KdPrint2((PRINT_PREFIX "requested LunExt->GeomType=%x\n", LunExt->opt_GeomType));
2150  if(deviceExtension->FullIdentifyData.CurrentSectorsPerTrack &&
2151  deviceExtension->FullIdentifyData.NumberOfCurrentHeads) {
2152  tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *
2153  deviceExtension->FullIdentifyData.NumberOfCurrentHeads);
2154  } else
2155  if(deviceExtension->FullIdentifyData.SectorsPerTrack &&
2156  deviceExtension->FullIdentifyData.NumberOfHeads) {
2157  KdPrint2((PRINT_PREFIX "Current C/H = %#I64x/%#I64x\n",
2158  deviceExtension->FullIdentifyData.CurrentSectorsPerTrack,
2159  deviceExtension->FullIdentifyData.NumberOfCurrentHeads));
2160  tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.SectorsPerTrack *
2161  deviceExtension->FullIdentifyData.NumberOfHeads);
2162  } else {
2163  tmp_cylinders = 0;
2164  }
2165  KdPrint2((PRINT_PREFIX "tmp_cylinders = %#I64x\n", tmp_cylinders));
2166  if((tmp_cylinders < 0xffff) || (LunExt->opt_GeomType == GEOM_ORIG)) {
2167  // ok, we can keep original values
2168  if(LunExt->opt_GeomType == GEOM_AUTO) {
2169  LunExt->opt_GeomType = GEOM_ORIG;
2170  }
2171  } else {
2172  tmp_cylinders = NumOfSectors / (255*63);
2173  if(tmp_cylinders < 0xffff) {
2174  // we can use generic values for H/S for generic geometry approach
2175  if(LunExt->opt_GeomType == GEOM_AUTO) {
2176  LunExt->opt_GeomType = GEOM_STD;
2177  }
2178  } else {
2179  // we should use UNIATA geometry approach
2180  if(LunExt->opt_GeomType == GEOM_AUTO) {
2181  LunExt->opt_GeomType = GEOM_UNIATA;
2182  }
2183  }
2184  }
2185 
2186  if(!deviceExtension->FullIdentifyData.SectorsPerTrack ||
2187  !deviceExtension->FullIdentifyData.NumberOfHeads) {
2188  KdPrint2((PRINT_PREFIX "Zero S/H -> Force Use GEOM_STD\n"));
2189  }
2190 
2191  if(LunExt->opt_GeomType == GEOM_STD) {
2192  deviceExtension->FullIdentifyData.CurrentSectorsPerTrack =
2193  deviceExtension->FullIdentifyData.SectorsPerTrack = 63;
2194 
2195  deviceExtension->FullIdentifyData.NumberOfCurrentHeads =
2196  deviceExtension->FullIdentifyData.NumberOfHeads = 255;
2197 
2198  cylinders = NumOfSectors / (255*63);
2199  KdPrint2((PRINT_PREFIX "Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders, 255, 63));
2200  } else
2201  if(LunExt->opt_GeomType == GEOM_UNIATA) {
2202  while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x80)) {
2203  cylinders /= 2;
2204  KdPrint2((PRINT_PREFIX "cylinders /= 2\n"));
2205  deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
2206  deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
2207  }
2208  while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x80)) {
2209  cylinders /= 2;
2210  KdPrint2((PRINT_PREFIX "cylinders /= 2 (2)\n"));
2211  deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
2212  deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
2213  }
2214  while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x8000)) {
2215  cylinders /= 2;
2216  KdPrint2((PRINT_PREFIX "cylinders /= 2 (3)\n"));
2217  deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
2218  deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
2219  }
2220  while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x8000)) {
2221  cylinders /= 2;
2222  KdPrint2((PRINT_PREFIX "cylinders /= 2 (4)\n"));
2223  deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
2224  deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
2225  }
2226  KdPrint2((PRINT_PREFIX "Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders,
2227  deviceExtension->FullIdentifyData.NumberOfCurrentHeads,
2228  deviceExtension->FullIdentifyData.CurrentSectorsPerTrack));
2229  }
2230  if(!cylinders) {
2231  KdPrint2((PRINT_PREFIX "cylinders = tmp_cylinders (%x = %x)\n", cylinders, tmp_cylinders));
2232  cylinders = tmp_cylinders;
2233  }
2234  deviceExtension->FullIdentifyData.NumberOfCurrentCylinders =
2235  deviceExtension->FullIdentifyData.NumberOfCylinders = (USHORT)cylinders;
2236 
2237 skip_lba_staff:
2238 
2239  KdPrint2((PRINT_PREFIX "Geometry: C %#x (%#x)\n",
2240  deviceExtension->FullIdentifyData.NumberOfCylinders,
2242  ));
2243  KdPrint2((PRINT_PREFIX "Geometry: H %#x (%#x)\n",
2244  deviceExtension->FullIdentifyData.NumberOfHeads,
2245  deviceExtension->FullIdentifyData.NumberOfCurrentHeads
2246  ));
2247  KdPrint2((PRINT_PREFIX "Geometry: S %#x (%#x)\n",
2248  deviceExtension->FullIdentifyData.SectorsPerTrack,
2249  deviceExtension->FullIdentifyData.CurrentSectorsPerTrack
2250  ));
2251 
2252  if(NumOfSectors) {
2253  LunExt->NumOfSectors = NumOfSectors;
2254  }
2255  if(deviceExtension->FullIdentifyData.MajorRevision &&
2256  deviceExtension->FullIdentifyData.DoubleWordIo) {
2258  KdPrint2((PRINT_PREFIX "IssueIdentify: DWORDIO supported\n"));
2259  }
2260  } else {
2261  // ATAPI
2262  if(deviceExtension->FullIdentifyData.MajorRevision &&
2263  deviceExtension->FullIdentifyData.DoubleWordIo) {
2265  KdPrint2((PRINT_PREFIX "IssueIdentify: DFLAGS_DWORDIO_ENABLED.\n"));
2266  }
2267  if(deviceExtension->FullIdentifyData.AtapiDMA.DMADirRequired) {
2268  KdPrint2((PRINT_PREFIX "DMADirRequired.\n"));
2269  }
2270  if(deviceExtension->FullIdentifyData.AtapiByteCount0) {
2271  KdPrint2((PRINT_PREFIX "AtapiByteCount0=%x\n", deviceExtension->FullIdentifyData.AtapiByteCount0));
2272  }
2273  }
2274 
2276  &deviceExtension->FullIdentifyData,sizeof(IDENTIFY_DATA2));
2277 
2278  InitBadBlocks(LunExt);
2279 
2280  if ((LunExt->IdentifyData.DrqType & ATAPI_DRQT_INTR) &&
2282 
2283  // This device interrupts with the assertion of DRQ after receiving
2284  // Atapi Packet Command
2285  LunExt->DeviceFlags |= DFLAGS_INT_DRQ;
2286  KdPrint2((PRINT_PREFIX "IssueIdentify: Device interrupts on assertion of DRQ.\n"));
2287 
2288  } else {
2289  KdPrint2((PRINT_PREFIX "IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
2290  }
2291 
2292  if(Command != IDE_COMMAND_IDENTIFY) {
2293  // ATAPI branch
2294  if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_TAPE) {
2295  // This is a tape.
2296  LunExt->DeviceFlags |= DFLAGS_TAPE_DEVICE;
2297  KdPrint2((PRINT_PREFIX "IssueIdentify: Device is a tape drive.\n"));
2298  } else
2299  if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM ||
2300  LunExt->IdentifyData.DeviceType == ATAPI_TYPE_OPTICAL) {
2301  KdPrint2((PRINT_PREFIX "IssueIdentify: Device is CD/Optical drive.\n"));
2302  // set CD default costs
2306  statusByte = WaitForDrq(chan);
2307  } else {
2308  KdPrint2((PRINT_PREFIX "IssueIdentify: ATAPI drive type %#x.\n",
2309  LunExt->IdentifyData.DeviceType));
2310  }
2311  KdPrint2((PRINT_PREFIX "IssueIdentify: AtapiCmdSize %#x\n", deviceExtension->FullIdentifyData.AtapiCmdSize));
2312  } else {
2313  KdPrint2((PRINT_PREFIX "IssueIdentify: hard drive.\n"));
2314  }
2315 
2316  GetBaseStatus(chan, statusByte);
2317  KdPrint2((PRINT_PREFIX "IssueIdentify: final Status on exit (%#x)\n", statusByte));
2318  return TRUE;
2319 
2320 } // end IssueIdentify()
2321 
2322 
2323 /*++
2324 
2325 Routine Description:
2326  Set drive parameters using the IDENTIFY data.
2327 
2328 Arguments:
2329  HwDeviceExtension - HBA miniport driver's adapter data storage
2330  DeviceNumber - Indicates which device.
2331 
2332 Return Value:
2333  TRUE if all goes well.
2334 
2335 --*/
2336 BOOLEAN
2337 NTAPI
2339  IN PVOID HwDeviceExtension,
2341  IN ULONG lChannel
2342  )
2343 {
2344  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2345  PIDENTIFY_DATA2 identifyData;
2346  PHW_LU_EXTENSION LunExt;
2347 // ULONG i;
2348  UCHAR statusByte;
2349  UCHAR errorByte;
2350 
2351  LunExt = deviceExtension->chan[lChannel].lun[DeviceNumber];
2352  identifyData = &(LunExt->IdentifyData);
2353 
2354  if(LunExt->DeviceFlags &
2356  return TRUE;
2357 
2358  KdPrint2((PRINT_PREFIX "SetDriveParameters: Number of heads %#x\n", identifyData->NumberOfHeads));
2359  KdPrint2((PRINT_PREFIX "SetDriveParameters: Sectors per track %#x\n", identifyData->SectorsPerTrack));
2360 
2361  // Send SET PARAMETER command.
2362  statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
2364  (identifyData->NumberOfHeads - 1), 0,
2365  (UCHAR)identifyData->SectorsPerTrack, 0, ATA_WAIT_IDLE);
2366 
2367  statusByte = UniataIsIdle(deviceExtension, statusByte);
2368  if(statusByte & IDE_STATUS_ERROR) {
2369  errorByte = AtapiReadPort1(&deviceExtension->chan[lChannel], IDX_IO1_i_Error);
2370  KdPrint2((PRINT_PREFIX "SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2371  errorByte, statusByte));
2372  return FALSE;
2373  }
2374 
2375  if(statusByte == IDE_STATUS_IDLE) {
2376  return TRUE;
2377  }
2378 
2379  return FALSE;
2380 
2381 } // end SetDriveParameters()
2382 
2383 VOID
2384 NTAPI
2386  PHW_LU_EXTENSION LunExt
2387  )
2388 {
2389  // keep only DFLAGS_HIDDEN flag
2390  LunExt->DeviceFlags &= DFLAGS_HIDDEN;
2391  LunExt->AtapiReadyWaitDelay = 0;
2392 } // end UniataForgetDevice()
2393 
2394 
2395 /*++
2396 
2397 Routine Description:
2398  Reset IDE controller and/or Atapi device.
2399  ->HwResetBus
2400 
2401 Arguments:
2402  HwDeviceExtension - HBA miniport driver's adapter data storage
2403 
2404 Return Value:
2405  Nothing.
2406 
2407 
2408 --*/
2409 BOOLEAN
2410 NTAPI
2412  IN PVOID HwDeviceExtension,
2413  IN ULONG PathId
2414  )
2415 {
2416  KdPrint2((PRINT_PREFIX "AtapiResetController(%x)\n", PathId));
2417  return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
2418 } // end AtapiResetController()
2419 
2420 BOOLEAN
2421 NTAPI
2423  IN PVOID HwDeviceExtension,
2424  IN ULONG PathId,
2425  IN BOOLEAN CompleteType
2426  )
2427 {
2428  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2429  ULONG numberChannels = deviceExtension->NumberChannels;
2430  PHW_CHANNEL chan = NULL;
2431  ULONG i,j;
2432  ULONG MaxLuns;
2433  UCHAR statusByte;
2434  PSCSI_REQUEST_BLOCK CurSrb;
2435  ULONG ChannelCtrlFlags;
2436  UCHAR dma_status = 0;
2437 
2438  ULONG slotNumber = deviceExtension->slotNumber;
2439  ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
2440  ULONG VendorID = deviceExtension->DevID & 0xffff;
2441 #ifdef _DEBUG
2442  ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
2443 #endif
2444  //ULONG RevID = deviceExtension->RevID;
2445  ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
2446  //UCHAR tmp8;
2447  USHORT tmp16;
2448 
2449  KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber));
2450  KdPrint2((PRINT_PREFIX "simplexOnly %d, VM %x\n", deviceExtension->simplexOnly, g_opt_VirtualMachine));
2451 
2452  if(!deviceExtension->simplexOnly && (PathId != CHAN_NOT_SPECIFIED)) {
2453  // we shall reset both channels on SimplexOnly devices,
2454  // It's not worth doing so on normal controllers
2455  j = PathId;
2456  numberChannels = min(j+1, deviceExtension->NumberChannels);
2457  } else {
2458  j=0;
2459  numberChannels = deviceExtension->NumberChannels;
2460  }
2461 
2462  for (; j < numberChannels; j++) {
2463 
2464  KdPrint2((PRINT_PREFIX "AtapiResetController: Reset lchannel %d[%d]\n", j, deviceExtension->Channel));
2465  chan = &(deviceExtension->chan[j]);
2466  MaxLuns = chan->NumberLuns;
2467  // Save control flags
2468  ChannelCtrlFlags = chan->ChannelCtrlFlags;
2469  KdPrint2((PRINT_PREFIX " CompleteType %#x, Luns %d, chan %#x, sptr %#x, flags %#x\n", CompleteType, MaxLuns, chan, &chan, ChannelCtrlFlags));
2470  //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2471  if(CompleteType != RESET_COMPLETE_NONE) {
2472 #ifndef UNIATA_CORE
2473  while((CurSrb = UniataGetCurRequest(chan))) {
2474 
2475  PHW_LU_EXTENSION LunExt;
2476  PATA_REQ AtaReq = (PATA_REQ)(CurSrb->SrbExtension);
2477 
2478  i = GET_CDEV(CurSrb);
2479  KdPrint2((PRINT_PREFIX " Lun %x\n", i));
2480  LunExt = chan->lun[i];
2481 
2482  KdPrint2((PRINT_PREFIX "AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb, chan));
2483  if(CurSrb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
2484  KdPrint2((PRINT_PREFIX " was MechStatus\n"));
2485 
2486  if(!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)) {
2488  KdPrint2((PRINT_PREFIX " set DFLAGS_CHANGER_INITED\n"));
2489  }
2490  }
2491  // Check and see if we are processing an internal srb
2492  if (AtaReq->OriginalSrb) {
2493  KdPrint2((PRINT_PREFIX " restore original SRB %#x\n", AtaReq->OriginalSrb));
2494  AtaReq->Srb = AtaReq->OriginalSrb;
2495  CurSrb->SrbExtension = NULL;
2496  AtaReq->OriginalSrb = NULL;
2497  // NOTE: internal SRB doesn't get to SRB queue !!!
2498  CurSrb = AtaReq->Srb;
2499  }
2500 
2501  // Remove current request from queue
2502  UniataRemoveRequest(chan, CurSrb);
2503 
2504  // Check if request is in progress.
2505  ASSERT(AtaReq->Srb == CurSrb);
2506  if (CurSrb) {
2507  // Complete outstanding request with SRB_STATUS_BUS_RESET.
2508  UCHAR CurPathId = CurSrb->PathId;
2509  UCHAR TargetId = CurSrb->TargetId;
2510  UCHAR Lun = CurSrb->Lun;
2511 
2514 
2515  if (CurSrb->SenseInfoBuffer) {
2516 
2517  PSENSE_DATA senseBuffer = (PSENSE_DATA)CurSrb->SenseInfoBuffer;
2518  KdPrint2((PRINT_PREFIX " senseBuffer %#x, chan %#x, ReqFlags %#x\n", senseBuffer, chan, AtaReq->Flags));
2519 
2520  senseBuffer->ErrorCode = 0x70;
2521  senseBuffer->Valid = 1;
2522  senseBuffer->AdditionalSenseLength = 0xb;
2523  if(CompleteType == RESET_COMPLETE_ALL) {
2524  KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2525  senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
2528  } else {
2529  KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2530  senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
2531  senseBuffer->AdditionalSenseCode = 0;
2532  senseBuffer->AdditionalSenseCodeQualifier = 0;
2533  }
2534  }
2535 
2536  if(!ATAPI_DEVICE(chan, i) && AtaReq->bcount && AtaReq->retry < MAX_RETRIES) {
2537  KdPrint2((PRINT_PREFIX "Save IDE retry status %d\n", AtaReq->retry));
2538  LunExt->errLastLba = AtaReq->lba;
2539  LunExt->errBCount = AtaReq->bcount;
2540  LunExt->errRetry = AtaReq->retry+1;
2541  //KdPrint2((PRINT_PREFIX "AtaReq->Flags & REQ_FLAG_RW_MASK = %x (%x)\n", (AtaReq->Flags & REQ_FLAG_RW_MASK), REQ_FLAG_READ));
2542  //KdPrint2((PRINT_PREFIX "ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION = %x (%x)\n", ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE, CTRFLAGS_DMA_OPERATION));
2543  //KdPrint2((PRINT_PREFIX "g_opt_VirtualMachine = %x (%x)\n", g_opt_VirtualMachine, VM_BOCHS));
2544  if(((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_READ) &&
2545  (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) &&
2547  KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
2550  } else {
2551  KdPrint2((PRINT_PREFIX "do nothing\n"));
2552  }
2553  } else
2554  if(ATAPI_DEVICE(chan, i) && AtaReq->bcount && !AtaReq->retry) {
2555  KdPrint2((PRINT_PREFIX "Save ATAPI retry status %d\n", AtaReq->retry));
2556  LunExt->errLastLba = AtaReq->lba;
2557  LunExt->errBCount = AtaReq->bcount;
2558  LunExt->errRetry = AtaReq->retry+1;
2559  if(((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_READ) &&
2560  (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) &&
2562  KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS ATAPI\n"));
2563  //g_opt_BochsDmaReadWorkaround = TRUE;
2565  } else {
2566  KdPrint2((PRINT_PREFIX "do nothing\n"));
2567  }
2568  } else {
2569  LunExt->errRetry = 0;
2570  }
2571 
2572  // Clear request tracking fields.
2573  AtaReq->WordsLeft = 0;
2574  AtaReq->DataBuffer = NULL;
2575  AtaReq->TransferLength = 0;
2576  KdPrint2((PRINT_PREFIX "chan %#x\n", chan));
2577 
2579  deviceExtension,
2580  CurSrb);
2581 
2582  // Indicate ready for next request.
2584  deviceExtension,
2585  CurPathId,
2586  TargetId,
2587  Lun);
2588  }
2589  if(CompleteType != RESET_COMPLETE_ALL)
2590  break;
2591  } // end while()
2592 #endif //UNIATA_CORE
2593  } // end if (!CompleteType != RESET_COMPLETE_NONE)
2594 
2595  // Clear expecting interrupt flag.
2597  chan->RDP = FALSE;
2598  chan->ChannelCtrlFlags = ChannelCtrlFlags & CTRFLAGS_PERMANENT;
2599  InterlockedExchange(&(chan->CheckIntr),
2600  CHECK_INTR_IDLE);
2601 
2602  for (i = 0; i < MaxLuns; i++) {
2603  chan->lun[i]->PowerState = 0;
2604  }
2605  // Reset controller
2606  if(ChipFlags & UNIATA_AHCI) {
2607  KdPrint2((PRINT_PREFIX " AHCI path\n"));
2608  if(UniataAhciChanImplemented(deviceExtension, j)) {
2609 #ifdef _DEBUG
2610  UniataDumpAhciPortRegs(chan);
2611 #endif
2612  AtapiDisableInterrupts(deviceExtension, j);
2613  UniataAhciReset(HwDeviceExtension, j);
2614  } else {
2615  KdPrint2((PRINT_PREFIX " skip not implemented\n"));
2616  continue;
2617  }
2618  } else {
2619  KdPrint2((PRINT_PREFIX " ATA path, chan %#x\n", chan));
2620  KdPrint2((PRINT_PREFIX " disable intr (0)\n"));
2621  AtapiDisableInterrupts(deviceExtension, j);
2622  KdPrint2((PRINT_PREFIX " done\n"));
2623  switch(VendorID) {
2624  case ATA_INTEL_ID: {
2625  ULONG mask;
2626  ULONG pshift;
2627  ULONG timeout;
2628  if(!(ChipFlags & UNIATA_SATA)) {
2629  goto default_reset;
2630  }
2631  if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
2632  goto default_reset;
2633  }
2634 
2635 #if 0
2636  /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2637  if(ChipFlags & UNIATA_AHCI) {
2638  mask = 0x0005 << j;
2639  } else {
2640  /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2641  GetPciConfig1(0x90, tmp8);
2642  if(tmp8 & 0x04) {
2643  mask = 0x0003;
2644  } else {
2645  mask = 0x0001 << j;
2646  }
2647  }
2648 #else
2649  mask = 1 << chan->lun[0]->SATA_lun_map;
2650  if (MaxLuns > 1) {
2651  mask |= (1 << chan->lun[1]->SATA_lun_map);
2652  }
2653 #endif
2654  ChangePciConfig2(0x92, a & ~mask);
2655  AtapiStallExecution(10);
2656  ChangePciConfig2(0x92, a | mask);
2657  timeout = 100;
2658 
2659  /* Wait up to 1 sec for "connect well". */
2660  if (ChipFlags & (I6CH | I6CH2)) {
2661  pshift = 8;
2662  } else {
2663  pshift = 4;
2664  }
2665  while (timeout--) {
2666  GetPciConfig2(0x92, tmp16);
2667  if (((tmp16 >> pshift) & mask) == mask) {
2668  GetBaseStatus(chan, statusByte);
2669  if(statusByte != IDE_STATUS_WRONG) {
2670  break;
2671  }
2672  }
2673  AtapiStallExecution(10000);
2674  }
2675  break; }
2676  case ATA_SIS_ID: {
2677  KdPrint2((PRINT_PREFIX " SIS\n"));
2678  if(!(ChipFlags & UNIATA_SATA))
2679  goto default_reset;
2680  break; }
2681 #if 0
2682  case ATA_NVIDIA_ID: {
2683  KdPrint2((PRINT_PREFIX " nVidia\n"));
2684  if(!(ChipFlags & UNIATA_SATA))
2685  goto default_reset;
2686  break; }
2687 #else
2688  case ATA_NVIDIA_ID: {
2689  ULONG offs;
2690  ULONG Channel = deviceExtension->Channel + j;
2691  KdPrint2((PRINT_PREFIX " nVidia\n"));
2692  if(!(ChipFlags & UNIATA_SATA)) {
2693  goto default_reset;
2694  }
2695  offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
2696 
2697  KdPrint2((PRINT_PREFIX " disable Phy intr, offs %#x, c %u\n", offs, Channel));
2698  /* disable device and PHY state change interrupts */
2699  if(ChipFlags & NVQ) {
2700  KdPrint2((PRINT_PREFIX " NVQ, 32bits reg\n"));
2701  AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4,
2702  AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) & ((~(ULONG)0x0000000d) << (!Channel*16)) );
2703  } else {
2704  AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1,
2705  AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) & ((~(UCHAR)0x0d) << (!Channel*4)) );
2706  }
2707  tmp16 = UniataSataPhyEnable(HwDeviceExtension, j, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE);
2708 
2709  KdPrint2((PRINT_PREFIX " enable Phy intr, offs %#x\n", offs));
2710  /* enable device and PHY state change interrupts */
2711  if(ChipFlags & NVQ) {
2712  AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4,
2713  AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) | (((ULONG)0x0000000d) << (!Channel*16)) );
2714  } else {
2715  AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1,
2716  AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) | (((UCHAR)0x0d) << (!Channel*4)) );
2717  }
2718 
2719  KdPrint2((PRINT_PREFIX " dev status %#x\n", tmp16));
2720  if(tmp16 != IDE_STATUS_WRONG) {
2721  goto default_reset;
2722  }
2723  break; }
2724 #endif //0
2725  case ATA_SILICON_IMAGE_ID: {
2726  ULONG offset;
2727  ULONG Channel = deviceExtension->Channel + j;
2728  if(!(ChipFlags & UNIATA_SATA))
2729  goto default_reset;
2730  offset = ((Channel & 1) << 7) + ((Channel & 2) << 8);
2731  /* disable PHY state change interrupt */
2732  AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + offset, 0);
2733 
2734  UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
2735 
2736  /* reset controller part for this channel */
2737  AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
2738  AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) | (0xc0 >> Channel));
2739  AtapiStallExecution(1000);
2740  AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
2741  AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) & ~(0xc0 >> Channel));
2742 
2743 
2744  break; }
2745  case ATA_PROMISE_ID: {
2746  break; }
2747  default:
2748  if(ChipFlags & UNIATA_SATA) {
2749  KdPrint2((PRINT_PREFIX " SATA generic reset\n"));
2750  UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
2751  }
2752 default_reset:
2753 /*
2754  AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
2755  IDE_DC_RESET_CONTROLLER );
2756  chan->last_devsel = -1;
2757  KdPrint2((PRINT_PREFIX " wait a little\n"));
2758  AtapiStallExecution(10000);
2759  // Disable interrupts
2760  KdPrint2((PRINT_PREFIX " disable intr\n"));
2761  AtapiDisableInterrupts(deviceExtension, j);
2762  AtapiStallExecution(100);
2763  KdPrint2((PRINT_PREFIX " re-enable intr\n"));
2764  AtapiEnableInterrupts(deviceExtension, j);
2765  KdPrint2((PRINT_PREFIX " wait a little (2)\n"));
2766  AtapiStallExecution(100000);
2767 */
2768  AtapiHardReset(chan, TRUE, 100000);
2769  KdPrint2((PRINT_PREFIX " disable intr\n"));
2770  AtapiDisableInterrupts(deviceExtension, j);
2771  AtapiStallExecution(100);
2772  KdPrint2((PRINT_PREFIX " re-enable intr\n"));
2773  AtapiEnableInterrupts(deviceExtension, j);
2774  KdPrint2((PRINT_PREFIX " done\n"));
2775 
2776  break;
2777  } // end switch()
2778 
2779  //if(!(ChipFlags & UNIATA_SATA)) {}
2780  if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
2781  // Reset DMA engine if active
2782  KdPrint2((PRINT_PREFIX " check DMA engine\n"));
2783  dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
2784  KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
2785  if((ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
2786  (dma_status & BM_STATUS_INTR)) {
2787  AtapiDmaDone(HwDeviceExtension, 0, j, NULL);
2788  }
2789  }
2790  } // ATA vs AHCI
2791 
2792  // all these shall be performed inside AtapiHwInitialize__() ?
2793 #if 1
2794  KdPrint2((PRINT_PREFIX " process connected devices 0 - %d\n", MaxLuns-1));
2795  // Do special processing for ATAPI and IDE disk devices.
2796  for (i = 0; i < MaxLuns; i++) {
2797 
2798  // Check if device present.
2799  KdPrint2((PRINT_PREFIX " Chan %#x\n", chan));
2800  KdPrint2((PRINT_PREFIX " Lun %#x\n", i));
2801  KdPrint2((PRINT_PREFIX " Lun ptr %#x\n", chan->lun[i]));
2802  if (!(chan->lun[i]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
2803  if(ChipFlags & UNIATA_AHCI) {
2804  // everything is done in UniataAhciReset()
2805  KdPrint2((PRINT_PREFIX " device have gone\n"));
2806  continue;
2807  }
2808 #ifdef NAVO_TEST
2809  continue;
2810 #else //NAVO_TEST
2811  //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2812  if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
2813  continue;
2814  }
2815  if(!CheckDevice(HwDeviceExtension, j, i, TRUE)) {
2816  continue;
2817  }
2818  } else {
2819  if(ChipFlags & UNIATA_AHCI) {
2820  // everything is done in UniataAhciReset()
2821  KdPrint2((PRINT_PREFIX " found some device\n"));
2822 
2823  if(!IssueIdentify(HwDeviceExtension,
2824  i, j,
2825  ATAPI_DEVICE(chan, i) ?
2827  FALSE)) {
2828  KdPrint2((PRINT_PREFIX " identify failed !\n"));
2829  UniataForgetDevice(chan->lun[i]);
2830  }
2831  continue;
2832  }
2833  if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
2834  KdPrint2((PRINT_PREFIX " device have gone\n"));
2835  UniataForgetDevice(chan->lun[i]);
2836  }
2837 #endif //NAVO_TEST
2838  }
2839 
2840  SelectDrive(chan, i);
2841  AtapiStallExecution(10);
2842  statusByte = WaitOnBusyLong(chan);
2843  statusByte = UniataIsIdle(deviceExtension, statusByte);
2844  if(statusByte == IDE_STATUS_WRONG) {
2846  "no drive, status %#x\n",
2847  statusByte));
2848  UniataForgetDevice(chan->lun[i]);
2849  } else
2850  // Check for ATAPI disk.
2851  if (ATAPI_DEVICE(chan, i)) {
2852  // Issue soft reset and issue identify.
2853  GetStatus(chan, statusByte);
2854  KdPrint2((PRINT_PREFIX "AtapiResetController: Status before Atapi reset (%#x).\n",
2855  statusByte));
2856 
2857  AtapiDisableInterrupts(deviceExtension, j);
2858  AtapiSoftReset(chan, i);
2859  AtapiEnableInterrupts(deviceExtension, j);
2860 
2861  GetStatus(chan, statusByte);
2862 
2863  if(statusByte != IDE_STATUS_SUCCESS) {
2864  ULONG k;
2865  k = UniataAnybodyHome(deviceExtension, j, i);
2866  if(k == ATA_AT_HOME_HDD) {
2867  // device reset in progress, perform additional wait
2868  KdPrint2((PRINT_PREFIX " long reset, wait up to 4.5 s\n"));
2869  k = 30 * 1000;
2870  while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
2871  k--)
2872  {
2873  AtapiStallExecution(150);
2874  }
2875  KdPrint2((PRINT_PREFIX " exit after %u loops\n", k));
2876  GetStatus(chan, statusByte);
2877  }
2878  }
2879  if(statusByte == IDE_STATUS_SUCCESS) {
2880 
2881  IssueIdentify(HwDeviceExtension,
2882  i, j,
2884  } else {
2885 
2887  "AtapiResetController: Status after soft reset %#x\n",
2888  statusByte));
2889  }
2890  GetBaseStatus(chan, statusByte);
2891 
2892  } else {
2893  // Issue identify and reinit after channel reset.
2894 
2895  if (statusByte != IDE_STATUS_IDLE &&
2896  statusByte != IDE_STATUS_SUCCESS &&
2897  statusByte != IDE_STATUS_DRDY) {
2898 // result2 = FALSE;
2899  KdPrint2((PRINT_PREFIX "AtapiResetController: IdeHardReset failed\n"));
2900  } else
2901  if(!IssueIdentify(HwDeviceExtension,
2902  i, j,
2904 // result2 = FALSE;
2905  KdPrint2((PRINT_PREFIX "AtapiResetController: IDE IssueIdentify failed\n"));
2906  } else
2907  // Set disk geometry parameters.
2908  if (!SetDriveParameters(HwDeviceExtension, i, j)) {
2909  KdPrint2((PRINT_PREFIX "AtapiResetController: SetDriveParameters failed\n"));
2910  }
2911  GetBaseStatus(chan, statusByte);
2912  }
2913  // force DMA mode reinit
2914  KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n"));
2915  chan->lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
2916  }
2917 #endif //0
2918 
2919  // Enable interrupts, note, we can have here recursive disable
2920  AtapiStallExecution(10);
2921  KdPrint2((PRINT_PREFIX "AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2922  j,
2923  chan->DisableIntr));
2924  AtapiEnableInterrupts(deviceExtension, j);
2925 
2926  // Call the HwInitialize routine to setup multi-block.
2927  AtapiHwInitialize__(deviceExtension, j);
2928  } // for(channel)
2929  ScsiPortNotification(NextRequest, deviceExtension, NULL);
2930 
2931  return TRUE;
2932 
2933 } // end AtapiResetController__()
2934 
2935 
2936 /*++
2937 
2938 Routine Description:
2939  This routine maps ATAPI and IDE errors to specific SRB statuses.
2940 
2941 Arguments:
2942  HwDeviceExtension - HBA miniport driver's adapter data storage
2943  Srb - IO request packet
2944 
2945 Return Value:
2946  SRB status
2947 
2948 --*/
2949 ULONG
2950 NTAPI
2952  IN PVOID HwDeviceExtension,
2954  )
2955 {
2956  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2957  ULONG lChannel = GET_CHANNEL(Srb);
2958  PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
2959 // ULONG i;
2960  UCHAR errorByte = 0;
2961  UCHAR srbStatus = SRB_STATUS_SUCCESS;
2962  UCHAR scsiStatus;
2964  PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
2965 
2966  // Read the error register.
2967 
2968  if(deviceExtension->HwFlags & UNIATA_AHCI) {
2969  PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
2970  if(AtaReq) {
2971  errorByte = AtaReq->ahci.in_error;
2972  } else {
2973  }
2974  } else {
2975  errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
2976  }
2978  "MapError: Error register is %#x\n",
2979  errorByte));
2980 
2981  if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2982 
2983  switch (errorByte >> 4) {
2984  case SCSI_SENSE_NO_SENSE:
2985 
2987  "ATAPI: No sense information\n"));
2988  scsiStatus = SCSISTAT_CHECK_CONDITION;
2989  srbStatus = SRB_STATUS_ERROR;
2990  break;
2991 
2993 
2995  "ATAPI: Recovered error\n"));
2996  scsiStatus = 0;
2997  srbStatus = SRB_STATUS_SUCCESS;
2998  break;
2999 
3000  case SCSI_SENSE_NOT_READY:
3001 
3003  "ATAPI: Device not ready\n"));
3004  scsiStatus = SCSISTAT_CHECK_CONDITION;
3005  srbStatus = SRB_STATUS_ERROR;
3006  break;
3007 
3009 
3011  "ATAPI: Media error\n"));
3012  scsiStatus = SCSISTAT_CHECK_CONDITION;
3013  srbStatus = SRB_STATUS_ERROR;
3014  break;
3015 
3017 
3019  "ATAPI: Hardware error\n"));
3020  scsiStatus = SCSISTAT_CHECK_CONDITION;
3021  srbStatus = SRB_STATUS_ERROR;
3022  break;
3023 
3025 
3027  "ATAPI: Illegal request\n"));
3028  scsiStatus = SCSISTAT_CHECK_CONDITION;
3029  srbStatus = SRB_STATUS_ERROR;
3030  break;
3031 
3033 
3035  "ATAPI: Unit attention\n"));
3036  scsiStatus = SCSISTAT_CHECK_CONDITION;
3037  srbStatus = SRB_STATUS_ERROR;
3038  break;
3039 
3041 
3043  "ATAPI: Data protect\n"));
3044  scsiStatus = SCSISTAT_CHECK_CONDITION;
3045  srbStatus = SRB_STATUS_ERROR;
3046  break;
3047 
3049 
3051  "ATAPI: Blank check\n"));
3052  scsiStatus = SCSISTAT_CHECK_CONDITION;
3053  srbStatus = SRB_STATUS_ERROR;
3054  break;
3055 
3058  "Atapi: Command Aborted\n"));
3059  scsiStatus = SCSISTAT_CHECK_CONDITION;
3060  srbStatus = SRB_STATUS_ERROR;
3061  break;
3062 
3063  default:
3064 
3066  "ATAPI: Invalid sense information\n"));
3067  scsiStatus = 0;
3068  srbStatus = SRB_STATUS_ERROR;
3069  break;
3070  }
3071 
3072  } else {
3073 
3074  scsiStatus = 0;
3075 
3076  // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
3077  chan->ReturningMediaStatus = errorByte;
3078 
3079  if (errorByte & IDE_ERROR_MEDIA_CHANGE_REQ) {
3081  "IDE: Media change\n"));
3082  scsiStatus = SCSISTAT_CHECK_CONDITION;
3083  srbStatus = SRB_STATUS_ERROR;
3084 
3085  if (Srb->SenseInfoBuffer) {
3086 
3087  PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3088 
3089  senseBuffer->ErrorCode = 0x70;
3090  senseBuffer->Valid = 1;
3091  senseBuffer->AdditionalSenseLength = 0xb;
3092  senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
3094  senseBuffer->AdditionalSenseCodeQualifier = 0;
3095 
3096  srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3097  }
3098 
3099  } else if (errorByte & IDE_ERROR_COMMAND_ABORTED) {
3101  "IDE: Command abort\n"));
3102  srbStatus = SRB_STATUS_ABORTED;
3103  scsiStatus = SCSISTAT_CHECK_CONDITION;
3104 
3105  if (Srb->SenseInfoBuffer) {
3106 
3107  PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3108 
3109  senseBuffer->ErrorCode = 0x70;
3110  senseBuffer->Valid = 1;
3111  senseBuffer->AdditionalSenseLength = 0xb;
3112  senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
3113  senseBuffer->AdditionalSenseCode = 0;
3114  senseBuffer->AdditionalSenseCodeQualifier = 0;
3115 
3116  srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3117  }
3118 
3119  LunExt->ErrorCount++;
3120 
3121  } else if (errorByte & IDE_ERROR_END_OF_MEDIA) {
3122 
3124  "IDE: End of media\n"));
3125  scsiStatus = SCSISTAT_CHECK_CONDITION;
3126  srbStatus = SRB_STATUS_ERROR;
3127 
3128  if (Srb->SenseInfoBuffer) {
3129 
3130  PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3131 
3132  senseBuffer->ErrorCode = 0x70;
3133  senseBuffer->Valid = 1;
3134  senseBuffer->AdditionalSenseLength = 0xb;
3135  senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
3138  senseBuffer->EndOfMedia = 1;
3139 
3140  srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3141  }
3142 
3143  if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
3144  LunExt->ErrorCount++;
3145  }
3146 
3147  } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) {
3148 
3150  "IDE: Illegal length\n"));
3151  srbStatus = SRB_STATUS_INVALID_REQUEST;
3152 
3153  if (Srb->SenseInfoBuffer) {
3154 
3155  PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3156 
3157  senseBuffer->ErrorCode = 0x70;
3158  senseBuffer->Valid = 1;
3159  senseBuffer->AdditionalSenseLength = 0xb;
3160  senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
3163  senseBuffer->IncorrectLength = 1;
3164 
3165  srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3166  }
3167 
3168  } else if (errorByte & IDE_ERROR_BAD_BLOCK) {
3169 
3171  "IDE: Bad block\n"));
3172  srbStatus = SRB_STATUS_ERROR;
3173  scsiStatus = SCSISTAT_CHECK_CONDITION;
3174  if (Srb->SenseInfoBuffer) {
3175 
3176  PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3177 
3178  senseBuffer->ErrorCode = 0x70;
3179  senseBuffer->Valid = 1;
3180  senseBuffer->AdditionalSenseLength = 0xb;
3181  senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
3182  senseBuffer->AdditionalSenseCode = 0;
3183  senseBuffer->AdditionalSenseCodeQualifier = 0;
3184 
3185  srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3186  }
3187 
3188  } else if (errorByte & IDE_ERROR_ID_NOT_FOUND) {
3189 
3191  "IDE: Id not found\n"));
3192  srbStatus = SRB_STATUS_ERROR;
3193  scsiStatus = SCSISTAT_CHECK_CONDITION;
3194 
3195  if (Srb->SenseInfoBuffer) {
3196 
3197  PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3198 
3199  senseBuffer->ErrorCode = 0x70;
3200  senseBuffer->Valid = 1;
3201  senseBuffer->AdditionalSenseLength = 0xb;
3202  senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
3203  senseBuffer->AdditionalSenseCode = 0;
3204  senseBuffer->AdditionalSenseCodeQualifier = 0;
3205 
3206  srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3207  }
3208 
3209  LunExt->ErrorCount++;
3210 
3211  } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) {
3212 
3214  "IDE: Media change\n"));
3215  scsiStatus = SCSISTAT_CHECK_CONDITION;
3216  srbStatus = SRB_STATUS_ERROR;
3217 
3218  if (Srb->SenseInfoBuffer) {
3219 
3220  PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3221 
3222  senseBuffer->ErrorCode = 0x70;
3223  senseBuffer->Valid = 1;
3224  senseBuffer->AdditionalSenseLength = 0xb;
3225  senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
3227  senseBuffer->AdditionalSenseCodeQualifier = 0;
3228 
3229  srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3230  }
3231 
3232  } else if (errorByte & IDE_ERROR_DATA_ERROR) {
3233 
3235  "IDE: Data error\n"));
3236  scsiStatus = SCSISTAT_CHECK_CONDITION;
3237  srbStatus = SRB_STATUS_ERROR;
3238 
3239  if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
3240  LunExt->ErrorCount++;
3241  }
3242 
3243  // Build sense buffer
3244  if (Srb->SenseInfoBuffer) {
3245 
3246  PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3247 
3248  senseBuffer->ErrorCode = 0x70;
3249  senseBuffer->Valid = 1;
3250  senseBuffer->AdditionalSenseLength = 0xb;
3251  senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
3252  senseBuffer->AdditionalSenseCode = 0;
3253  senseBuffer->AdditionalSenseCodeQualifier = 0;
3254 
3255  srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3256  }
3257  }
3258 
3259  if (LunExt->ErrorCount >= MAX_ERRORS) {
3260 // deviceExtension->DWordIO = FALSE;
3261 
3263  "MapError: ErrorCount >= MAX_ERRORS\n"));
3264 
3265  LunExt->DeviceFlags &= ~DFLAGS_DWORDIO_ENABLED;
3266  LunExt->MaximumBlockXfer = 0;
3267  BrutePoint();
3268 
3270  "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
3271 
3272  // Log the error.
3274  "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
3275  HwDeviceExtension,
3276  Srb,
3277  Srb->PathId,
3278  Srb->TargetId,
3279  Srb->Lun,
3281  4
3282  ));
3283  ScsiPortLogError( HwDeviceExtension,
3284  Srb,
3285  Srb->PathId,
3286  Srb->TargetId,
3287  Srb->Lun,
3289  4);
3290 
3291  // Reprogram to not use Multi-sector.
3292  UCHAR statusByte;
3293 
3294  if (LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT &&
3296 
3297  statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY);
3298 
3299  // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3300  // command was aborted.
3301  if (statusByte & IDE_STATUS_ERROR) {
3302 
3303  // Read the error register.
3304  errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
3305 
3306  KdPrint2((PRINT_PREFIX "MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
3307  statusByte,
3308  errorByte));
3309 
3310  // Adjust the devExt. value, if necessary.
3311  LunExt->MaximumBlockXfer = 0;
3312  BrutePoint();
3313 
3314  }
3315  }
3316  }
3317  }
3318 
3319  // Set SCSI status to indicate a check condition.
3320  Srb->ScsiStatus = scsiStatus;
3321 
3322  return srbStatus;
3323 
3324 } // end MapError()
3325 
3326 
3327 /*++
3328 
3329 Routine Description:
3330 
3331 Arguments:
3332  HwDeviceExtension - HBA miniport driver's adapter data storage
3333  ->HwInitialize
3334 
3335 Return Value:
3336  TRUE - if initialization successful.
3337  FALSE - if initialization unsuccessful.
3338 
3339 --*/
3340 BOOLEAN
3341 NTAPI
3343  IN PVOID HwDeviceExtension
3344  )
3345 {
3346  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3347  ULONG numberChannels = deviceExtension->NumberChannels;
3348  ULONG c;
3349 
3350  KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base)\n"));
3351 
3352  if(WinVer_WDM_Model) {
3354  }
3355  if(deviceExtension->MasterDev) {
3356  KdPrint2((PRINT_PREFIX " mark chan %d of master controller [%x] as inited\n",
3357  deviceExtension->Channel, deviceExtension->DevIndex));
3358  BMList[deviceExtension->DevIndex].ChanInitOk |= 0x01 << deviceExtension->Channel;
3359  }
3360 
3361  /* do extra chipset specific setups */
3363 /*
3364  if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
3365  KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
3366  BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
3367  }
3368 */
3369  for (c = 0; c < numberChannels; c++) {
3370  AtapiHwInitialize__(deviceExtension, c);
3371  }
3372  KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base) done\n"));
3373  return TRUE;
3374 } // end AtapiHwInitialize()
3375 
3376 VOID
3377 NTAPI
3379  IN PHW_DEVICE_EXTENSION deviceExtension,
3380  IN ULONG lChannel
3381  )
3382 {
3383  ULONG i;
3384  UCHAR statusByte, errorByte;
3385  PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3386  PHW_LU_EXTENSION LunExt;
3387 // ULONG tmp32;
3388  ULONG PreferedMode = 0xffffffff;
3389 
3390  if((deviceExtension->HwFlags & UNIATA_AHCI) &&
3391  !UniataAhciChanImplemented(deviceExtension, lChannel)) {
3392  return;
3393  }
3394 
3395  AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
3396  FindDevices(deviceExtension, 0, lChannel);
3397 
3398  for (i = 0; i < chan->NumberLuns; i++) {
3399 
3400  KdPrint3((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel, i));
3401 
3402  LunExt = chan->lun[i];
3403  // skip empty slots
3404  if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
3405  continue;
3406  }
3407 
3408  AtapiDisableInterrupts(deviceExtension, lChannel);
3410 
3411  if (!(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) {
3412 
3413  KdPrint2((PRINT_PREFIX "AtapiHwInitialize: IDE branch\n"));
3414  // Enable media status notification
3415  IdeMediaStatus(TRUE,deviceExtension,lChannel,(UCHAR)i);
3416 
3417  // If supported, setup Multi-block transfers.
3418  statusByte = AtaCommand(deviceExtension, i, lChannel,
3419  IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
3421 
3422  // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3423  // command was aborted.
3424  if (statusByte & IDE_STATUS_ERROR) {
3425 
3426  // Read the error register.
3427  errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
3428 
3429  KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
3430  statusByte,
3431  errorByte));
3432 
3433  statusByte = AtaCommand(deviceExtension, i, lChannel,
3434  IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
3435  0, 0, ATA_WAIT_BASE_READY);
3436 
3437  if (statusByte & IDE_STATUS_ERROR) {
3438  // Read the error register.
3439  errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
3440 
3441  KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
3442  statusByte,
3443  errorByte));
3444  }
3445  // Adjust the devExt. value, if necessary.
3446  LunExt->MaximumBlockXfer = 0;
3447 
3448  } else {
3450  "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3451  i,
3452  LunExt->MaximumBlockXfer));
3453  }
3454 
3455  if(LunExt->IdentifyData.MajorRevision) {
3456 
3457  if(LunExt->opt_ReadCacheEnable) {
3458  KdPrint2((PRINT_PREFIX " Try Enable Read Cache\n"));
3459  // If supported, setup read/write cacheing
3460  statusByte = AtaCommand(deviceExtension, i, lChannel,
3461  IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3463 
3464  // Check for errors.
3465  if (statusByte & IDE_STATUS_ERROR) {
3467  "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3468  i));
3469  LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
3470  } else {
3472  }
3473  } else {
3474  KdPrint2((PRINT_PREFIX " Disable Read Cache\n"));
3475  statusByte = AtaCommand(deviceExtension, i, lChannel,
3476  IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3478  LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
3479  }
3480  if(LunExt->IdentifyData.FeaturesSupport.WriteCache) {
3481  if(LunExt->opt_WriteCacheEnable) {
3482  KdPrint2((PRINT_PREFIX " Try Enable Write Cache\n"));
3483  // If supported & allowed, setup write cacheing
3484  statusByte = AtaCommand(deviceExtension, i, lChannel,
3485  IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3487  // Check for errors.
3488  if (statusByte & IDE_STATUS_ERROR) {
3490  "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3491  i));
3492  LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
3493  } else {
3495  }
3496  } else {
3497  KdPrint2((PRINT_PREFIX " Disable Write Cache\n"));
3498  statusByte = AtaCommand(deviceExtension, i, lChannel,
3499  IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3501  LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
3502  }
3503  }
3504 
3505  if(/*LunExt->IdentifyData.FeaturesSupport.PowerMngt ||*/
3506  LunExt->IdentifyData.FeaturesSupport.APM) {
3507 
3508  if(LunExt->opt_AdvPowerMode) {
3509  KdPrint2((PRINT_PREFIX " Try Enable Adv. Power Mgmt\n"));
3510  // setup APM
3511  statusByte = AtaCommand(deviceExtension, i, lChannel,
3512  IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3514  // Check for errors.
3515  if (statusByte & IDE_STATUS_ERROR) {
3517  "AtapiHwInitialize: Enable APM on Device %d failed\n",
3518  i));
3519  }
3520  } else {
3521  KdPrint2((PRINT_PREFIX " Disable Adv. Power Mgmt\n"));
3522  statusByte = AtaCommand(deviceExtension, i, lChannel,
3523  IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3525  }
3526  }
3527  if(LunExt->IdentifyData.FeaturesSupport.AutoAcoustic) {
3528  if(LunExt->opt_AcousticMode) {
3529  KdPrint2((PRINT_PREFIX " Try Enable Acoustic Mgmt\n"));
3530  // setup acoustic mgmt
3531  statusByte = AtaCommand(deviceExtension, i, lChannel,
3532  IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3534  // Check for errors.
3535  if (statusByte & IDE_STATUS_ERROR) {
3537  "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3538  i));
3539  }
3540  } else {
3541  KdPrint2((PRINT_PREFIX " Disable Acoustic Mgmt\n"));
3542  statusByte = AtaCommand(deviceExtension, i, lChannel,
3543  IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3545  }
3546  }
3547  if(LunExt->IdentifyData.FeaturesSupport.Standby) {
3548  KdPrint2((PRINT_PREFIX " Try init standby timer: %d\n"));
3549  // setup standby timer
3550  statusByte = AtaCommand(deviceExtension, i, lChannel,
3551  IDE_COMMAND_IDLE, 0, 0, 0,
3553  // Check for errors.
3554  if (statusByte & IDE_STATUS_ERROR) {
3556  "AtapiHwInitialize: standby timer on Device %d failed\n",
3557  i));
3558  }
3559  }
3560  }
3561 
3562  } else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){
3563 
3564  ULONG j;
3565  //BOOLEAN isSanyo = FALSE;
3566  CCHAR vendorId[26];
3567 
3568  KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n"));
3569 
3570  // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3571  for (j = 0; j < 26; j += 2) {
3572 
3573  // Build a buffer based on the identify data.
3574  MOV_DW_SWP(vendorId[j], ((PUCHAR)LunExt->IdentifyData.ModelNumber)[j]);
3575  }
3576 
3577  if (!AtapiStringCmp (vendorId, "CD-ROM CDR", 11)) {
3578 
3579  // Inquiry string for older model had a '-', newer is '_'
3580  if (vendorId[12] == 'C') {
3581 
3582  // Torisan changer. Set the bit. This will be used in several places
3583  // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3585  LunExt->DiscsPresent = 3;
3586  //isSanyo = TRUE;
3587  }
3588  }
3589  }
3590 
3591  PreferedMode = LunExt->opt_MaxTransferMode;
3592  if((PreferedMode == 0xffffffff) || (PreferedMode > chan->MaxTransferMode)) {
3593  KdPrint2((PRINT_PREFIX "MaxTransferMode (overriden): %#x\n", chan->MaxTransferMode));
3594  PreferedMode = chan->MaxTransferMode;
3595  }
3596 
3597  if(LunExt->opt_PreferedTransferMode != 0xffffffff) {
3598  KdPrint2((PRINT_PREFIX "PreferedTransferMode: %#x\n", PreferedMode));
3599  PreferedMode = min(LunExt->opt_PreferedTransferMode, PreferedMode);
3600  }
3601 
3602  KdPrint2((PRINT_PREFIX " try mode %#x\n", PreferedMode));
3603  LunExt->LimitedTransferMode =
3604  LunExt->TransferMode =
3605  (CHAR)PreferedMode;
3606 
3607  AtapiDmaInit__(deviceExtension, LunExt);
3608 
3609  LunExt->LimitedTransferMode =
3610  LunExt->TransferMode;
3611  KdPrint2((PRINT_PREFIX "Using %#x mode\n", LunExt->TransferMode));
3612 
3613  // We need to get our device ready for action before
3614  // returning from this function
3615 
3616  // According to the atapi spec 2.5 or 2.6, an atapi device
3617  // clears its status BSY bit when it is ready for atapi commands.
3618  // However, some devices (Panasonic SQ-TC500N) are still
3619  // not ready even when the status BSY is clear. They don't react
3620  // to atapi commands.
3621  //
3622  // Since there is really no other indication that tells us
3623  // the drive is really ready for action. We are going to check BSY
3624  // is clear and then just wait for an arbitrary amount of time!
3625  //
3626  if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
3627  ULONG waitCount;
3628 
3629  // have to get out of the loop sometime!
3630  // 10000 * 100us = 1000,000us = 1000ms = 1s
3631  waitCount = 10000;
3632  GetStatus(chan, statusByte);
3633  if(statusByte == IDE_STATUS_WRONG) {
3634  waitCount = 0;
3635  }
3636  while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
3637 
3638  KdPrint2((PRINT_PREFIX "Wait for ATAPI (status %x)\n", statusByte));
3639  // Wait for Busy to drop.
3640  AtapiStallExecution(100);
3641  GetStatus(chan, statusByte);
3642  waitCount--;
3643  }
3644 
3645  // 5000 * 100us = 500,000us = 500ms = 0.5s
3646  if(statusByte != IDE_STATUS_WRONG) {
3647  waitCount = 5000;
3648  do {
3649  AtapiStallExecution(100);
3650  } while (waitCount--);
3651  }
3652  }
3653  GetBaseStatus(chan, statusByte);
3654  AtapiEnableInterrupts(deviceExtension, lChannel);
3655  AtapiStallExecution(10);
3656  }
3657 
3658  return;
3659 
3660 } // end AtapiHwInitialize__()
3661 
3662 
3663 #ifndef UNIATA_CORE
3664 
3665 VOID
3666 NTAPI
3668  IN PVOID HwDeviceExtension,
3670  IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus)
3671 {
3672  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3673  ULONG lChannel = GET_CHANNEL(Srb);
3674  PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3676  PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
3677 
3678  if (MechanismStatus) {
3679  LunExt->DiscsPresent = MechanismStatus->NumberAvailableSlots;
3680  if (LunExt->DiscsPresent > 1) {
3681  LunExt->DeviceFlags |= DFLAGS_ATAPI_CHANGER;
3682  }
3683  }
3684  return;
3685 } // end AtapiHwInitializeChanger()
3686 
3687 
3688 /*++
3689 
3690 Routine Description:
3691  This routine will parse the string for a match on the keyword, then
3692  calculate the value for the keyword and return it to the caller.
3693 
3694 Arguments:
3695  String - The ASCII string to parse.
3696  KeyWord - The keyword for the value desired.
3697 
3698 Return Values:
3699  Zero if value not found
3700  Value converted from ASCII to binary.
3701 
3702 --*/
3703 ULONG
3704 NTAPI
3706  IN PCCH String,
3707  IN PCCH KeyWord
3708  )
3709 {
3710  PCCH cptr;
3711  PCCH kptr;
3712  ULONG value;
3713  ULONG stringLength = 0;
3714  ULONG keyWordLength = 0;
3715  ULONG index;
3716 
3717  if (!String) {
3718  return 0;
3719  }
3720  if (!KeyWord) {
3721  return 0;
3722  }
3723 
3724  // Calculate the string length and lower case all characters.
3725  cptr = String;
3726  while (*cptr++) {
3727  stringLength++;
3728  }
3729 
3730  // Calculate the keyword length.
3731  kptr = KeyWord;
3732  while (*kptr++) {
3733  keyWordLength++;
3734  }
3735 
3736  if (keyWordLength > stringLength) {
3737 
3738  // Can't possibly have a match.
3739  return 0;
3740  }
3741 
3742  // Now setup and start the compare.
3743  cptr = String;
3744 
3745 ContinueSearch:
3746 
3747  // The input string may start with white space. Skip it.
3748  while (*cptr == ' ' || *cptr == '\t') {
3749  cptr++;
3750  }
3751 
3752  if (*cptr == '\0') {
3753  // end of string.
3754  return 0;
3755  }
3756 
3757  kptr = KeyWord;
3758  while ((*cptr == *kptr) ||
3759  (*cptr >= 'A' && *cptr <= 'Z' && *cptr + ('a' - 'A') == *kptr) ||
3760  (*cptr >= 'a' && *cptr <= 'z' && *cptr - ('a' - 'A') == *kptr)) {
3761  cptr++;
3762  kptr++;
3763 
3764  if (*cptr == '\0') {
3765  // end of string
3766  return 0;
3767  }
3768  }
3769 
3770  if (*kptr == '\0') {
3771 
3772  // May have a match backup and check for blank or equals.
3773  while (*cptr == ' ' || *cptr == '\t') {
3774  cptr++;
3775  }
3776 
3777  // Found a match. Make sure there is an equals.
3778  if (*cptr != '=') {
3779 
3780  // Not a match so move to the next semicolon.
3781  while (*cptr) {
3782  if (*cptr++ == ';') {
3783  goto ContinueSearch;
3784  }
3785  }
3786  return 0;
3787  }
3788  // Skip the equals sign.
3789  cptr++;
3790 
3791  // Skip white space.
3792  while ((*cptr == ' ') || (*cptr == '\t')) {
3793  cptr++;
3794  }
3795 
3796  if (*cptr == '\0') {
3797  // Early end of string, return not found
3798  return 0;
3799  }
3800 
3801  if (*cptr == ';') {
3802  // This isn't it either.
3803  cptr++;
3804  goto ContinueSearch;
3805  }
3806 
3807  value = 0;
3808  if ((*cptr == '0') && ((*(cptr + 1) == 'x') || (*(cptr + 1) == 'X'))) {
3809  // Value is in Hex. Skip the "0x"
3810  cptr += 2;
3811  for (index = 0; *(cptr + index); index++) {
3812 
3813  if (*(cptr + index) == ' ' ||
3814  *(cptr + index) == '\t' ||
3815  *(cptr + index) == ';') {
3816  break;
3817  }
3818 
3819  if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
3820  value = (16 * value) + (*(cptr + index) - '0');
3821  } else {
3822  if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
3823  value = (16 * value) + (*(cptr + index) - 'a' + 10);
3824  } else if ((*(cptr + index) >= 'A') && (*(cptr + index) <= 'F')) {
3825  value = (16 * value) + (*(cptr + index) - 'A' + 10);
3826  } else {
3827  // Syntax error, return not found.
3828  return 0;
3829  }
3830  }
3831  }
3832  } else {
3833 
3834  // Value is in Decimal.
3835  for (index = 0; *(cptr + index); index++) {
3836 
3837  if (*(cptr + index) == ' ' ||
3838  *(cptr + index) == '\t' ||
3839  *(cptr + index) == ';') {
3840  break;
3841  }
3842 
3843  if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
3844  value = (10 * value) + (*(cptr + index) - '0');
3845  } else {
3846 
3847  // Syntax error return not found.
3848  return 0;
3849  }
3850  }
3851  }
3852 
3853  return value;
3854  } else {
3855 
3856  // Not a match check for ';' to continue search.
3857  while (*cptr) {
3858  if (*cptr++ == ';') {
3859  goto ContinueSearch;
3860  }
3861  }
3862 
3863  return 0;
3864  }
3865 } // end AtapiParseArgumentString()_
3866 
3867 /*
3868  Timer callback
3869 */
3870 VOID
3871 NTAPI
3873  IN PVOID HwDeviceExtension,
3874  IN UCHAR lChannel
3875  )
3876 {
3877 
3878  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3879  PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3880  ULONG c, _c;
3881 
3883  UCHAR statusByte;
3884 
3885  KdPrint2((PRINT_PREFIX "AtapiCallBack:\n"));
3886  // If the last command was DSC restrictive, see if it's set. If so, the device is
3887  // ready for a new request. Otherwise, reset the timer and come back to here later.
3888 
3889  // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3890  // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3891  // we shall have no problem with interrupt handler.
3892  if (!srb || chan->ExpectingInterrupt) {
3893  KdPrint2((PRINT_PREFIX "AtapiCallBack: Calling ISR directly due to BUSY\n"));
3894  chan->DpcState = DPC_STATE_TIMER;
3895  if(!AtapiInterrupt__(HwDeviceExtension, lChannel)) {
3897  KdPrint2((PRINT_PREFIX "AtapiCallBack: What's fucking this ???\n"));
3898  }
3899  goto ReturnCallback;
3900  }
3901 
3902 #ifdef _DEBUG
3903  if (!IS_RDP((srb->Cdb[0]))) {
3904  KdPrint2((PRINT_PREFIX "AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb->Cdb[0]));
3905  }
3906 #endif
3907  if(!(chan->RDP)) {
3908  goto ReturnEnableIntr;
3909  }
3910  GetStatus(chan, statusByte);
3911  if (statusByte & IDE_STATUS_DSC) {
3912 
3913  UCHAR PathId = srb->PathId;
3914  UCHAR TargetId = srb->TargetId;
3915  UCHAR Lun = srb->Lun;
3916 
3917  KdPrint2((PRINT_PREFIX "AtapiCallBack: Found DSC for RDP - %#x\n", srb->Cdb[0]));
3918  AtapiDmaDBSync(chan, srb);
3919  UniataRemoveRequest(chan, srb);
3920  ScsiPortNotification(RequestComplete, deviceExtension, srb);
3921  // Clear current SRB.
3922  if(!deviceExtension->simplexOnly) {
3923  srb = UniataGetCurRequest(chan);
3924  } else {
3925  srb = NULL;
3926  }
3927  chan->RDP = FALSE;
3928 
3929  // Ask for next request.
3931  deviceExtension,
3932  PathId,
3933  TargetId,
3934  Lun);
3935  ScsiPortNotification(NextRequest, deviceExtension, NULL);
3936 
3937  if(srb) {
3938  AtapiStartIo__(HwDeviceExtension, srb, FALSE);
3939  }
3940 
3941  } else {
3942  KdPrint2((PRINT_PREFIX "AtapiCallBack: Requesting another timer for Op %#x\n",
3943  srb->Cdb[0]));
3944 
3945  AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
3947  1000);
3948 
3949  goto ReturnCallback;
3950  }
3951 
3952 ReturnEnableIntr:
3953 
3954  if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
3955  KdPrint2((PRINT_PREFIX "AtapiCallBack: CallDisableInterrupts\n"));
3956  //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3957 #ifdef UNIATA_USE_XXableInterrupts
3959  // must be called on DISPATCH_LEVEL
3960  ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
3962 #else
3963  AtapiEnableInterrupts(HwDeviceExtension, lChannel);
3964  InterlockedExchange(&(chan->CheckIntr),
3965  CHECK_INTR_IDLE);
3966  // Will raise IRQL to DIRQL
3967  AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
3969  1);
3970  KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
3971 #endif // UNIATA_USE_XXableInterrupts
3972  } else {
3973  //ASSERT(!deviceExtension->simplexOnly);
3974  }
3975 
3976 ReturnCallback:
3977 
3978  // Check other channel
3979  // In simplex mode no interrupts must appear on other channels
3980  for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3981  c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
3982 
3983  if(c == lChannel) {
3984  continue;
3985  }
3986 
3987  chan = &(deviceExtension->chan[c]);
3988 
3989  if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
3992  {
3993  //ASSERT(!deviceExtension->simplexOnly);
3994  chan->DpcState = DPC_STATE_ISR;
3995  if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
3997  }
3998  }
3999  }
4000  KdPrint2((PRINT_PREFIX "AtapiCallBack: return\n"));
4001  return;
4002 
4003 } // end AtapiCallBack__()
4004 
4005 VOID
4006 NTAPI
4008  IN PVOID HwDeviceExtension
4009  )
4010 {
4011  AtapiCallBack__(HwDeviceExtension, (UCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->ActiveDpcChan);
4012 } // end AtapiCallBack_X()
4013 
4014 #endif //UNIATA_CORE
4015 
4016 /*++
4017 
4018 Routine Description:
4019 
4020  This is the interrupt service routine for ATAPI IDE miniport driver.
4021 
4022 Arguments:
4023 
4024  HwDeviceExtension - HBA miniport driver's adapter data storage
4025 
4026 Return Value:
4027 
4028  TRUE if expecting an interrupt.
4029 
4030 --*/
4031 BOOLEAN
4032 NTAPI
4034  IN PVOID HwDeviceExtension
4035  )
4036 {
4037  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4038  ULONG c, _c;
4039  BOOLEAN status = FALSE;
4040  ULONG c_state;
4041  ULONG i_res = 0;
4042  ULONG pass;
4043  //BOOLEAN checked[AHCI_MAX_PORT];
4044  ULONG hIS;
4045  ULONG checked;
4046 
4047  KdPrint2((PRINT_PREFIX "Intr: DeviceID+VendorID/Rev %#x/%#x (ex %d)\n",
4048  deviceExtension->DevID, deviceExtension->RevID, deviceExtension->ExpectingInterrupt ));
4049 
4050  if(deviceExtension->HwFlags & UNIATA_AHCI) {
4051  // AHCI may generate state change notification, never skip this check
4052  hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
4053  KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
4054  if(!hIS) {
4055  return FALSE;
4056  }
4057  // assume all non-interrupted ports to be already checked
4058  checked = ~hIS;
4059  // assume all not implemented ports to be already checked
4060  checked |= ~deviceExtension->AHCI_PI;
4061  } else {
4062  checked = 0; // assume all ports are not checked
4063  }
4064 
4065  if(!deviceExtension->ExpectingInterrupt) {
4066  // if we do not expect interrupt, exit now,
4067  // but keep in mind that it can be unexpected one
4068  // Note: this is just a hint, not exact counter
4069  KdPrint2((PRINT_PREFIX "unexpected, 1st chance\n"));
4070  //deviceExtension->ExpectingInterrupt++;
4071  //return FALSE;
4072  }
4073  // clear this flag now, it can be set again in sub-calls
4074  deviceExtension->ExpectingInterrupt=0;
4075 
4076 
4077 // for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
4078 // checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
4079 // }
4080 
4081 // fc =
4082  for(pass=0; pass<2; pass++) {
4083  //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
4084  if(status && pass) {
4085  // we catched some expected interrupts now.
4086  // do not touch unexpected until next ISR call
4087  break;
4088  }
4089  for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
4090 
4091  c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
4092 
4093  if((checked>>c) & 0x01)
4094  continue;
4095 
4096  // check non-empty and expecting interrupt channels first
4097  if(!pass && !deviceExtension->chan[c].ExpectingInterrupt)
4098  continue;
4099 
4100  checked |= (ULONG)1 << c;
4101 
4102  KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
4103 
4104  if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
4105  // we get here on idle channels or when ISR is posted to DPC
4106  KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): disabled INTR on ch %d\n", c));
4107  continue;
4108  }
4109  // lock channel. Wait, while 2nd ISR checks interrupt on this channel
4110  do {
4111  KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): try lock\n"));
4112  // c_state = deviceExtension->chan[c].CheckIntr;
4113  // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
4114  // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
4115  // }
4116  c_state =
4117  (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4120  if(c_state == CHECK_INTR_IDLE) {
4121  // c_state = deviceExtension->chan[c].CheckIntr;
4122  // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
4123  // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
4124  // }
4125  c_state =
4126  (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4129  }
4130  } while(c_state == CHECK_INTR_CHECK);
4131  KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): locked\n"));
4132  // check if already serviced
4133  if(c_state == CHECK_INTR_ACTIVE) {
4134  KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
4135  continue;
4136  }
4137 
4138  if((c_state == CHECK_INTR_DETECTED) ||
4139  (i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
4140 
4141  if(i_res == INTERRUPT_REASON_UNEXPECTED) {
4142  KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): Catch unexpected\n"));
4143  InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4144  //return TRUE;
4145  status = TRUE;
4146  continue;
4147  }
4148  // disable interrupts on other channel of legacy mode
4149  // ISA-bridged onboard controller
4150  if(deviceExtension->simplexOnly /*||
4151  ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
4152  AtapiDisableInterrupts(deviceExtension, !c);
4153  }
4154 
4155  deviceExtension->chan[c].DpcState = DPC_STATE_ISR;
4156  if(AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
4157  deviceExtension->LastInterruptedChannel = (UCHAR)c;
4158  KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): return status TRUE\n"));
4159  status = TRUE;
4160  } else {
4161  KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
4162  InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4163  }
4164 
4165  // re-enable interrupts on other channel
4166  if(deviceExtension->simplexOnly /*||
4167  ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
4168  AtapiEnableInterrupts(deviceExtension, !c);
4169  }
4170 
4171  } else {
4172  KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
4173  InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4174  }
4175 
4176  }
4177  }
4178  KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): exit with status %#x\n", status));
4179  if(status) {
4180  deviceExtension->FirstChannelToCheck++;
4181  if(deviceExtension->FirstChannelToCheck >= deviceExtension->NumberChannels)
4182  deviceExtension->FirstChannelToCheck = 0;
4183  }
4184  return status;
4185 } // end AtapiInterrupt()
4186 
4187 //ULONG i2c = 0;
4188 #ifndef UNIATA_CORE
4189 
4190 BOOLEAN
4191 NTAPI
4194  IN PVOID Isr2HwDeviceExtension
4195  )
4196 {
4197  // This ISR is intended to catch interrupts when we are already in other ISR instance
4198  // for the same device. This may happen when we have multiple channels,
4199  // especially on SMP machines
4200 
4201  PISR2_DEVICE_EXTENSION Isr2DeviceExtension = (PISR2_DEVICE_EXTENSION)Isr2HwDeviceExtension;
4202  PHW_DEVICE_EXTENSION deviceExtension = Isr2DeviceExtension->HwDeviceExtension;
4203  ULONG c;
4204  BOOLEAN status = FALSE;
4205  ULONG c_count = 0;
4206  ULONG i_res;
4207  ULONG hIS;
4208  ULONG checked;
4209 
4210  // we should never get here for ISA/MCA
4211  if(!BMList[deviceExtension->DevIndex].Isr2Enable) {
4212  KdPrint2((PRINT_PREFIX "AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension->DevIndex, deviceExtension->Channel));
4213  return FALSE;
4214  }
4215 
4216  if(deviceExtension->HwFlags & UNIATA_AHCI) {
4217  // AHCI may generate state change notification, never skip this check
4218  hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
4219  KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
4220  if(!hIS) {
4221  return FALSE;
4222  }
4223  // assume all non-interrupted ports to be already checked
4224  checked = ~hIS;
4225  // assume all not implemented ports to be already checked
4226  checked |= ~deviceExtension->AHCI_PI;
4227 
4228  } else {
4229  checked = 0; // assume all ports are not checked
4230  }
4231  if(!deviceExtension->ExpectingInterrupt) {
4232  KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
4233  deviceExtension->ExpectingInterrupt++;
4234  return FALSE;
4235  }
4236  //deviceExtension->ExpectingInterrupt = 0;
4237 
4238  for(c=0; c<deviceExtension->NumberChannels; c++) {
4239  KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
4240 
4241  if((checked>>c) & 0x01)
4242  continue;
4243 
4244  checked |= (ULONG)1 << c;
4245 
4246  if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
4247  KdPrint2((PRINT_PREFIX "AtapiInterrupt2: disabled INTR\n"));
4248  continue;
4249  }
4250 
4251  if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4254  {
4255  KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
4256  // hunt on unexpected intr (Some devices generate double interrupts,
4257  // some controllers (at least CMD649) interrupt twice with small delay.
4258  // If interrupts are disabled, they queue interrupt and re-issue it later,
4259  // when we do not expect it.
4260  continue;
4261  }
4262 
4263  c_count++;
4264  if((i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
4265 
4266  KdPrint2((PRINT_PREFIX "AtapiInterrupt2: intr\n"));
4267  if(i_res == INTERRUPT_REASON_UNEXPECTED) {
4268  KdPrint2((PRINT_PREFIX "AtapiInterrupt2: Catch unexpected\n"));
4269  InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4270  return TRUE;
4271  }
4272 
4273  status = TRUE;
4274  InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_DETECTED);
4275  } else {
4276  InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4277  }
4278  }
4279  KdPrint2((PRINT_PREFIX "AtapiInterrupt2: status %d, c_count %d\n", status, c_count));
4280  if(status && (c_count != deviceExtension->NumberChannels)) {
4281  // there is an active ISR/DPC for one channel, but
4282  // we have an interrupt from another one
4283  // Lets inform current ISR/DPC about new interrupt
4284  InterlockedExchange(&(deviceExtension->ReCheckIntr), CHECK_INTR_DETECTED);
4285  } else {
4286  status = FALSE;
4287  }
4288  KdPrint2((PRINT_PREFIX "AtapiInterrupt2: return %d\n", status));
4289  return status;
4290 
4291 } // end AtapiInterrupt2()
4292 
4294 NTAPI
4296  IN PVOID HwDeviceExtension
4297  )
4298 {
4299  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4300  ULONG c;
4301 
4302  for(c=0; c<deviceExtension->NumberChannels; c++) {
4303  KdPrint2((PRINT_PREFIX "AtapiInterruptDpc: %#x\n",c));
4304 
4305  if(!(deviceExtension->chan[c].ChannelCtrlFlags & CTRFLAGS_DPC_REQ)) {
4306 
4307  if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4310  {
4311  continue;
4312  }
4313 
4314  } else {
4315  deviceExtension->chan[c].ChannelCtrlFlags &= ~CTRFLAGS_DPC_REQ;
4316  }
4317 /*
4318  if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
4319  AtapiDisableInterrupts(deviceExtension, lChannel);
4320  }
4321 */
4322  deviceExtension->chan[c].DpcState = DPC_STATE_DPC;
4323  if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
4324  InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4325  }
4326  }
4327  return RETVAL_XXableInterrupts;
4328 } // end AtapiInterruptDpc()
4329 
4330 
4332 NTAPI
4334  IN PVOID HwDeviceExtension
4335  )
4336 {
4337  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4338  KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__():\n"));
4339  ULONG c;
4340  PHW_CHANNEL chan = NULL;
4341 
4342  for(c=0; c<deviceExtension->NumberChannels; c++) {
4343  KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__(2): %#x\n",c));
4344  chan = &(deviceExtension->chan[c]);
4345 
4347  // enable intrs on requested channel
4349  AtapiEnableInterrupts(HwDeviceExtension, c);
4350  InterlockedExchange(&(chan->CheckIntr),
4351  CHECK_INTR_IDLE);
4352 
4353  // check if current or other channel(s) interrupted
4354  //AtapiInterrupt(HwDeviceExtension);
4355 
4356  if(deviceExtension->simplexOnly) {
4357  break;
4358  }
4359  } else {
4360  // check if other channel(s) interrupted
4361  // must do nothing in simplex mode
4362  if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
4365  continue;
4366  }
4367  //ASSERT(!deviceExtension->simplexOnly);
4368  chan->DpcState = DPC_STATE_ISR;
4369  if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
4371  }
4372  }
4373  }
4374  // In simplex mode next command must be sent to device here
4375  if(deviceExtension->simplexOnly && chan) {
4376  PSCSI_REQUEST_BLOCK srb;
4377  chan = UniataGetNextChannel(chan);
4378  if(chan) {
4379  srb = UniataGetCurRequest(chan);
4380  } else {
4381  srb = NULL;
4382  }
4383  if(srb) {
4384  AtapiStartIo__(HwDeviceExtension, srb, FALSE);
4385  }
4386  }
4387 
4388  return RETVAL_XXableInterrupts;
4389 
4390 } // end AtapiEnableInterrupts__()
4391 
4392 #endif //UNIATA_CORE
4393 
4394 
4395 VOID
4396 NTAPI
4398  IN PVOID HwDeviceExtension,
4399  IN ULONG c
4400  )
4401 {
4402  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4403  PHW_CHANNEL chan;
4404  //UCHAR statusByte;
4405 
4406  if(c >= deviceExtension->NumberChannels) {
4407  KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c));
4408  return;
4409  }
4410  if((deviceExtension->HwFlags & UNIATA_AHCI) &&
4411  !UniataAhciChanImplemented(deviceExtension, c)) {
4412  KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c));
4413  return;
4414  }
4415 
4416  chan = &(deviceExtension->chan[c]);
4417  KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr));
4418  if(!InterlockedDecrement(&chan->DisableIntr)) {
4419  if(deviceExtension->HwFlags & UNIATA_AHCI) {
4423  ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) |
4424  ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | /* DEBUG */
4428  );
4429  } else {
4430  //SelectDrive(chan, 0);
4431  //GetBaseStatus(chan, statusByte);
4433  0 | IDE_DC_A_4BIT );
4434  //if(chan->NumberLuns) {
4435  // SelectDrive(chan, 1);
4436  // GetBaseStatus(chan, statusByte);
4437  // AtapiWritePort1(chan, IDX_IO2_o_Control,
4438  // IDE_DC_A_4BIT );
4439  // SelectDrive(chan, chan->cur_cdev);
4440  //}
4441  }
4443  } else {
4444  if(deviceExtension->HwFlags & UNIATA_AHCI) {
4445  // keep interrupts disabled
4447  } else {
4449  IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4450  }
4451  }
4452  return;
4453 } // end AtapiEnableInterrupts()
4454 
4455 VOID
4456 NTAPI
4458  IN PVOID HwDeviceExtension,
4459  IN ULONG c
4460  )
4461 {
4462  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4463  PHW_CHANNEL chan;
4464  if(c >= deviceExtension->NumberChannels) {
4465  KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c));
4466  return;
4467  }
4468  chan = &(deviceExtension->chan[c]);
4469  KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: %d\n",c, chan->DisableIntr));
4470  // mark channel as busy
4471  if(InterlockedIncrement(&chan->DisableIntr)) {
4472  if(deviceExtension->HwFlags & UNIATA_AHCI) {
4474  } else {
4475  //SelectDrive(chan, 0);
4477  IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4478  //if(chan->NumberLuns) {
4479  // SelectDrive(chan, 1);
4480  // AtapiWritePort1(chan, IDX_IO2_o_Control,
4481  // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4482  // SelectDrive(chan, chan->cur_cdev);
4483  //}
4484  }
4486  }
4487 
4488  return;
4489 } // end AtapiDisableInterrupts()
4490 
4491 VOID
4493  IN struct _HW_CHANNEL* chan,
4494  IN BOOLEAN Expecting
4495  )
4496 {
4497  chan->ExpectingInterrupt = Expecting;
4498  if(Expecting) {
4499  chan->DeviceExtension->ExpectingInterrupt++;
4500  } else
4501  if(chan->DeviceExtension->ExpectingInterrupt) {
4502  chan->DeviceExtension->ExpectingInterrupt--;
4503  }
4504  return;
4505 } // end UniataExpectChannelInterrupt()
4506 
4507 /*
4508  Check hardware for interrupt state
4509  */
4510 BOOLEAN
4511 NTAPI
4513  IN PVOID HwDeviceExtension,
4514  IN UCHAR c // logical channel
4515  )
4516 {
4517  PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4518  PHW_CHANNEL chan = &(deviceExtension->chan[c]);
4519  PHW_LU_EXTENSION LunExt;
4520 
4521  ULONG VendorID = deviceExtension->DevID & 0xffff;
4522  ULONG ChipType = deviceExtension->HwFlags & CHIPTYPE_MASK;
4523 
4524  ULONG status;
4525  ULONG pr_status = 0;
4526  UCHAR dma_status = 0;
4527  UCHAR reg8 = 0;
4528  ULONG reg32 = 0;
4529  UCHAR statusByte = 0;
4530  ULONG slotNumber = deviceExtension->slotNumber;
4531  ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
4532  ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
4533  UCHAR Channel;
4534  UCHAR lChannel;
4535  BOOLEAN DmaTransfer = FALSE;
4536  BOOLEAN OurInterrupt = FALSE;
4537  BOOLEAN StatusValid = FALSE;
4538 // ULONG k;
4539  UCHAR interruptReason;
4540  BOOLEAN EarlyIntr = FALSE;
4541  BOOLEAN SingleBlockIntr = FALSE;
4542 
4543  KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__:\n"));
4544 
4545  lChannel = c;
4546  Channel = (UCHAR)(deviceExtension->Channel + lChannel);
4547  LunExt = chan->lun[chan->cur_cdev];
4548 
4549  //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4550  //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4551 
4552  if((ChipFlags & UNIATA_AHCI) &&
4553  UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
4554 
4555  if(!UniataAhciChanImplemented(deviceExtension, lChannel)) {
4556  return OurInterrupt;
4557  }
4558 
4559  OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
4560  if((OurInterrupt == INTERRUPT_REASON_UNEXPECTED) &&
4561  (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
4562  UniataAhciWaitCommandReady(chan, 2 /* ms */ );
4563  statusByte = (UCHAR)UniataAhciWaitReady(chan, 0 /* immediate */);
4564  if(!(statusByte & (IDE_STATUS_BUSY)) ) {
4565  KdPrint2((PRINT_PREFIX "ATAPI special case READY\n"));
4566  //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4567  OurInterrupt = INTERRUPT_REASON_OUR;
4568  } else
4569  if((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRDY)) == (IDE_STATUS_BUSY | IDE_STATUS_DRDY) ) {
4570  KdPrint2((PRINT_PREFIX "ATAPI special case pre ERR-READY\n"));
4571  OurInterrupt = INTERRUPT_REASON_OUR;
4572  } else
4573  if(statusByte & IDE_STATUS_ERROR) {
4574  KdPrint2((PRINT_PREFIX "ATAPI special case ERR-READY\n"));
4575  OurInterrupt = INTERRUPT_REASON_OUR;
4576  } else {
4577  KdPrint2((PRINT_PREFIX "ATAPI special case ? %x\n", statusByte));
4578  OurInterrupt = INTERRUPT_REASON_OUR;
4579  }
4580  }
4581  return OurInterrupt;
4582  }
4583 
4585  DmaTransfer = TRUE;
4586  KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension->DevIndex,
4587  deviceExtension->Channel + c, c));
4588  } else {
4589  KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension->DevIndex,
4590  deviceExtension->Channel + c, c));
4591  dma_status = GetDmaStatus(deviceExtension, lChannel);
4592  KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
4593  }
4594 
4595  // do controller-specific interrupt servicing staff
4596  if(deviceExtension->UnknownDev) {
4597  KdPrint2((PRINT_PREFIX " UnknownDev\n"));
4598  goto check_unknown;
4599  }
4600 
4601  // Attention !
4602  // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4603  // Such behavior was observed with Intel ICH-xxx chips
4604  // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4605 
4606  switch(VendorID) {
4607 
4608  case ATA_PROMISE_ID: {
4609  switch(ChipType) {
4610  case PROLD:
4611  case PRNEW:
4612  status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1c);
4613  if (!DmaTransfer)
4614  break;
4615  if (!(status &
4616  ((Channel) ? 0x00004000 : 0x00000400))) {
4617  KdPrint2((PRINT_PREFIX " Promise old/new unexpected\n"));
4618  return INTERRUPT_REASON_IGNORE;
4619  }
4620  break;
4621  case PRTX:
4624  if (!DmaTransfer)
4625  break;
4626  if(!(status & 0x20)) {
4627  KdPrint2((PRINT_PREFIX " Promise tx unexpected\n"));
4628  return INTERRUPT_REASON_IGNORE;
4629  }
4630  break;
4631  case PRMIO: {
4632  ULONG stat_reg = (ChipFlags & PRG2) ? 0x60 : 0x6c;
4633  status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40);
4634  AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40, status);
4635 
4636  if(status & (1 << (Channel+1))) {
4637  // our
4638  } else {
4639  KdPrint2((PRINT_PREFIX " Promise mio unexpected\n"));
4640  return INTERRUPT_REASON_IGNORE;
4641  }
4642 
4643  if(!(ChipFlags & UNIATA_SATA))
4644  break;
4645 
4646  pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg);
4647  AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg, (pr_status & (0x11 << Channel)));
4648  if(pr_status & (0x11 << Channel)) {
4649  // TODO: reset channel
4650  KdPrint2((PRINT_PREFIX " Promise mio unexpected + reset req\n"));
4651  UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
4652  }
4653  if(!(status & (0x01 << Channel))) {
4654  // Connect event
4655  KdPrint2((PRINT_PREFIX " Promise mio unexpected attach\n"));
4656  UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0);
4657  }
4658  if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4659  OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4660  } else {
4661  return INTERRUPT_REASON_IGNORE;
4662  }
4663 
4664  AtapiWritePort4(chan, IDX_BM_DeviceSpecific0, 0x00000001);
4665  break; }
4666  }
4667  break; }
4668  case ATA_NVIDIA_ID: {
4669  if(!(ChipFlags & UNIATA_SATA) || (ChipFlags & NVGEN))
4670  break;
4671 
4672  KdPrint2((PRINT_PREFIX "NVIDIA\n"));
4673 
4674  ULONG offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
4675  ULONG shift = Channel * ((ChipFlags & NVQ) ? 4 : 16);
4676 
4677  /* get and clear interrupt status */
4678  if(ChipFlags & NVQ) {
4679  pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
4680  AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0fUL << shift) | 0x00f000f0);
4681  } else {
4682  pr_status =