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