ReactOS  0.4.13-dev-259-g5ca9c9c
storahci.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GNU GPLv2 only as published by the Free Software Foundation
4  * PURPOSE: To Implement AHCI Miniport driver targeting storport NT 5.2
5  * PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com)
6  */
7 
8 #include "storahci.h"
9 
21 BOOLEAN
22 NTAPI
24  __in PVOID DeviceExtension
25  )
26 {
27  PAHCI_PORT_EXTENSION PortExtension;
30  ULONG mappedLength, portNumber, ticks;
31  PAHCI_ADAPTER_EXTENSION adapterExtension;
32  STOR_PHYSICAL_ADDRESS commandListPhysical, receivedFISPhysical;
33 
34  AhciDebugPrint("AhciPortInitialize()\n");
35 
36  PortExtension = (PAHCI_PORT_EXTENSION)DeviceExtension;
37  adapterExtension = PortExtension->AdapterExtension;
38  abar = adapterExtension->ABAR_Address;
39  portNumber = PortExtension->PortNumber;
40 
41  NT_ASSERT(abar != NULL);
42  NT_ASSERT(portNumber < adapterExtension->PortCount);
43 
44  PortExtension->Port = &abar->PortList[portNumber];
45 
46  commandListPhysical = StorPortGetPhysicalAddress(adapterExtension,
47  NULL,
48  PortExtension->CommandList,
49  &mappedLength);
50 
51  if ((mappedLength == 0) || ((commandListPhysical.LowPart % 1024) != 0))
52  {
53  AhciDebugPrint("\tcommandListPhysical mappedLength:%d\n", mappedLength);
54  return FALSE;
55  }
56 
57  receivedFISPhysical = StorPortGetPhysicalAddress(adapterExtension,
58  NULL,
59  PortExtension->ReceivedFIS,
60  &mappedLength);
61 
62  if ((mappedLength == 0) || ((receivedFISPhysical.LowPart % 256) != 0))
63  {
64  AhciDebugPrint("\treceivedFISPhysical mappedLength:%d\n", mappedLength);
65  return FALSE;
66  }
67 
68  // Ensure that the controller is not in the running state by reading and examining each
69  // implemented port’s PxCMD register. If PxCMD.ST, PxCMD.CR, PxCMD.FRE and
70  // PxCMD.FR are all cleared, the port is in an idle state. Otherwise, the port is not idle and
71  // should be placed in the idle state prior to manipulating HBA and port specific registers.
72  // System software places a port into the idle state by clearing PxCMD.ST and waiting for
73  // PxCMD.CR to return ‘0’ when read. Software should wait at least 500 milliseconds for
74  // this to occur. If PxCMD.FRE is set to ‘1’, software should clear it to ‘0’ and wait at least
75  // 500 milliseconds for PxCMD.FR to return ‘0’ when read. If PxCMD.CR or PxCMD.FR do
76  // not clear to ‘0’ correctly, then software may attempt a port reset or a full HBA reset to recove
77 
78  // TODO: Check if port is in idle state or not, if not then restart port
79  cmd.Status = StorPortReadRegisterUlong(adapterExtension, &PortExtension->Port->CMD);
80  if ((cmd.FR != 0) || (cmd.CR != 0) || (cmd.FRE != 0) || (cmd.ST != 0))
81  {
82  cmd.ST = 0;
83  cmd.FRE = 0;
84 
85  ticks = 3;
86  do
87  {
89  cmd.Status = StorPortReadRegisterUlong(adapterExtension, &PortExtension->Port->CMD);
90  if (ticks == 0)
91  {
92  AhciDebugPrint("\tAttempt to reset port failed: %x\n", cmd);
93  return FALSE;
94  }
95  ticks--;
96  }
97  while(cmd.CR != 0 || cmd.FR != 0);
98  }
99 
100  // 10.1.2 For each implemented port, system software shall allocate memory for and program:
101  // ? PxCLB and PxCLBU (if CAP.S64A is set to ‘1’)
102  // ? PxFB and PxFBU (if CAP.S64A is set to ‘1’)
103  // Note: Assuming 32bit support only
104  StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->CLB, commandListPhysical.LowPart);
105  if (IsAdapterCAPS64(adapterExtension->CAP))
106  {
107  StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->CLBU, commandListPhysical.HighPart);
108  }
109 
110  StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->FB, receivedFISPhysical.LowPart);
111  if (IsAdapterCAPS64(adapterExtension->CAP))
112  {
113  StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->FBU, receivedFISPhysical.HighPart);
114  }
115 
116  PortExtension->IdentifyDeviceDataPhysicalAddress = StorPortGetPhysicalAddress(adapterExtension,
117  NULL,
118  PortExtension->IdentifyDeviceData,
119  &mappedLength);
120 
121  // set device power state flag to D0
122  PortExtension->DevicePowerState = StorPowerDeviceD0;
123 
124  // clear pending interrupts
125  StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->SERR, (ULONG)~0);
126  StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->IS, (ULONG)~0);
127  StorPortWriteRegisterUlong(adapterExtension, adapterExtension->IS, (1 << PortExtension->PortNumber));
128 
129  return TRUE;
130 }// -- AhciPortInitialize();
131 
144 BOOLEAN
146  __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
148  )
149 {
150  PCHAR nonCachedExtension, tmp;
151  ULONG index, NCS, AlignedNCS;
152  ULONG portCount, portImplemented, nonCachedExtensionSize;
153  PAHCI_PORT_EXTENSION PortExtension;
154 
155  AhciDebugPrint("AhciAllocateResourceForAdapter()\n");
156 
157  NCS = AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP);
158  AlignedNCS = ROUND_UP(NCS, 8);
159 
160  // get port count -- Number of set bits in `AdapterExtension->PortImplemented`
161  portCount = 0;
162  portImplemented = AdapterExtension->PortImplemented;
163 
164  NT_ASSERT(portImplemented != 0);
165  for (index = MAXIMUM_AHCI_PORT_COUNT - 1; index > 0; index--)
166  if ((portImplemented & (1 << index)) != 0)
167  break;
168 
169  portCount = index + 1;
170  AhciDebugPrint("\tPort Count: %d\n", portCount);
171 
172  AdapterExtension->PortCount = portCount;
173  nonCachedExtensionSize = sizeof(AHCI_COMMAND_HEADER) * AlignedNCS + //should be 1K aligned
174  sizeof(AHCI_RECEIVED_FIS) +
175  sizeof(IDENTIFY_DEVICE_DATA);
176 
177  // align nonCachedExtensionSize to 1024
178  nonCachedExtensionSize = ROUND_UP(nonCachedExtensionSize, 1024);
179 
180  AdapterExtension->NonCachedExtension = StorPortGetUncachedExtension(AdapterExtension,
181  ConfigInfo,
182  nonCachedExtensionSize * portCount);
183 
184  if (AdapterExtension->NonCachedExtension == NULL)
185  {
186  AhciDebugPrint("\tadapterExtension->NonCachedExtension == NULL\n");
187  return FALSE;
188  }
189 
190  nonCachedExtension = AdapterExtension->NonCachedExtension;
191  AhciZeroMemory(nonCachedExtension, nonCachedExtensionSize * portCount);
192 
193  for (index = 0; index < portCount; index++)
194  {
195  PortExtension = &AdapterExtension->PortExtension[index];
196 
197  PortExtension->DeviceParams.IsActive = FALSE;
198  if ((AdapterExtension->PortImplemented & (1 << index)) != 0)
199  {
200  PortExtension->PortNumber = index;
201  PortExtension->DeviceParams.IsActive = TRUE;
202  PortExtension->AdapterExtension = AdapterExtension;
203  PortExtension->CommandList = (PAHCI_COMMAND_HEADER)nonCachedExtension;
204 
205  tmp = (PCHAR)(nonCachedExtension + sizeof(AHCI_COMMAND_HEADER) * AlignedNCS);
206 
207  PortExtension->ReceivedFIS = (PAHCI_RECEIVED_FIS)tmp;
208  PortExtension->IdentifyDeviceData = (PIDENTIFY_DEVICE_DATA)(tmp + sizeof(AHCI_RECEIVED_FIS));
209  PortExtension->MaxPortQueueDepth = NCS;
210  nonCachedExtension += nonCachedExtensionSize;
211  }
212  }
213 
214  return TRUE;
215 }// -- AhciAllocateResourceForAdapter();
216 
227 BOOLEAN
229  __in PAHCI_PORT_EXTENSION PortExtension
230  )
231 {
232  ULONG index;
238  PAHCI_ADAPTER_EXTENSION AdapterExtension;
239 
240  AhciDebugPrint("AhciStartPort()\n");
241 
242  AdapterExtension = PortExtension->AdapterExtension;
243  cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
244 
245  if ((cmd.FR == 1) && (cmd.CR == 1) && (cmd.FRE == 1) && (cmd.ST == 1))
246  {
247  // Already Running
248  return TRUE;
249  }
250 
251  cmd.SUD = 1;
252  StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CMD, cmd.Status);
253 
254  if (((cmd.FR == 1) && (cmd.FRE == 0)) ||
255  ((cmd.CR == 1) && (cmd.ST == 0)))
256  {
257  AhciDebugPrint("\tCOMRESET\n");
258  // perform COMRESET
259  // section 10.4.2
260 
261  // Software causes a port reset (COMRESET) by writing 1h to the PxSCTL.DET field to invoke a
262  // COMRESET on the interface and start a re-establishment of Phy layer communications. Software shall
263  // wait at least 1 millisecond before clearing PxSCTL.DET to 0h; this ensures that at least one COMRESET
264  // signal is sent over the interface. After clearing PxSCTL.DET to 0h, software should wait for
265  // communication to be re-established as indicated by PxSSTS.DET being set to 3h. Then software should
266  // write all 1s to the PxSERR register to clear any bits that were set as part of the port reset.
267 
268  sctl.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL);
269  sctl.DET = 1;
270  StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL, sctl.Status);
271 
273 
274  sctl.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL);
275  sctl.DET = 0;
276  StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL, sctl.Status);
277 
278  // Poll DET to verify if a device is attached to the port
279  index = 0;
280  do
281  {
283  ssts.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SSTS);
284 
285  index++;
286  if (ssts.DET != 0)
287  {
288  break;
289  }
290  }
291  while(index < 30);
292  }
293 
294  ssts.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SSTS);
295  switch (ssts.DET)
296  {
297  case 0x3:
298  {
299  NT_ASSERT(cmd.ST == 0);
300 
301  // make sure FIS Recieve is enabled (cmd.FRE)
302  index = 0;
303  do
304  {
305  StorPortStallExecution(10000);
306  cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
307  cmd.FRE = 1;
308  StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CMD, cmd.Status);
309  index++;
310  }
311  while((cmd.FR != 1) && (index < 3));
312 
313  if (cmd.FR != 1)
314  {
315  // failed to start FIS DMA engine
316  // it can crash the driver later
317  // so better to turn this port off
318  return FALSE;
319  }
320 
321  // start port channel
322  // set cmd.ST
323 
324  NT_ASSERT(cmd.FRE == 1);
325  NT_ASSERT(cmd.CR == 0);
326 
327  // why assert? well If we face such condition on DET = 0x3
328  // then we don't have port in idle state and hence before executing this part of code
329  // we must have restarted it.
330  tfd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->TFD);
331 
332  if ((tfd.STS.BSY) || (tfd.STS.DRQ))
333  {
334  AhciDebugPrint("\tUnhandled Case BSY-DRQ\n");
335  }
336 
337  // clear pending interrupts
338  StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->SERR, (ULONG)~0);
339  StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->IS, (ULONG)~0);
340  StorPortWriteRegisterUlong(AdapterExtension, AdapterExtension->IS, (1 << PortExtension->PortNumber));
341 
342  // set IE
343  ie.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->IE);
344  /* Device to Host Register FIS Interrupt Enable */
345  ie.DHRE = 1;
346  /* PIO Setup FIS Interrupt Enable */
347  ie.PSE = 1;
348  /* DMA Setup FIS Interrupt Enable */
349  ie.DSE = 1;
350  /* Set Device Bits FIS Interrupt Enable */
351  ie.SDBE = 1;
352  /* Unknown FIS Interrupt Enable */
353  ie.UFE = 0;
354  /* Descriptor Processed Interrupt Enable */
355  ie.DPE = 0;
356  /* Port Change Interrupt Enable */
357  ie.PCE = 1;
358  /* Device Mechanical Presence Enable */
359  ie.DMPE = 0;
360  /* PhyRdy Change Interrupt Enable */
361  ie.PRCE = 1;
362  /* Incorrect Port Multiplier Enable */
363  ie.IPME = 0;
364  /* Overflow Enable */
365  ie.OFE = 1;
366  /* Interface Non-fatal Error Enable */
367  ie.INFE = 1;
368  /* Interface Fatal Error Enable */
369  ie.IFE = 1;
370  /* Host Bus Data Error Enable */
371  ie.HBDE = 1;
372  /* Host Bus Fatal Error Enable */
373  ie.HBFE = 1;
374  /* Task File Error Enable */
375  ie.TFEE = 1;
376 
377  cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
378  /* Cold Presence Detect Enable */
379  if (cmd.CPD) // does it support CPD?
380  {
381  // disable it for now
382  ie.CPDE = 0;
383  }
384 
385  // should I replace this to single line?
386  // by directly setting ie.Status?
387 
388  StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->IE, ie.Status);
389 
390  cmd.ST = 1;
391  StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CMD, cmd.Status);
392  cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
393 
394  if (cmd.ST != 1)
395  {
396  AhciDebugPrint("\tFailed to start Port\n");
397  return FALSE;
398  }
399 
400  return TRUE;
401  }
402  default:
403  // unhandled case
404  AhciDebugPrint("\tDET == %x Unsupported\n", ssts.DET);
405  return FALSE;
406  }
407 }// -- AhciStartPort();
408 
420 VOID
423  __in PVOID HwDeviceExtension,
426  )
427 {
429  PAHCI_SRB_EXTENSION SrbExtension;
430  STOR_LOCK_HANDLE lockhandle = {0};
432  PAHCI_ADAPTER_EXTENSION AdapterExtension;
433  PAHCI_PORT_EXTENSION PortExtension;
434 
437 
438  AhciDebugPrint("AhciCommandCompletionDpcRoutine()\n");
439 
440  AdapterExtension = (PAHCI_ADAPTER_EXTENSION)HwDeviceExtension;
441  PortExtension = (PAHCI_PORT_EXTENSION)SystemArgument1;
442 
443  StorPortAcquireSpinLock(AdapterExtension, InterruptLock, NULL, &lockhandle);
444  Srb = RemoveQueue(&PortExtension->CompletionQueue);
445  StorPortReleaseSpinLock(AdapterExtension, &lockhandle);
446 
447  NT_ASSERT(Srb != NULL);
448 
449  if (Srb->SrbStatus == SRB_STATUS_PENDING)
450  {
451  Srb->SrbStatus = SRB_STATUS_SUCCESS;
452  }
453  else
454  {
455  return;
456  }
457 
458  SrbExtension = GetSrbExtension(Srb);
459 
460  CompletionRoutine = SrbExtension->CompletionRoutine;
462 
463  // now it's completion routine responsibility to set SrbStatus
464  CompletionRoutine(PortExtension, Srb);
465 
466  StorPortNotification(RequestComplete, AdapterExtension, Srb);
467 
468  return;
469 }// -- AhciCommandCompletionDpcRoutine();
470 
482 BOOLEAN
484  __in PVOID DeviceExtension
485  )
486 {
487  ULONG index;
488  PAHCI_ADAPTER_EXTENSION AdapterExtension;
489  PAHCI_PORT_EXTENSION PortExtension;
490 
491  AhciDebugPrint("AhciHwPassiveInitialize()\n");
492 
493  AdapterExtension = (PAHCI_ADAPTER_EXTENSION)DeviceExtension;
494 
495  for (index = 0; index < AdapterExtension->PortCount; index++)
496  {
497  if ((AdapterExtension->PortImplemented & (0x1 << index)) != 0)
498  {
499  PortExtension = &AdapterExtension->PortExtension[index];
500  PortExtension->DeviceParams.IsActive = AhciStartPort(PortExtension);
501  StorPortInitializeDpc(AdapterExtension, &PortExtension->CommandCompletion, AhciCommandCompletionDpcRoutine);
502  }
503  }
504 
505  return TRUE;
506 }// -- AhciHwPassiveInitialize();
507 
519 BOOLEAN
520 NTAPI
522  __in PVOID DeviceExtension
523  )
524 {
525  PAHCI_ADAPTER_EXTENSION AdapterExtension;
526  AHCI_GHC ghc;
527 
528  AhciDebugPrint("AhciHwInitialize()\n");
529 
530  AdapterExtension = (PAHCI_ADAPTER_EXTENSION)DeviceExtension;
531  AdapterExtension->StateFlags.MessagePerPort = FALSE;
532 
533  // First check what type of interrupt/synchronization device is using
534  ghc.Status = StorPortReadRegisterUlong(AdapterExtension, &AdapterExtension->ABAR_Address->GHC);
535 
536  // When set to ‘1’ by hardware, indicates that the HBA requested more than one MSI vector
537  // but has reverted to using the first vector only. When this bit is cleared to ‘0’,
538  // the HBA has not reverted to single MSI mode (i.e. hardware is already in single MSI mode,
539  // software has allocated the number of messages requested
540  if (ghc.MRSM == 0)
541  {
542  AdapterExtension->StateFlags.MessagePerPort = TRUE;
543  AhciDebugPrint("\tMultiple MSI based message not supported\n");
544  }
545 
547 
548  return TRUE;
549 }// -- AhciHwInitialize();
550 
560 VOID
562  __in PAHCI_PORT_EXTENSION PortExtension,
563  __in ULONG CommandsToComplete
564  )
565 {
566  ULONG NCS, i;
568  PAHCI_SRB_EXTENSION SrbExtension;
569  PAHCI_ADAPTER_EXTENSION AdapterExtension;
570 
571  AhciDebugPrint("AhciCompleteIssuedSrb()\n");
572 
573  NT_ASSERT(CommandsToComplete != 0);
574 
575  AhciDebugPrint("\tCompleted Commands: %d\n", CommandsToComplete);
576 
577  AdapterExtension = PortExtension->AdapterExtension;
578  NCS = AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP);
579 
580  for (i = 0; i < NCS; i++)
581  {
582  if (((1 << i) & CommandsToComplete) != 0)
583  {
584  Srb = PortExtension->Slot[i];
585 
586  if (Srb == NULL)
587  {
588  continue;
589  }
590 
591  SrbExtension = GetSrbExtension(Srb);
592  NT_ASSERT(SrbExtension != NULL);
593 
594  if (SrbExtension->CompletionRoutine != NULL)
595  {
596  AddQueue(&PortExtension->CompletionQueue, Srb);
597  StorPortIssueDpc(AdapterExtension, &PortExtension->CommandCompletion, PortExtension, Srb);
598  }
599  else
600  {
601  NT_ASSERT(Srb->SrbStatus == SRB_STATUS_PENDING);
602  Srb->SrbStatus = SRB_STATUS_SUCCESS;
603  StorPortNotification(RequestComplete, AdapterExtension, Srb);
604  }
605  }
606  }
607 
608  return;
609 }// -- AhciCompleteIssuedSrb();
610 
620 VOID
622  __in PAHCI_PORT_EXTENSION PortExtension
623  )
624 {
625  ULONG is, ci, sact, outstanding;
627  AHCI_INTERRUPT_STATUS PxISMasked;
628  PAHCI_ADAPTER_EXTENSION AdapterExtension;
629 
630  AhciDebugPrint("AhciInterruptHandler()\n");
631  AhciDebugPrint("\tPort Number: %d\n", PortExtension->PortNumber);
632 
633  AdapterExtension = PortExtension->AdapterExtension;
634  NT_ASSERT(IsPortValid(AdapterExtension, PortExtension->PortNumber));
635 
636  // 5.5.3
637  // 1. Software determines the cause of the interrupt by reading the PxIS register.
638  // It is possible for multiple bits to be set
639  // 2. Software clears appropriate bits in the PxIS register corresponding to the cause of the interrupt.
640  // 3. Software clears the interrupt bit in IS.IPS corresponding to the port.
641  // 4. If executing non-queued commands, software reads the PxCI register, and compares the current value to
642  // the list of commands previously issued by software that are still outstanding.
643  // If executing native queued commands, software reads the PxSACT register and compares the current
644  // value to the list of commands previously issued by software.
645  // Software completes with success any outstanding command whose corresponding bit has been cleared in
646  // the respective register. PxCI and PxSACT are volatile registers; software should only use their values
647  // to determine commands that have completed, not to determine which commands have previously been issued.
648  // 5. If there were errors, noted in the PxIS register, software performs error recovery actions (see section 6.2.2).
649  PxISMasked.Status = 0;
650  PxIS.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->IS);
651 
652  // 6.2.2
653  // Fatal Error
654  // signified by the setting of PxIS.HBFS, PxIS.HBDS, PxIS.IFS, or PxIS.TFES
655  if (PxIS.HBFS || PxIS.HBDS || PxIS.IFS || PxIS.TFES)
656  {
657  // In this state, the HBA shall not issue any new commands nor acknowledge DMA Setup FISes to process
658  // any native command queuing commands. To recover, the port must be restarted
659  // To detect an error that requires software recovery actions to be performed,
660  // software should check whether any of the following status bits are set on an interrupt:
661  // PxIS.HBFS, PxIS.HBDS, PxIS.IFS, and PxIS.TFES. If any of these bits are set,
662  // software should perform the appropriate error recovery actions based on whether
663  // non-queued commands were being issued or native command queuing commands were being issued.
664 
665  AhciDebugPrint("\tFatal Error: %x\n", PxIS.Status);
666  }
667 
668  // Normal Command Completion
669  // 3.3.5
670  // A D2H Register FIS has been received with the ‘I’ bit set, and has been copied into system memory.
671  PxISMasked.DHRS = PxIS.DHRS;
672  // A PIO Setup FIS has been received with the ‘I’ bit set, it has been copied into system memory.
673  PxISMasked.PSS = PxIS.PSS;
674  // A DMA Setup FIS has been received with the ‘I’ bit set and has been copied into system memory.
675  PxISMasked.DSS = PxIS.DSS;
676  // A Set Device Bits FIS has been received with the ‘I’ bit set and has been copied into system memory/
677  PxISMasked.SDBS = PxIS.SDBS;
678  // A PRD with the ‘I’ bit set has transferred all of its data.
679  PxISMasked.DPS = PxIS.DPS;
680 
681  if (PxISMasked.Status != 0)
682  {
683  StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->IS, PxISMasked.Status);
684  }
685 
686  // 10.7.1.1
687  // Clear port interrupt
688  // It is set by the level of the virtual interrupt line being a set, and cleared by a write of ‘1’ from the software.
689  is = (1 << PortExtension->PortNumber);
690  StorPortWriteRegisterUlong(AdapterExtension, AdapterExtension->IS, is);
691 
692  ci = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CI);
693  sact = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SACT);
694 
695  outstanding = ci | sact; // NOTE: Including both non-NCQ and NCQ based commands
696  if ((PortExtension->CommandIssuedSlots & (~outstanding)) != 0)
697  {
698  AhciCompleteIssuedSrb(PortExtension, (PortExtension->CommandIssuedSlots & (~outstanding)));
699  PortExtension->CommandIssuedSlots &= outstanding;
700  }
701 
702  return;
703 }// -- AhciInterruptHandler();
704 
717 BOOLEAN
718 NTAPI
720  __in PVOID DeviceExtension
721  )
722 {
723  PAHCI_ADAPTER_EXTENSION AdapterExtension;
724  ULONG portPending, nextPort, i, portCount;
725 
726  AdapterExtension = (PAHCI_ADAPTER_EXTENSION)DeviceExtension;
727 
728  if (AdapterExtension->StateFlags.Removed)
729  {
730  return FALSE;
731  }
732 
733  portPending = StorPortReadRegisterUlong(AdapterExtension, AdapterExtension->IS);
734 
735  // we process interrupt for implemented ports only
736  portCount = AdapterExtension->PortCount;
737  portPending = portPending & AdapterExtension->PortImplemented;
738 
739  if (portPending == 0)
740  {
741  return FALSE;
742  }
743 
744  for (i = 1; i <= portCount; i++)
745  {
746  nextPort = (AdapterExtension->LastInterruptPort + i) % portCount;
747  if ((portPending & (0x1 << nextPort)) == 0)
748  continue;
749 
750  NT_ASSERT(IsPortValid(AdapterExtension, nextPort));
751 
752  if (AdapterExtension->PortExtension[nextPort].DeviceParams.IsActive == FALSE)
753  {
754  continue;
755  }
756 
757  // we can assign this interrupt to this port
758  AdapterExtension->LastInterruptPort = nextPort;
759  AhciInterruptHandler(&AdapterExtension->PortExtension[nextPort]);
760 
761  portPending &= ~(1 << nextPort);
762 
763  // interrupt belongs to this device
764  // should always return TRUE
765  return TRUE;
766  }
767 
768  AhciDebugPrint("\tSomething went wrong");
769  return FALSE;
770 }// -- AhciHwInterrupt();
771 
785 BOOLEAN
786 NTAPI
788  __in PVOID DeviceExtension,
790  )
791 {
792  PAHCI_ADAPTER_EXTENSION AdapterExtension;
793 
794  AhciDebugPrint("AhciHwStartIo()\n");
795 
796  AdapterExtension = (PAHCI_ADAPTER_EXTENSION)DeviceExtension;
797 
798  if (!IsPortValid(AdapterExtension, Srb->PathId))
799  {
800  Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
801  StorPortNotification(RequestComplete, AdapterExtension, Srb);
802  return TRUE;
803  }
804 
805  switch(Srb->Function)
806  {
807  case SRB_FUNCTION_PNP:
808  {
809  // https://msdn.microsoft.com/windows/hardware/drivers/storage/handling-srb-function-pnp
810  // If the function member of an SRB is set to SRB_FUNCTION_PNP,
811  // the SRB is a structure of type SCSI_PNP_REQUEST_BLOCK.
812 
813  PSCSI_PNP_REQUEST_BLOCK pnpRequest;
814  pnpRequest = (PSCSI_PNP_REQUEST_BLOCK)Srb;
815  if ((pnpRequest->SrbPnPFlags & SRB_PNP_FLAGS_ADAPTER_REQUEST) != 0)
816  {
817  switch(pnpRequest->PnPAction)
818  {
819  case StorRemoveDevice:
820  case StorSurpriseRemoval:
821  {
822  Srb->SrbStatus = SRB_STATUS_SUCCESS;
823  AdapterExtension->StateFlags.Removed = 1;
824  AhciDebugPrint("\tAdapter removed\n");
825  }
826  break;
827  case StorStopDevice:
828  {
829  Srb->SrbStatus = SRB_STATUS_SUCCESS;
830  AhciDebugPrint("\tRequested to Stop the adapter\n");
831  }
832  break;
833  default:
834  Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
835  break;
836  }
837  }
838  else
839  {
840  Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
841  }
842  }
843  break;
845  {
846  // https://msdn.microsoft.com/en-us/windows/hardware/drivers/storage/handling-srb-function-execute-scsi
847  // On receipt of an SRB_FUNCTION_EXECUTE_SCSI request, a miniport driver's HwScsiStartIo
848  // routine does the following:
849  //
850  // - Gets and/or sets up whatever context the miniport driver maintains in its device,
851  // logical unit, and/or SRB extensions
852  // For example, a miniport driver might set up a logical unit extension with pointers
853  // to the SRB itself and the SRB DataBuffer pointer, the SRB DataTransferLength value,
854  // and a driver-defined value (or CDB SCSIOP_XXX value) indicating the operation to be
855  // carried out on the HBA.
856  //
857  // - Calls an internal routine to program the HBA, as partially directed by the SrbFlags,
858  // for the requested operation
859  // For a device I/O operation, such an internal routine generally selects the target device
860  // and sends the CDB over the bus to the target logical unit.
861  PCDB cdb = (PCDB)&Srb->Cdb;
862  if (Srb->CdbLength == 0)
863  {
864  AhciDebugPrint("\tOperationCode: %d\n", cdb->CDB10.OperationCode);
865  Srb->SrbStatus = SRB_STATUS_BAD_FUNCTION;
866  break;
867  }
868 
869  NT_ASSERT(cdb != NULL);
870 
871  switch(cdb->CDB10.OperationCode)
872  {
873  case SCSIOP_INQUIRY:
874  Srb->SrbStatus = DeviceInquiryRequest(AdapterExtension, Srb, cdb);
875  break;
876  case SCSIOP_REPORT_LUNS:
877  Srb->SrbStatus = DeviceReportLuns(AdapterExtension, Srb, cdb);
878  break;
880  Srb->SrbStatus = DeviceRequestCapacity(AdapterExtension, Srb, cdb);
881  break;
883  Srb->SrbStatus = DeviceRequestComplete(AdapterExtension, Srb, cdb);
884  break;
885  case SCSIOP_MODE_SENSE:
886  Srb->SrbStatus = DeviceRequestSense(AdapterExtension, Srb, cdb);
887  break;
888  case SCSIOP_READ:
889  case SCSIOP_WRITE:
890  Srb->SrbStatus = DeviceRequestReadWrite(AdapterExtension, Srb, cdb);
891  break;
892  default:
893  AhciDebugPrint("\tOperationCode: %d\n", cdb->CDB10.OperationCode);
894  Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
895  break;
896  }
897  }
898  break;
899  default:
900  AhciDebugPrint("\tUnknown function code recieved: %x\n", Srb->Function);
901  Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
902  break;
903  }
904 
905  if (Srb->SrbStatus != SRB_STATUS_PENDING)
906  {
907  StorPortNotification(RequestComplete, AdapterExtension, Srb);
908  }
909  else
910  {
911  AhciProcessIO(AdapterExtension, Srb->PathId, Srb);
912  }
913  return TRUE;
914 }// -- AhciHwStartIo();
915 
928 BOOLEAN
929 NTAPI
931  __in PVOID AdapterExtension,
933  )
934 {
935  STOR_LOCK_HANDLE lockhandle = {0};
936 // PAHCI_ADAPTER_EXTENSION adapterExtension;
937 
938  AhciDebugPrint("AhciHwResetBus()\n");
939 
940 // adapterExtension = AdapterExtension;
941 
942  if (IsPortValid(AdapterExtension, PathId))
943  {
944  // Acquire Lock
945  StorPortAcquireSpinLock(AdapterExtension, InterruptLock, NULL, &lockhandle);
946 
947  // TODO: Perform port reset
948 
949  // Release lock
950  StorPortReleaseSpinLock(AdapterExtension, &lockhandle);
951  }
952 
953  return FALSE;
954 }// -- AhciHwResetBus();
955 
988 ULONG
989 NTAPI
991  __in PVOID DeviceExtension,
993  __in PVOID BusInformation,
994  __in PCHAR ArgumentString,
997  )
998 {
999  AHCI_GHC ghc;
1000  ULONG index, pci_cfg_len;
1001  PACCESS_RANGE accessRange;
1002  UCHAR pci_cfg_buf[sizeof(PCI_COMMON_CONFIG)];
1003 
1005  PPCI_COMMON_CONFIG pciConfigData;
1006  PAHCI_ADAPTER_EXTENSION adapterExtension;
1007 
1008  AhciDebugPrint("AhciHwFindAdapter()\n");
1009 
1011  UNREFERENCED_PARAMETER(BusInformation);
1012  UNREFERENCED_PARAMETER(ArgumentString);
1014 
1015  adapterExtension = DeviceExtension;
1016  adapterExtension->SlotNumber = ConfigInfo->SlotNumber;
1017  adapterExtension->SystemIoBusNumber = ConfigInfo->SystemIoBusNumber;
1018 
1019  // get PCI configuration header
1020  pci_cfg_len = StorPortGetBusData(
1021  adapterExtension,
1023  adapterExtension->SystemIoBusNumber,
1024  adapterExtension->SlotNumber,
1025  pci_cfg_buf,
1026  sizeof(PCI_COMMON_CONFIG));
1027 
1028  if (pci_cfg_len != sizeof(PCI_COMMON_CONFIG))
1029  {
1030  AhciDebugPrint("\tpci_cfg_len != %d :: %d", sizeof(PCI_COMMON_CONFIG), pci_cfg_len);
1031  return SP_RETURN_ERROR;//Not a valid device at the given bus number
1032  }
1033 
1034  pciConfigData = (PPCI_COMMON_CONFIG)pci_cfg_buf;
1035  adapterExtension->VendorID = pciConfigData->VendorID;
1036  adapterExtension->DeviceID = pciConfigData->DeviceID;
1037  adapterExtension->RevisionID = pciConfigData->RevisionID;
1038  // The last PCI base address register (BAR[5], header offset 0x24) points to the AHCI base memory, it’s called ABAR (AHCI Base Memory Register).
1039  adapterExtension->AhciBaseAddress = pciConfigData->u.type0.BaseAddresses[5] & (0xFFFFFFF0);
1040 
1041  AhciDebugPrint("\tVendorID: %04x DeviceID: %04x RevisionID: %02x\n",
1042  adapterExtension->VendorID,
1043  adapterExtension->DeviceID,
1044  adapterExtension->RevisionID);
1045 
1046  // 2.1.11
1047  abar = NULL;
1048  if (ConfigInfo->NumberOfAccessRanges > 0)
1049  {
1050  accessRange = *(ConfigInfo->AccessRanges);
1051  for (index = 0; index < ConfigInfo->NumberOfAccessRanges; index++)
1052  {
1053  if (accessRange[index].RangeStart.QuadPart == adapterExtension->AhciBaseAddress)
1054  {
1055  abar = StorPortGetDeviceBase(adapterExtension,
1056  ConfigInfo->AdapterInterfaceType,
1057  ConfigInfo->SystemIoBusNumber,
1058  accessRange[index].RangeStart,
1059  accessRange[index].RangeLength,
1060  !accessRange[index].RangeInMemory);
1061  break;
1062  }
1063  }
1064  }
1065 
1066  if (abar == NULL)
1067  {
1068  AhciDebugPrint("\tabar == NULL\n");
1069  return SP_RETURN_ERROR; // corrupted information supplied
1070  }
1071 
1072  adapterExtension->ABAR_Address = abar;
1073  adapterExtension->CAP = StorPortReadRegisterUlong(adapterExtension, &abar->CAP);
1074  adapterExtension->CAP2 = StorPortReadRegisterUlong(adapterExtension, &abar->CAP2);
1075  adapterExtension->Version = StorPortReadRegisterUlong(adapterExtension, &abar->VS);
1076  adapterExtension->LastInterruptPort = (ULONG)-1;
1077 
1078  // 10.1.2
1079  // 1. Indicate that system software is AHCI aware by setting GHC.AE to ‘1’.
1080  // 3.1.2 -- AE bit is read-write only if CAP.SAM is '0'
1081  ghc.Status = StorPortReadRegisterUlong(adapterExtension, &abar->GHC);
1082  // AE := Highest Significant bit of GHC
1083  if (ghc.AE != 0)// Hmm, controller was already in power state
1084  {
1085  // reset controller to have it in known state
1086  AhciDebugPrint("\tAE Already set, Reset()\n");
1087  if (!AhciAdapterReset(adapterExtension))
1088  {
1089  AhciDebugPrint("\tReset Failed!\n");
1090  return SP_RETURN_ERROR;// reset failed
1091  }
1092  }
1093 
1094  ghc.Status = 0;
1095  ghc.AE = 1;// only AE=1
1096  // tell the controller that we know about AHCI
1097  StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc.Status);
1098 
1099  adapterExtension->IS = &abar->IS;
1100  adapterExtension->PortImplemented = StorPortReadRegisterUlong(adapterExtension, &abar->PI);
1101 
1102  if (adapterExtension->PortImplemented == 0)
1103  {
1104  AhciDebugPrint("\tadapterExtension->PortImplemented == 0\n");
1105  return SP_RETURN_ERROR;
1106  }
1107 
1108  ConfigInfo->Master = TRUE;
1109  ConfigInfo->AlignmentMask = 0x3;
1110  ConfigInfo->ScatterGather = TRUE;
1111  ConfigInfo->DmaWidth = Width32Bits;
1112  ConfigInfo->WmiDataProvider = FALSE;
1113  ConfigInfo->Dma32BitAddresses = TRUE;
1114 
1115  if (IsAdapterCAPS64(adapterExtension->CAP))
1116  {
1117  ConfigInfo->Dma64BitAddresses = TRUE;
1118  }
1119 
1120  ConfigInfo->MaximumNumberOfTargets = 1;
1121  ConfigInfo->ResetTargetSupported = TRUE;
1122  ConfigInfo->NumberOfPhysicalBreaks = 0x21;
1123  ConfigInfo->MaximumNumberOfLogicalUnits = 1;
1124  ConfigInfo->NumberOfBuses = MAXIMUM_AHCI_PORT_COUNT;
1125  ConfigInfo->MaximumTransferLength = MAXIMUM_TRANSFER_LENGTH;
1126  ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;
1127 
1128  // Turn IE -- Interrupt Enabled
1129  ghc.Status = StorPortReadRegisterUlong(adapterExtension, &abar->GHC);
1130  ghc.IE = 1;
1131  StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc.Status);
1132 
1133  // allocate necessary resource for each port
1134  if (!AhciAllocateResourceForAdapter(adapterExtension, ConfigInfo))
1135  {
1136  NT_ASSERT(FALSE);
1137  return SP_RETURN_ERROR;
1138  }
1139 
1140  for (index = 0; index < adapterExtension->PortCount; index++)
1141  {
1142  if ((adapterExtension->PortImplemented & (0x1 << index)) != 0)
1143  AhciPortInitialize(&adapterExtension->PortExtension[index]);
1144  }
1145 
1146  return SP_RETURN_FOUND;
1147 }// -- AhciHwFindAdapter();
1148 
1161 ULONG
1162 NTAPI
1166  )
1167 {
1168  ULONG status;
1169  // initialize the hardware data structure
1170  HW_INITIALIZATION_DATA hwInitializationData = {0};
1171 
1172  // set size of hardware initialization structure
1173  hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
1174 
1175  // identity required miniport entry point routines
1176  hwInitializationData.HwStartIo = AhciHwStartIo;
1177  hwInitializationData.HwResetBus = AhciHwResetBus;
1178  hwInitializationData.HwInterrupt = AhciHwInterrupt;
1179  hwInitializationData.HwInitialize = AhciHwInitialize;
1180  hwInitializationData.HwFindAdapter = AhciHwFindAdapter;
1181 
1182  // adapter specific information
1183  hwInitializationData.TaggedQueuing = TRUE;
1184  hwInitializationData.AutoRequestSense = TRUE;
1185  hwInitializationData.MultipleRequestPerLu = TRUE;
1186  hwInitializationData.NeedPhysicalAddresses = TRUE;
1187 
1188  hwInitializationData.NumberOfAccessRanges = 6;
1189  hwInitializationData.AdapterInterfaceType = PCIBus;
1190  hwInitializationData.MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS;
1191 
1192  // set required extension sizes
1193  hwInitializationData.SrbExtensionSize = sizeof(AHCI_SRB_EXTENSION);
1194  hwInitializationData.DeviceExtensionSize = sizeof(AHCI_ADAPTER_EXTENSION);
1195 
1196  // register our hw init data
1198  RegistryPath,
1199  &hwInitializationData,
1200  NULL);
1201 
1203  return status;
1204 }// -- DriverEntry();
1205 
1218 ULONG
1220  __in PAHCI_PORT_EXTENSION PortExtension,
1221  __in PAHCI_SRB_EXTENSION SrbExtension
1222  )
1223 {
1224  PAHCI_COMMAND_TABLE cmdTable;
1225 
1226  UNREFERENCED_PARAMETER(PortExtension);
1227 
1228  AhciDebugPrint("AhciATA_CFIS()\n");
1229 
1230  cmdTable = (PAHCI_COMMAND_TABLE)SrbExtension;
1231 
1232  AhciZeroMemory((PCHAR)cmdTable->CFIS, sizeof(cmdTable->CFIS));
1233 
1234  cmdTable->CFIS[AHCI_ATA_CFIS_FisType] = FIS_TYPE_REG_H2D; // FIS Type
1235  cmdTable->CFIS[AHCI_ATA_CFIS_PMPort_C] = (1 << 7); // PM Port & C
1236  cmdTable->CFIS[AHCI_ATA_CFIS_CommandReg] = SrbExtension->CommandReg;
1237 
1238  cmdTable->CFIS[AHCI_ATA_CFIS_FeaturesLow] = SrbExtension->FeaturesLow;
1239  cmdTable->CFIS[AHCI_ATA_CFIS_LBA0] = SrbExtension->LBA0;
1240  cmdTable->CFIS[AHCI_ATA_CFIS_LBA1] = SrbExtension->LBA1;
1241  cmdTable->CFIS[AHCI_ATA_CFIS_LBA2] = SrbExtension->LBA2;
1242  cmdTable->CFIS[AHCI_ATA_CFIS_Device] = SrbExtension->Device;
1243  cmdTable->CFIS[AHCI_ATA_CFIS_LBA3] = SrbExtension->LBA3;
1244  cmdTable->CFIS[AHCI_ATA_CFIS_LBA4] = SrbExtension->LBA4;
1245  cmdTable->CFIS[AHCI_ATA_CFIS_LBA5] = SrbExtension->LBA5;
1246  cmdTable->CFIS[AHCI_ATA_CFIS_FeaturesHigh] = SrbExtension->FeaturesHigh;
1247  cmdTable->CFIS[AHCI_ATA_CFIS_SectorCountLow] = SrbExtension->SectorCountLow;
1248  cmdTable->CFIS[AHCI_ATA_CFIS_SectorCountHigh] = SrbExtension->SectorCountHigh;
1249 
1250  return 5;
1251 }// -- AhciATA_CFIS();
1252 
1265 ULONG
1267  __in PAHCI_PORT_EXTENSION PortExtension,
1268  __in PAHCI_SRB_EXTENSION SrbExtension
1269  )
1270 {
1271  PAHCI_COMMAND_TABLE cmdTable;
1272  UNREFERENCED_PARAMETER(PortExtension);
1273 
1274  AhciDebugPrint("AhciATAPI_CFIS()\n");
1275 
1276  cmdTable = (PAHCI_COMMAND_TABLE)SrbExtension;
1277 
1278  NT_ASSERT(SrbExtension->CommandReg == IDE_COMMAND_ATAPI_PACKET);
1279 
1280  AhciZeroMemory((PCHAR)cmdTable->CFIS, sizeof(cmdTable->CFIS));
1281 
1282  cmdTable->CFIS[AHCI_ATA_CFIS_FisType] = FIS_TYPE_REG_H2D; // FIS Type
1283  cmdTable->CFIS[AHCI_ATA_CFIS_PMPort_C] = (1 << 7); // PM Port & C
1284  cmdTable->CFIS[AHCI_ATA_CFIS_CommandReg] = SrbExtension->CommandReg;
1285 
1286  cmdTable->CFIS[AHCI_ATA_CFIS_FeaturesLow] = SrbExtension->FeaturesLow;
1287  cmdTable->CFIS[AHCI_ATA_CFIS_LBA0] = SrbExtension->LBA0;
1288  cmdTable->CFIS[AHCI_ATA_CFIS_LBA1] = SrbExtension->LBA1;
1289  cmdTable->CFIS[AHCI_ATA_CFIS_LBA2] = SrbExtension->LBA2;
1290  cmdTable->CFIS[AHCI_ATA_CFIS_Device] = SrbExtension->Device;
1291  cmdTable->CFIS[AHCI_ATA_CFIS_LBA3] = SrbExtension->LBA3;
1292  cmdTable->CFIS[AHCI_ATA_CFIS_LBA4] = SrbExtension->LBA4;
1293  cmdTable->CFIS[AHCI_ATA_CFIS_LBA5] = SrbExtension->LBA5;
1294  cmdTable->CFIS[AHCI_ATA_CFIS_FeaturesHigh] = SrbExtension->FeaturesHigh;
1295  cmdTable->CFIS[AHCI_ATA_CFIS_SectorCountLow] = SrbExtension->SectorCountLow;
1296  cmdTable->CFIS[AHCI_ATA_CFIS_SectorCountHigh] = SrbExtension->SectorCountHigh;
1297 
1298  return 5;
1299 }// -- AhciATAPI_CFIS();
1300 
1313 ULONG
1315  __in PAHCI_PORT_EXTENSION PortExtension,
1316  __in PAHCI_SRB_EXTENSION SrbExtension
1317  )
1318 {
1319  ULONG index;
1320  PAHCI_COMMAND_TABLE cmdTable;
1322  PAHCI_ADAPTER_EXTENSION AdapterExtension;
1323 
1324  AhciDebugPrint("AhciBuild_PRDT()\n");
1325 
1326  sgl = SrbExtension->pSgl;
1327  cmdTable = (PAHCI_COMMAND_TABLE)SrbExtension;
1328  AdapterExtension = PortExtension->AdapterExtension;
1329 
1330  NT_ASSERT(sgl != NULL);
1332 
1333  for (index = 0; index < sgl->NumberOfElements; index++)
1334  {
1336 
1337  cmdTable->PRDT[index].DBA = sgl->List[index].PhysicalAddress.LowPart;
1338  if (IsAdapterCAPS64(AdapterExtension->CAP))
1339  {
1340  cmdTable->PRDT[index].DBAU = sgl->List[index].PhysicalAddress.HighPart;
1341  }
1342 
1343  // Data Byte Count (DBC): A ‘0’ based value that Indicates the length, in bytes, of the data block.
1344  // A maximum of length of 4MB may exist for any entry. Bit ‘0’ of this field must always be ‘1’ to
1345  // indicate an even byte count. A value of ‘1’ indicates 2 bytes, ‘3’ indicates 4 bytes, etc.
1346  cmdTable->PRDT[index].DBC = sgl->List[index].Length - 1;
1347  }
1348 
1349  return sgl->NumberOfElements;
1350 }// -- AhciBuild_PRDT();
1351 
1363 VOID
1365  __in PAHCI_PORT_EXTENSION PortExtension,
1367  __in ULONG SlotIndex
1368  )
1369 {
1370  ULONG prdtlen, sig, length, cfl;
1371  PAHCI_SRB_EXTENSION SrbExtension;
1372  PAHCI_COMMAND_HEADER CommandHeader;
1373  PAHCI_ADAPTER_EXTENSION AdapterExtension;
1374  STOR_PHYSICAL_ADDRESS CommandTablePhysicalAddress;
1375 
1376  AhciDebugPrint("AhciProcessSrb()\n");
1377 
1378  NT_ASSERT(Srb->PathId == PortExtension->PortNumber);
1379 
1380  SrbExtension = GetSrbExtension(Srb);
1381  AdapterExtension = PortExtension->AdapterExtension;
1382 
1383  NT_ASSERT(SrbExtension != NULL);
1384  NT_ASSERT(SrbExtension->AtaFunction != 0);
1385 
1386  if ((SrbExtension->AtaFunction == ATA_FUNCTION_ATA_IDENTIFY) &&
1387  (SrbExtension->CommandReg == IDE_COMMAND_NOT_VALID))
1388  {
1389  // Here we are safe to check SIG register
1390  sig = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SIG);
1391  if (sig == 0x101)
1392  {
1393  AhciDebugPrint("\tATA Device Found!\n");
1394  SrbExtension->CommandReg = IDE_COMMAND_IDENTIFY;
1395  }
1396  else
1397  {
1398  AhciDebugPrint("\tATAPI Device Found!\n");
1399  SrbExtension->CommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
1400  }
1401  }
1402 
1403  NT_ASSERT(SlotIndex < AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP));
1404  SrbExtension->SlotIndex = SlotIndex;
1405 
1406  // program the CFIS in the CommandTable
1407  CommandHeader = &PortExtension->CommandList[SlotIndex];
1408 
1409  cfl = 0;
1410  if (IsAtapiCommand(SrbExtension->AtaFunction))
1411  {
1412  cfl = AhciATAPI_CFIS(PortExtension, SrbExtension);
1413  }
1414  else if (IsAtaCommand(SrbExtension->AtaFunction))
1415  {
1416  cfl = AhciATA_CFIS(PortExtension, SrbExtension);
1417  }
1418  else
1419  {
1420  NT_ASSERT(FALSE);
1421  }
1422 
1423  prdtlen = 0;
1424  if (IsDataTransferNeeded(SrbExtension))
1425  {
1426  prdtlen = AhciBuild_PRDT(PortExtension, SrbExtension);
1427  NT_ASSERT(prdtlen != -1);
1428  }
1429 
1430  // Program the command header
1431  CommandHeader->DI.PRDTL = prdtlen; // number of entries in PRD table
1432  CommandHeader->DI.CFL = cfl;
1433  CommandHeader->DI.A = (SrbExtension->AtaFunction & ATA_FUNCTION_ATAPI_COMMAND) ? 1 : 0;
1434  CommandHeader->DI.W = (SrbExtension->Flags & ATA_FLAGS_DATA_OUT) ? 1 : 0;
1435  CommandHeader->DI.P = 0; // ATA Specifications says so
1436  CommandHeader->DI.PMP = 0; // Port Multiplier
1437 
1438  // Reset -- Manual Configuation
1439  CommandHeader->DI.R = 0;
1440  CommandHeader->DI.B = 0;
1441  CommandHeader->DI.C = 0;
1442 
1443  CommandHeader->PRDBC = 0;
1444 
1445  CommandHeader->Reserved[0] = 0;
1446  CommandHeader->Reserved[1] = 0;
1447  CommandHeader->Reserved[2] = 0;
1448  CommandHeader->Reserved[3] = 0;
1449 
1450  // set CommandHeader CTBA
1451  CommandTablePhysicalAddress = StorPortGetPhysicalAddress(AdapterExtension,
1452  NULL,
1453  SrbExtension,
1454  &length);
1455 
1456  NT_ASSERT(length != 0);
1457 
1458  // command table alignment
1459  NT_ASSERT((CommandTablePhysicalAddress.LowPart % 128) == 0);
1460 
1461  CommandHeader->CTBA = CommandTablePhysicalAddress.LowPart;
1462 
1463  if (IsAdapterCAPS64(AdapterExtension->CAP))
1464  {
1465  CommandHeader->CTBA_U = CommandTablePhysicalAddress.HighPart;
1466  }
1467 
1468  // mark this slot
1469  PortExtension->Slot[SlotIndex] = Srb;
1470  PortExtension->QueueSlots |= 1 << SlotIndex;
1471  return;
1472 }// -- AhciProcessSrb();
1473 
1484 #ifdef _MSC_VER // avoid MSVC C4700
1485  #pragma warning(push)
1486  #pragma warning(disable: 4700)
1487 #endif
1488 
1489 VOID
1491  __in PAHCI_PORT_EXTENSION PortExtension
1492  )
1493 {
1495  ULONG QueueSlots, slotToActivate, tmp;
1496  PAHCI_ADAPTER_EXTENSION AdapterExtension;
1497 
1498  AhciDebugPrint("AhciActivatePort()\n");
1499 
1500  AdapterExtension = PortExtension->AdapterExtension;
1501  QueueSlots = PortExtension->QueueSlots;
1502 
1503  if (QueueSlots == 0)
1504  {
1505  return;
1506  }
1507 
1508  // section 3.3.14
1509  // Bits in this field shall only be set to ‘1’ by software when PxCMD.ST is set to ‘1’
1510  cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
1511 
1512  if (cmd.ST == 0) // PxCMD.ST == 0
1513  {
1514  return;
1515  }
1516 
1517  // get the lowest set bit
1518  tmp = QueueSlots & (QueueSlots - 1);
1519 
1520  if (tmp == 0)
1521  slotToActivate = QueueSlots;
1522  else
1523  slotToActivate = (QueueSlots & (~tmp));
1524 
1525  // mark that bit off in QueueSlots
1526  // so we can know we it is really needed to activate port or not
1527  PortExtension->QueueSlots &= ~slotToActivate;
1528  // mark this CommandIssuedSlots
1529  // to validate in completeIssuedCommand
1530  PortExtension->CommandIssuedSlots |= slotToActivate;
1531 
1532  // tell the HBA to issue this Command Slot to the given port
1533  StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CI, slotToActivate);
1534 
1535  return;
1536 }// -- AhciActivatePort();
1537 
1538 #ifdef _MSC_VER // avoid MSVC C4700
1539  #pragma warning(pop)
1540 #endif
1541 
1554 VOID
1556  __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
1557  __in UCHAR PathId,
1559  )
1560 {
1561  PSCSI_REQUEST_BLOCK tmpSrb;
1562  STOR_LOCK_HANDLE lockhandle = {0};
1563  PAHCI_PORT_EXTENSION PortExtension;
1564  ULONG commandSlotMask, occupiedSlots, slotIndex, NCS;
1565 
1566  AhciDebugPrint("AhciProcessIO()\n");
1567  AhciDebugPrint("\tPathId: %d\n", PathId);
1568 
1569  PortExtension = &AdapterExtension->PortExtension[PathId];
1570 
1571  NT_ASSERT(PathId < AdapterExtension->PortCount);
1572 
1573  // Acquire Lock
1574  StorPortAcquireSpinLock(AdapterExtension, InterruptLock, NULL, &lockhandle);
1575 
1576  // add Srb to queue
1577  AddQueue(&PortExtension->SrbQueue, Srb);
1578 
1579  if (PortExtension->DeviceParams.IsActive == FALSE)
1580  {
1581  // Release Lock
1582  StorPortReleaseSpinLock(AdapterExtension, &lockhandle);
1583  return; // we should wait for device to get active
1584  }
1585 
1586  occupiedSlots = (PortExtension->QueueSlots | PortExtension->CommandIssuedSlots); // Busy command slots for given port
1587  NCS = AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP);
1588  commandSlotMask = (1 << NCS) - 1; // available slots mask
1589 
1590  commandSlotMask = (commandSlotMask & ~occupiedSlots);
1591  if(commandSlotMask != 0)
1592  {
1593  // iterate over HBA port slots
1594  for (slotIndex = 0; slotIndex < NCS; slotIndex++)
1595  {
1596  // find first free slot
1597  if ((commandSlotMask & (1 << slotIndex)) != 0)
1598  {
1599  tmpSrb = RemoveQueue(&PortExtension->SrbQueue);
1600  if (tmpSrb != NULL)
1601  {
1602  NT_ASSERT(tmpSrb->PathId == PathId);
1603  AhciProcessSrb(PortExtension, tmpSrb, slotIndex);
1604  }
1605  else
1606  {
1607  break;
1608  }
1609  }
1610  else
1611  {
1612  break;
1613  }
1614  }
1615  }
1616 
1617  // program HBA port
1618  AhciActivatePort(PortExtension);
1619 
1620  // Release Lock
1621  StorPortReleaseSpinLock(AdapterExtension, &lockhandle);
1622 
1623  return;
1624 }// -- AhciProcessIO();
1625 
1637 VOID
1639  __in PVOID _Extension,
1640  __in PVOID _Srb
1641  )
1642 {
1643  PAHCI_PORT_EXTENSION PortExtension;
1644  PAHCI_ADAPTER_EXTENSION AdapterExtension;
1646  BOOLEAN status;
1647 
1648  AhciDebugPrint("AtapiInquiryCompletion()\n");
1649 
1650  PortExtension = (PAHCI_PORT_EXTENSION)_Extension;
1651  Srb = (PSCSI_REQUEST_BLOCK)_Srb;
1652 
1653  NT_ASSERT(Srb != NULL);
1654  NT_ASSERT(PortExtension != NULL);
1655 
1656  AdapterExtension = PortExtension->AdapterExtension;
1657 
1658  // send queue depth
1660  Srb->PathId,
1661  Srb->TargetId,
1662  Srb->Lun,
1663  AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP));
1664 
1665  NT_ASSERT(status == TRUE);
1666  return;
1667 }// -- AtapiInquiryCompletion();
1668 
1680 VOID
1682  __in PVOID _Extension,
1683  __in PVOID _Srb
1684  )
1685 {
1686  PAHCI_PORT_EXTENSION PortExtension;
1688 
1689 // PCDB cdb;
1690  BOOLEAN status;
1691  PINQUIRYDATA InquiryData;
1692  PAHCI_SRB_EXTENSION SrbExtension;
1693  PAHCI_ADAPTER_EXTENSION AdapterExtension;
1694  PIDENTIFY_DEVICE_DATA IdentifyDeviceData;
1695 
1696  AhciDebugPrint("InquiryCompletion()\n");
1697 
1698  PortExtension = (PAHCI_PORT_EXTENSION)_Extension;
1699  Srb = (PSCSI_REQUEST_BLOCK)_Srb;
1700 
1701  NT_ASSERT(Srb != NULL);
1702  NT_ASSERT(PortExtension != NULL);
1703 
1704 // cdb = (PCDB)&Srb->Cdb;
1705  InquiryData = Srb->DataBuffer;
1706  SrbExtension = GetSrbExtension(Srb);
1707  AdapterExtension = PortExtension->AdapterExtension;
1708  IdentifyDeviceData = PortExtension->IdentifyDeviceData;
1709 
1710  if (Srb->SrbStatus != SRB_STATUS_SUCCESS)
1711  {
1712  if (Srb->SrbStatus == SRB_STATUS_NO_DEVICE)
1713  {
1714  PortExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_NODEVICE;
1715  }
1716  return;
1717  }
1718 
1719  NT_ASSERT(InquiryData != NULL);
1720  NT_ASSERT(Srb->SrbStatus == SRB_STATUS_SUCCESS);
1721 
1722  // Device specific data
1723  PortExtension->DeviceParams.MaxLba.QuadPart = 0;
1724 
1725  if (SrbExtension->CommandReg == IDE_COMMAND_IDENTIFY)
1726  {
1727  PortExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_ATA;
1728  if (IdentifyDeviceData->GeneralConfiguration.RemovableMedia)
1729  {
1730  PortExtension->DeviceParams.RemovableDevice = 1;
1731  }
1732 
1733  if ((IdentifyDeviceData->CommandSetSupport.BigLba) && (IdentifyDeviceData->CommandSetActive.BigLba))
1734  {
1735  PortExtension->DeviceParams.Lba48BitMode = 1;
1736  }
1737 
1738  PortExtension->DeviceParams.AccessType = DIRECT_ACCESS_DEVICE;
1739 
1740  /* Device max address lba */
1741  if (PortExtension->DeviceParams.Lba48BitMode)
1742  {
1743  PortExtension->DeviceParams.MaxLba.LowPart = IdentifyDeviceData->Max48BitLBA[0];
1744  PortExtension->DeviceParams.MaxLba.HighPart = IdentifyDeviceData->Max48BitLBA[1];
1745  }
1746  else
1747  {
1748  PortExtension->DeviceParams.MaxLba.LowPart = IdentifyDeviceData->UserAddressableSectors;
1749  }
1750 
1751  /* Bytes Per Logical Sector */
1752  if (IdentifyDeviceData->PhysicalLogicalSectorSize.LogicalSectorLongerThan256Words)
1753  {
1754  AhciDebugPrint("\tBytesPerLogicalSector != DEVICE_ATA_BLOCK_SIZE\n");
1755  NT_ASSERT(FALSE);
1756  }
1757 
1758  PortExtension->DeviceParams.BytesPerLogicalSector = DEVICE_ATA_BLOCK_SIZE;
1759 
1760  /* Bytes Per Physical Sector */
1761  if (IdentifyDeviceData->PhysicalLogicalSectorSize.MultipleLogicalSectorsPerPhysicalSector)
1762  {
1763  AhciDebugPrint("\tBytesPerPhysicalSector != DEVICE_ATA_BLOCK_SIZE\n");
1764  NT_ASSERT(FALSE);
1765  }
1766 
1767  PortExtension->DeviceParams.BytesPerPhysicalSector = DEVICE_ATA_BLOCK_SIZE;
1768 
1769  // last byte should be NULL
1770  StorPortCopyMemory(PortExtension->DeviceParams.VendorId, IdentifyDeviceData->ModelNumber, sizeof(PortExtension->DeviceParams.VendorId) - 1);
1771  StorPortCopyMemory(PortExtension->DeviceParams.RevisionID, IdentifyDeviceData->FirmwareRevision, sizeof(PortExtension->DeviceParams.RevisionID) - 1);
1772  StorPortCopyMemory(PortExtension->DeviceParams.SerialNumber, IdentifyDeviceData->SerialNumber, sizeof(PortExtension->DeviceParams.SerialNumber) - 1);
1773 
1774  PortExtension->DeviceParams.VendorId[sizeof(PortExtension->DeviceParams.VendorId) - 1] = '\0';
1775  PortExtension->DeviceParams.RevisionID[sizeof(PortExtension->DeviceParams.RevisionID) - 1] = '\0';
1776  PortExtension->DeviceParams.SerialNumber[sizeof(PortExtension->DeviceParams.SerialNumber) - 1] = '\0';
1777 
1778  // TODO: Add other device params
1779  AhciDebugPrint("\tATA Device\n");
1780  }
1781  else
1782  {
1783  AhciDebugPrint("\tATAPI Device\n");
1784  PortExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_ATAPI;
1785  PortExtension->DeviceParams.AccessType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1786  }
1787 
1788  // INQUIRYDATABUFFERSIZE = 36 ; Defined in storport.h
1789  if (Srb->DataTransferLength < INQUIRYDATABUFFERSIZE)
1790  {
1791  AhciDebugPrint("\tDataBufferLength < sizeof(INQUIRYDATA), Could crash the driver.\n");
1792  NT_ASSERT(FALSE);
1793  }
1794 
1795  // update data transfer length
1796  Srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
1797 
1798  // prepare data to send
1799  InquiryData->Versions = 2;
1800  InquiryData->Wide32Bit = 1;
1801  InquiryData->CommandQueue = 0; // NCQ not supported
1802  InquiryData->ResponseDataFormat = 0x2;
1803  InquiryData->DeviceTypeModifier = 0;
1804  InquiryData->DeviceTypeQualifier = DEVICE_CONNECTED;
1805  InquiryData->AdditionalLength = INQUIRYDATABUFFERSIZE - 5;
1806  InquiryData->DeviceType = PortExtension->DeviceParams.AccessType;
1807  InquiryData->RemovableMedia = PortExtension->DeviceParams.RemovableDevice;
1808 
1809  // Fill VendorID, Product Revision Level and other string fields
1810  StorPortCopyMemory(InquiryData->VendorId, PortExtension->DeviceParams.VendorId, sizeof(InquiryData->VendorId) - 1);
1811  StorPortCopyMemory(InquiryData->ProductId, PortExtension->DeviceParams.RevisionID, sizeof(PortExtension->DeviceParams.RevisionID));
1812  StorPortCopyMemory(InquiryData->ProductRevisionLevel, PortExtension->DeviceParams.SerialNumber, sizeof(InquiryData->ProductRevisionLevel) - 1);
1813 
1814  InquiryData->VendorId[sizeof(InquiryData->VendorId) - 1] = '\0';
1815  InquiryData->ProductId[sizeof(InquiryData->ProductId) - 1] = '\0';
1816  InquiryData->ProductRevisionLevel[sizeof(InquiryData->ProductRevisionLevel) - 1] = '\0';
1817 
1818  // send queue depth
1820  Srb->PathId,
1821  Srb->TargetId,
1822  Srb->Lun,
1823  AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP));
1824 
1825  NT_ASSERT(status == TRUE);
1826  return;
1827 }// -- InquiryCompletion();
1828 
1842 UCHAR
1844  __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
1846  __in PCDB Cdb
1847  )
1848 {
1849  ULONG SrbFlags, DataBufferLength;
1850  PAHCI_SRB_EXTENSION SrbExtension;
1851  PAHCI_PORT_EXTENSION PortExtension;
1852 
1853  AhciDebugPrint("AhciATAPICommand()\n");
1854 
1855  SrbFlags = Srb->SrbFlags;
1856  SrbExtension = GetSrbExtension(Srb);
1857  DataBufferLength = Srb->DataTransferLength;
1858  PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
1859 
1860  NT_ASSERT(PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI);
1861 
1862  NT_ASSERT(SrbExtension != NULL);
1863 
1864  SrbExtension->AtaFunction = ATA_FUNCTION_ATAPI_COMMAND;
1865  SrbExtension->Flags = 0;
1866 
1867  if (SrbFlags & SRB_FLAGS_DATA_IN)
1868  {
1869  SrbExtension->Flags |= ATA_FLAGS_DATA_IN;
1870  }
1871 
1872  if (SrbFlags & SRB_FLAGS_DATA_OUT)
1873  {
1874  SrbExtension->Flags |= ATA_FLAGS_DATA_OUT;
1875  }
1876 
1877  SrbExtension->FeaturesLow = 0;
1878 
1879  SrbExtension->CompletionRoutine = NULL;
1880 
1881  NT_ASSERT(Cdb != NULL);
1882  switch(Cdb->CDB10.OperationCode)
1883  {
1884  case SCSIOP_INQUIRY:
1885  SrbExtension->Flags |= ATA_FLAGS_DATA_IN;
1886  SrbExtension->CompletionRoutine = AtapiInquiryCompletion;
1887  break;
1888  case SCSIOP_READ:
1889  SrbExtension->Flags |= ATA_FLAGS_USE_DMA;
1890  SrbExtension->FeaturesLow = 0x5;
1891  break;
1892  case SCSIOP_WRITE:
1893  SrbExtension->Flags |= ATA_FLAGS_USE_DMA;
1894  SrbExtension->FeaturesLow = 0x1;
1895  break;
1896  }
1897 
1898  SrbExtension->CommandReg = IDE_COMMAND_ATAPI_PACKET;
1899 
1900  SrbExtension->LBA0 = 0;
1901  SrbExtension->LBA1 = (UCHAR)(DataBufferLength >> 0);
1902  SrbExtension->LBA2 = (UCHAR)(DataBufferLength >> 8);
1903  SrbExtension->Device = 0;
1904  SrbExtension->LBA3 = 0;
1905  SrbExtension->LBA4 = 0;
1906  SrbExtension->LBA5 = 0;
1907  SrbExtension->FeaturesHigh = 0;
1908  SrbExtension->SectorCountLow = 0;
1909  SrbExtension->SectorCountHigh = 0;
1910 
1911  if ((SrbExtension->Flags & ATA_FLAGS_DATA_IN) || (SrbExtension->Flags & ATA_FLAGS_DATA_OUT))
1912  {
1913  SrbExtension->pSgl = (PLOCAL_SCATTER_GATHER_LIST)StorPortGetScatterGatherList(AdapterExtension, Srb);
1914  }
1915 
1916  return SRB_STATUS_PENDING;
1917 }// -- AhciATAPICommand();
1918 
1932 UCHAR
1934  __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
1936  __in PCDB Cdb
1937  )
1938 {
1939  PMODE_PARAMETER_HEADER ModeHeader;
1940  PAHCI_PORT_EXTENSION PortExtension;
1941 
1942  AhciDebugPrint("DeviceRequestSense()\n");
1943 
1944  NT_ASSERT(IsPortValid(AdapterExtension, Srb->PathId));
1945  NT_ASSERT(Cdb->CDB10.OperationCode == SCSIOP_MODE_SENSE);
1946 
1947  PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
1948 
1949  if (PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI)
1950  {
1951  return AhciATAPICommand(AdapterExtension, Srb, Cdb);
1952  }
1953 
1954  ModeHeader = (PMODE_PARAMETER_HEADER)Srb->DataBuffer;
1955 
1956  NT_ASSERT(ModeHeader != NULL);
1957 
1958  AhciZeroMemory((PCHAR)ModeHeader, Srb->DataTransferLength);
1959 
1960  ModeHeader->ModeDataLength = sizeof(MODE_PARAMETER_HEADER);
1961  ModeHeader->MediumType = 0;
1962  ModeHeader->DeviceSpecificParameter = 0;
1963  ModeHeader->BlockDescriptorLength = 0;
1964 
1965  if (Cdb->MODE_SENSE.PageCode == MODE_SENSE_CURRENT_VALUES)
1966  {
1967  ModeHeader->ModeDataLength = sizeof(MODE_PARAMETER_HEADER) + sizeof(MODE_PARAMETER_BLOCK);
1968  ModeHeader->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK);
1969  }
1970 
1971  return SRB_STATUS_SUCCESS;
1972 }// -- DeviceRequestSense();
1973 
1987 UCHAR
1989  __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
1991  __in PCDB Cdb
1992  )
1993 {
1994  BOOLEAN IsReading;
1995  ULONG64 StartOffset;
1996  PAHCI_SRB_EXTENSION SrbExtension;
1997  PAHCI_PORT_EXTENSION PortExtension;
1998  ULONG DataTransferLength, BytesPerSector, SectorCount;
1999 
2000  AhciDebugPrint("DeviceRequestReadWrite()\n");
2001 
2002  NT_ASSERT(IsPortValid(AdapterExtension, Srb->PathId));
2003  NT_ASSERT((Cdb->CDB10.OperationCode == SCSIOP_READ) || (Cdb->CDB10.OperationCode == SCSIOP_WRITE));
2004 
2005  SrbExtension = GetSrbExtension(Srb);
2006  PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
2007 
2008  if (PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI)
2009  {
2010  return AhciATAPICommand(AdapterExtension, Srb, Cdb);
2011  }
2012 
2013  DataTransferLength = Srb->DataTransferLength;
2014  BytesPerSector = PortExtension->DeviceParams.BytesPerLogicalSector;
2015 
2016  NT_ASSERT(BytesPerSector > 0);
2017 
2018  //ROUND_UP(DataTransferLength, BytesPerSector);
2019 
2020  SectorCount = DataTransferLength / BytesPerSector;
2021 
2022  Srb->DataTransferLength = SectorCount * BytesPerSector;
2023 
2024  StartOffset = AhciGetLba(Cdb, Srb->CdbLength);
2025  IsReading = (Cdb->CDB10.OperationCode == SCSIOP_READ);
2026 
2027  NT_ASSERT(SectorCount > 0);
2028 
2029  SrbExtension->AtaFunction = ATA_FUNCTION_ATA_READ;
2030  SrbExtension->Flags |= ATA_FLAGS_USE_DMA;
2031  SrbExtension->CompletionRoutine = NULL;
2032 
2033  if (IsReading)
2034  {
2035  SrbExtension->Flags |= ATA_FLAGS_DATA_IN;
2036  SrbExtension->CommandReg = IDE_COMMAND_READ_DMA;
2037  }
2038  else
2039  {
2040  SrbExtension->Flags |= ATA_FLAGS_DATA_OUT;
2041  SrbExtension->CommandReg = IDE_COMMAND_WRITE_DMA;
2042  }
2043 
2044  SrbExtension->FeaturesLow = 0;
2045  SrbExtension->LBA0 = (StartOffset >> 0) & 0xFF;
2046  SrbExtension->LBA1 = (StartOffset >> 8) & 0xFF;
2047  SrbExtension->LBA2 = (StartOffset >> 16) & 0xFF;
2048 
2049  SrbExtension->Device = (0xA0 | IDE_LBA_MODE);
2050 
2051  if (PortExtension->DeviceParams.Lba48BitMode)
2052  {
2053  SrbExtension->Flags |= ATA_FLAGS_48BIT_COMMAND;
2054 
2055  if (IsReading)
2056  {
2057  SrbExtension->CommandReg = IDE_COMMAND_READ_DMA_EXT;
2058  }
2059  else
2060  {
2061  SrbExtension->CommandReg = IDE_COMMAND_WRITE_DMA_EXT;
2062  }
2063 
2064  SrbExtension->LBA3 = (StartOffset >> 24) & 0xFF;
2065  SrbExtension->LBA4 = (StartOffset >> 32) & 0xFF;
2066  SrbExtension->LBA5 = (StartOffset >> 40) & 0xFF;
2067  }
2068  else
2069  {
2070  NT_ASSERT(FALSE);
2071  }
2072 
2073  SrbExtension->FeaturesHigh = 0;
2074  SrbExtension->SectorCountLow = (SectorCount >> 0) & 0xFF;
2075  SrbExtension->SectorCountHigh = (SectorCount >> 8) & 0xFF;
2076 
2077  NT_ASSERT(SectorCount < 0x100);
2078 
2079  SrbExtension->pSgl = (PLOCAL_SCATTER_GATHER_LIST)StorPortGetScatterGatherList(AdapterExtension, Srb);
2080 
2081  return SRB_STATUS_PENDING;
2082 }// -- DeviceRequestReadWrite();
2083 
2097 UCHAR
2099  __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
2101  __in PCDB Cdb
2102  )
2103 {
2104  ULONG MaxLba, BytesPerLogicalSector;
2105  PREAD_CAPACITY_DATA ReadCapacity;
2106  PAHCI_PORT_EXTENSION PortExtension;
2107 
2108  AhciDebugPrint("DeviceRequestCapacity()\n");
2109 
2110  UNREFERENCED_PARAMETER(AdapterExtension);
2112 
2113  NT_ASSERT(Srb->DataBuffer != NULL);
2114  NT_ASSERT(IsPortValid(AdapterExtension, Srb->PathId));
2115 
2116 
2117  PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
2118 
2119  if (PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI)
2120  {
2121  return AhciATAPICommand(AdapterExtension, Srb, Cdb);
2122  }
2123 
2124  if (Cdb->CDB10.OperationCode == SCSIOP_READ_CAPACITY)
2125  {
2126  ReadCapacity = (PREAD_CAPACITY_DATA)Srb->DataBuffer;
2127 
2128  BytesPerLogicalSector = PortExtension->DeviceParams.BytesPerLogicalSector;
2129  MaxLba = (ULONG)PortExtension->DeviceParams.MaxLba.QuadPart - 1;
2130 
2131  // I trust you windows :D
2132  NT_ASSERT(Srb->DataTransferLength >= sizeof(READ_CAPACITY_DATA));
2133 
2134  // I trust you user :D
2135  NT_ASSERT(PortExtension->DeviceParams.MaxLba.QuadPart < (ULONG)-1);
2136 
2137  // Actually I don't trust anyone :p
2138  Srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
2139 
2140  REVERSE_BYTES(&ReadCapacity->BytesPerBlock, &BytesPerLogicalSector);
2141  REVERSE_BYTES(&ReadCapacity->LogicalBlockAddress, &MaxLba);
2142  }
2143  else
2144  {
2145  AhciDebugPrint("\tSCSIOP_READ_CAPACITY16 not supported\n");
2146  NT_ASSERT(FALSE);
2147  }
2148 
2149  return SRB_STATUS_SUCCESS;
2150 }// -- DeviceRequestCapacity();
2151 
2165 UCHAR
2167  __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
2169  __in PCDB Cdb
2170  )
2171 {
2172  AhciDebugPrint("DeviceRequestComplete()\n");
2173 
2174  UNREFERENCED_PARAMETER(AdapterExtension);
2176 
2177  Srb->ScsiStatus = SCSISTAT_GOOD;
2178 
2179  return SRB_STATUS_SUCCESS;
2180 }// -- DeviceRequestComplete();
2181 
2195 UCHAR
2197  __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
2199  __in PCDB Cdb
2200  )
2201 {
2202  PLUN_LIST LunList;
2203  PAHCI_PORT_EXTENSION PortExtension;
2204 
2205  AhciDebugPrint("DeviceReportLuns()\n");
2206 
2208 
2209  PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
2210 
2211  NT_ASSERT(Srb->DataTransferLength >= sizeof(LUN_LIST));
2212  NT_ASSERT(Cdb->CDB10.OperationCode == SCSIOP_REPORT_LUNS);
2213 
2214  if (PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI)
2215  {
2216  return AhciATAPICommand(AdapterExtension, Srb, Cdb);
2217  }
2218 
2219  LunList = (PLUN_LIST)Srb->DataBuffer;
2220 
2221  NT_ASSERT(LunList != NULL);
2222 
2223  AhciZeroMemory((PCHAR)LunList, sizeof(LUN_LIST));
2224 
2225  LunList->LunListLength[3] = 8;
2226 
2227  Srb->ScsiStatus = SCSISTAT_GOOD;
2228  Srb->DataTransferLength = sizeof(LUN_LIST);
2229 
2230  return SRB_STATUS_SUCCESS;
2231 }// -- DeviceReportLuns();
2232 
2249 UCHAR
2251  __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
2253  __in PCDB Cdb
2254  )
2255 {
2256  PVOID DataBuffer;
2257  PAHCI_SRB_EXTENSION SrbExtension;
2258  PAHCI_PORT_EXTENSION PortExtension;
2259  PVPD_SUPPORTED_PAGES_PAGE VpdOutputBuffer;
2260  ULONG DataBufferLength, RequiredDataBufferLength;
2261 
2262  AhciDebugPrint("DeviceInquiryRequest()\n");
2263 
2264  NT_ASSERT(Cdb->CDB10.OperationCode == SCSIOP_INQUIRY);
2265  NT_ASSERT(IsPortValid(AdapterExtension, Srb->PathId));
2266 
2267  SrbExtension = GetSrbExtension(Srb);
2268  PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
2269 
2270  if (PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI)
2271  {
2272  return AhciATAPICommand(AdapterExtension, Srb, Cdb);
2273  }
2274 
2275  if (Srb->Lun != 0)
2276  {
2278  }
2279  else if (Cdb->CDB6INQUIRY3.EnableVitalProductData == 0)
2280  {
2281  // 3.6.1
2282  // If the EVPD bit is set to zero, the device server shall return the standard INQUIRY data
2283  AhciDebugPrint("\tEVPD Inquired\n");
2284  NT_ASSERT(SrbExtension != NULL);
2285 
2286  SrbExtension->AtaFunction = ATA_FUNCTION_ATA_IDENTIFY;
2287  SrbExtension->Flags |= ATA_FLAGS_DATA_IN;
2288  SrbExtension->CompletionRoutine = InquiryCompletion;
2289  SrbExtension->CommandReg = IDE_COMMAND_NOT_VALID;
2290 
2291  // TODO: Should use AhciZeroMemory
2292  SrbExtension->FeaturesLow = 0;
2293  SrbExtension->LBA0 = 0;
2294  SrbExtension->LBA1 = 0;
2295  SrbExtension->LBA2 = 0;
2296  SrbExtension->Device = 0xA0;
2297  SrbExtension->LBA3 = 0;
2298  SrbExtension->LBA4 = 0;
2299  SrbExtension->LBA5 = 0;
2300  SrbExtension->FeaturesHigh = 0;
2301  SrbExtension->SectorCountLow = 0;
2302  SrbExtension->SectorCountHigh = 0;
2303 
2304  SrbExtension->Sgl.NumberOfElements = 1;
2305  SrbExtension->Sgl.List[0].PhysicalAddress.LowPart = PortExtension->IdentifyDeviceDataPhysicalAddress.LowPart;
2306  SrbExtension->Sgl.List[0].PhysicalAddress.HighPart = PortExtension->IdentifyDeviceDataPhysicalAddress.HighPart;
2307  SrbExtension->Sgl.List[0].Length = sizeof(IDENTIFY_DEVICE_DATA);
2308 
2309  SrbExtension->pSgl = &SrbExtension->Sgl;
2310  return SRB_STATUS_PENDING;
2311  }
2312  else
2313  {
2314  AhciDebugPrint("\tVPD Inquired\n");
2315 
2316  DataBuffer = Srb->DataBuffer;
2317  DataBufferLength = Srb->DataTransferLength;
2318  RequiredDataBufferLength = DataBufferLength; // make the compiler happy :p
2319 
2320  if (DataBuffer == NULL)
2321  {
2323  }
2324 
2325  AhciZeroMemory(DataBuffer, DataBufferLength);
2326 
2327  switch(Cdb->CDB6INQUIRY3.PageCode)
2328  {
2329  case VPD_SUPPORTED_PAGES:
2330  {
2331  AhciDebugPrint("\tVPD_SUPPORTED_PAGES\n");
2332  RequiredDataBufferLength = sizeof(VPD_SUPPORTED_PAGES_PAGE) + 1;
2333 
2334  if (DataBufferLength < RequiredDataBufferLength)
2335  {
2336  AhciDebugPrint("\tDataBufferLength: %d Required: %d\n", DataBufferLength, RequiredDataBufferLength);
2338  }
2339 
2340  VpdOutputBuffer = (PVPD_SUPPORTED_PAGES_PAGE)DataBuffer;
2341 
2342  VpdOutputBuffer->DeviceType = PortExtension->DeviceParams.AccessType;
2343  VpdOutputBuffer->DeviceTypeQualifier = 0;
2344  VpdOutputBuffer->PageCode = VPD_SUPPORTED_PAGES;
2345  VpdOutputBuffer->PageLength = 1;
2346  VpdOutputBuffer->SupportedPageList[0] = VPD_SUPPORTED_PAGES;
2347  //VpdOutputBuffer->SupportedPageList[1] = VPD_SERIAL_NUMBER;
2348  //VpdOutputBuffer->SupportedPageList[2] = VPD_DEVICE_IDENTIFIERS;
2349 
2350  NT_ASSERT(VpdOutputBuffer->DeviceType == DIRECT_ACCESS_DEVICE);
2351  }
2352  break;
2353  case VPD_SERIAL_NUMBER:
2354  {
2355  AhciDebugPrint("\tVPD_SERIAL_NUMBER\n");
2356  }
2357  break;
2359  {
2360  AhciDebugPrint("\tVPD_DEVICE_IDENTIFIERS\n");
2361  }
2362  break;
2363  default:
2364  AhciDebugPrint("\tPageCode: %x\n", Cdb->CDB6INQUIRY3.PageCode);
2366  }
2367 
2368  Srb->DataTransferLength = RequiredDataBufferLength;
2369  return SRB_STATUS_SUCCESS;
2370  }
2371 }// -- DeviceInquiryRequest();
2372 
2392 BOOLEAN
2394  __in PAHCI_ADAPTER_EXTENSION AdapterExtension
2395  )
2396 {
2397  ULONG ticks;
2398  AHCI_GHC ghc;
2400 
2401  AhciDebugPrint("AhciAdapterReset()\n");
2402 
2403  abar = AdapterExtension->ABAR_Address;
2404  if (abar == NULL) // basic sanity
2405  {
2406  return FALSE;
2407  }
2408 
2409  // HR -- Very first bit (lowest significant)
2410  ghc.HR = 1;
2411  StorPortWriteRegisterUlong(AdapterExtension, &abar->GHC, ghc.Status);
2412 
2413  for (ticks = 0; ticks < 50; ++ticks)
2414  {
2415  ghc.Status = StorPortReadRegisterUlong(AdapterExtension, &abar->GHC);
2416  if (ghc.HR == 0)
2417  {
2418  break;
2419  }
2420  StorPortStallExecution(20000);
2421  }
2422 
2423  if (ticks == 50)// 1 second
2424  {
2425  AhciDebugPrint("\tDevice Timeout\n");
2426  return FALSE;
2427  }
2428 
2429  return TRUE;
2430 }// -- AhciAdapterReset();
2431 
2441 __inline
2442 VOID
2444  __out PCHAR Buffer,
2446  )
2447 {
2448  ULONG i;
2449  for (i = 0; i < BufferSize; i++)
2450  {
2451  Buffer[i] = 0;
2452  }
2453 
2454  return;
2455 }// -- AhciZeroMemory();
2456 
2469 __inline
2470 BOOLEAN
2472  __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
2473  __in ULONG pathId
2474  )
2475 {
2477 
2478  if (pathId >= AdapterExtension->PortCount)
2479  {
2480  return FALSE;
2481  }
2482 
2483  return AdapterExtension->PortExtension[pathId].DeviceParams.IsActive;
2484 }// -- IsPortValid()
2485 
2499 __inline
2500 BOOLEAN
2502  __inout PAHCI_QUEUE Queue,
2503  __in PVOID Srb
2504  )
2505 {
2506  NT_ASSERT(Queue->Head < MAXIMUM_QUEUE_BUFFER_SIZE);
2507  NT_ASSERT(Queue->Tail < MAXIMUM_QUEUE_BUFFER_SIZE);
2508 
2509  if (Queue->Tail == ((Queue->Head + 1) % MAXIMUM_QUEUE_BUFFER_SIZE))
2510  return FALSE;
2511 
2512  Queue->Buffer[Queue->Head++] = Srb;
2513  Queue->Head %= MAXIMUM_QUEUE_BUFFER_SIZE;
2514 
2515  return TRUE;
2516 }// -- AddQueue();
2517 
2530 __inline
2531 PVOID
2533  __inout PAHCI_QUEUE Queue
2534  )
2535 {
2536  PVOID Srb;
2537 
2538  NT_ASSERT(Queue->Head < MAXIMUM_QUEUE_BUFFER_SIZE);
2539  NT_ASSERT(Queue->Tail < MAXIMUM_QUEUE_BUFFER_SIZE);
2540 
2541  if (Queue->Head == Queue->Tail)
2542  return NULL;
2543 
2544  Srb = Queue->Buffer[Queue->Tail++];
2545  Queue->Tail %= MAXIMUM_QUEUE_BUFFER_SIZE;
2546 
2547  return Srb;
2548 }// -- RemoveQueue();
2549 
2562 __inline
2566  )
2567 {
2568  ULONG Offset;
2569  ULONG_PTR SrbExtension;
2570 
2571  SrbExtension = (ULONG_PTR)Srb->SrbExtension;
2572  Offset = SrbExtension % 128;
2573 
2574  // CommandTable should be 128 byte aligned
2575  if (Offset != 0)
2576  Offset = 128 - Offset;
2577 
2578  return (PAHCI_SRB_EXTENSION)(SrbExtension + Offset);
2579 }// -- PAHCI_SRB_EXTENSION();
2580 
2593 __inline
2594 ULONG64
2596  __in PCDB Cdb,
2597  __in ULONG CdbLength
2598  )
2599 {
2600  ULONG64 lba = 0;
2601 
2602  NT_ASSERT(Cdb != NULL);
2603  NT_ASSERT(CdbLength != 0);
2604 
2605  if (CdbLength == 0x10)
2606  {
2607  REVERSE_BYTES_QUAD(&lba, Cdb->CDB16.LogicalBlock);
2608  }
2609  else
2610  {
2611  lba |= Cdb->CDB10.LogicalBlockByte3 << 0;
2612  lba |= Cdb->CDB10.LogicalBlockByte2 << 8;
2613  lba |= Cdb->CDB10.LogicalBlockByte1 << 16;
2614  lba |= Cdb->CDB10.LogicalBlockByte0 << 24;
2615  }
2616 
2617  return lba;
2618 }// -- AhciGetLba();
signed char * PCHAR
Definition: retypes.h:7
UCHAR CFIS[64]
Definition: storahci.h:360
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:338
VOID AhciProcessSrb(__in PAHCI_PORT_EXTENSION PortExtension, __in PSCSI_REQUEST_BLOCK Srb, __in ULONG SlotIndex)
Definition: storahci.c:1364
ULONG IS
Definition: storahci.h:397
struct _VPD_SUPPORTED_PAGES_PAGE * PVPD_SUPPORTED_PAGES_PAGE
struct _VPD_SUPPORTED_PAGES_PAGE VPD_SUPPORTED_PAGES_PAGE
AHCI_PORT_EXTENSION PortExtension[MAXIMUM_AHCI_PORT_COUNT]
Definition: storahci.h:528
#define TRUE
Definition: types.h:120
VOID AhciCommandCompletionDpcRoutine(__in PSTOR_DPC Dpc, __in PVOID HwDeviceExtension, __in PVOID SystemArgument1, __in PVOID SystemArgument2)
Definition: storahci.c:421
__inline BOOLEAN IsPortValid(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in ULONG pathId)
Definition: storahci.c:2471
#define IDE_COMMAND_READ_DMA_EXT
Definition: ata.h:262
UCHAR ProductRevisionLevel[4]
Definition: cdrw_hw.h:1134
PLOCAL_SCATTER_GATHER_LIST pSgl
Definition: storahci.h:560
ULONG AhciATAPI_CFIS(__in PAHCI_PORT_EXTENSION PortExtension, __in PAHCI_SRB_EXTENSION SrbExtension)
Definition: storahci.c:1266
STOR_PNP_ACTION PnPAction
Definition: srb.h:411
struct _MODE_PARAMETER_HEADER MODE_PARAMETER_HEADER
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
ULONG NTAPI AhciHwFindAdapter(__in PVOID DeviceExtension, __in PVOID HwContext, __in PVOID BusInformation, __in PCHAR ArgumentString, __inout PPORT_CONFIGURATION_INFORMATION ConfigInfo, __in PBOOLEAN Reserved3)
Definition: storahci.c:990
#define AHCI_ATA_CFIS_LBA2
Definition: storahci.h:52
#define AHCI_ATA_CFIS_FisType
Definition: storahci.h:46
STORPORT_API STOR_PHYSICAL_ADDRESS NTAPI StorPortGetPhysicalAddress(_In_ PVOID HwDeviceExtension, _In_opt_ PSCSI_REQUEST_BLOCK Srb, _In_ PVOID VirtualAddress, _Out_ ULONG *Length)
Definition: storport.c:788
STORPORT_API VOID NTAPI StorPortStallExecution(_In_ ULONG Delay)
Definition: storport.c:1402
ULONG Max48BitLBA[2]
Definition: ata.h:168
#define VPD_SUPPORTED_PAGES
Definition: scsi.h:495
ULONG HR
Definition: storahci.h:254
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
BOOLEAN AhciStartPort(__in PAHCI_PORT_EXTENSION PortExtension)
Definition: storahci.c:228
#define AHCI_ATA_CFIS_CommandReg
Definition: storahci.h:48
_In_ ULONG _In_ BOOLEAN _In_ ULONG _In_ UCHAR PathId
Definition: classpnp.h:1117
Definition: ftp_var.h:139
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
UCHAR ResponseDataFormat
Definition: cdrw_hw.h:1121
BOOLEAN NTAPI AhciHwStartIo(__in PVOID DeviceExtension, __in PSCSI_REQUEST_BLOCK Srb)
Definition: storahci.c:787
struct _AHCI_TASK_FILE_DATA::@1270::_STS STS
struct _AHCI_COMMAND_HEADER * PAHCI_COMMAND_HEADER
BOOLEAN AhciHwPassiveInitialize(__in PVOID DeviceExtension)
Definition: storahci.c:483
#define IDE_LBA_MODE
Definition: ata.h:255
#define MAXIMUM_TRANSFER_LENGTH
Definition: storahci.h:25
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
ULONG CommandIssuedSlots
Definition: storahci.h:466
struct _MODE_PARAMETER_BLOCK MODE_PARAMETER_BLOCK
UCHAR FirmwareRevision[8]
Definition: ata.h:25
Definition: cdrw_hw.h:28
ULONG HwInitializationDataSize
Definition: srb.h:542
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
struct _PCI_COMMON_CONFIG * PPCI_COMMON_CONFIG
_Must_inspect_result_ _In_ PVOID _In_ struct _HW_INITIALIZATION_DATA _In_ PVOID HwContext
Definition: srb.h:664
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:2707
struct _HW_INITIALIZATION_DATA HW_INITIALIZATION_DATA
struct _AHCI_ADAPTER_EXTENSION::@1275 StateFlags
struct _IDENTIFY_DEVICE_DATA * PIDENTIFY_DEVICE_DATA
#define ATA_FLAGS_DATA_IN
Definition: uata_ctl.h:222
__inline PAHCI_SRB_EXTENSION GetSrbExtension(__in PSCSI_REQUEST_BLOCK Srb)
Definition: storahci.c:2564
ULONG DeviceExtensionSize
Definition: srb.h:566
FORCEINLINE VOID StorPortAcquireSpinLock(_In_ PVOID DeviceExtension, _In_ STOR_SPINLOCK SpinLock, _In_ PVOID LockContext, _Inout_ PSTOR_LOCK_HANDLE LockHandle)
Definition: storport.h:2867
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:340
STOR_PHYSICAL_ADDRESS PhysicalAddress
Definition: storport.h:2010
ULONG LogicalBlockAddress
Definition: cdrw_hw.h:1471
#define IDE_COMMAND_IDENTIFY
Definition: atapi.h:118
BOOLEAN MultipleRequestPerLu
Definition: srb.h:576
#define ATA_FUNCTION_ATA_READ
Definition: storahci.h:64
char * cmd
Definition: vfdcmd.c:85
PHW_FIND_ADAPTER HwFindAdapter
Definition: srb.h:562
UCHAR CommandQueue
Definition: cdrw_hw.h:1125
UCHAR ProductId[16]
Definition: cdrw_hw.h:1133
struct _CDB::_CDB10 CDB10
UCHAR VendorId[8]
Definition: cdrw_hw.h:1132
ULONG NTAPI DriverEntry(__in PVOID DriverObject, __in PVOID RegistryPath)
Definition: storahci.c:1163
PHW_RESET_BUS HwResetBus
Definition: srb.h:563
#define AHCI_ATA_CFIS_LBA5
Definition: storahci.h:56
ULONG DBAU
Definition: storahci.h:347
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
#define AHCI_DEVICE_TYPE_ATAPI
Definition: storahci.h:31
#define MAXIMUM_AHCI_PORT_COUNT
Definition: storahci.h:21
#define ATA_FLAGS_USE_DMA
Definition: uata_ctl.h:226
struct _AHCI_ADAPTER_EXTENSION AHCI_ADAPTER_EXTENSION
__inline PVOID RemoveQueue(__inout PAHCI_QUEUE Queue)
Definition: storahci.c:2532
#define lba
FORCEINLINE VOID StorPortInitializeDpc(_In_ PVOID DeviceExtension, _Out_ PSTOR_DPC Dpc, _In_ PHW_DPC_ROUTINE HwDpcRoutine)
Definition: storport.h:2835
struct _IDENTIFY_DEVICE_DATA::@1808 GeneralConfiguration
__inline BOOLEAN AddQueue(__inout PAHCI_QUEUE Queue, __in PVOID Srb)
Definition: storahci.c:2501
ULONG CLB
Definition: storahci.h:393
PAHCI_PORT Port
Definition: storahci.h:485
BOOLEAN AutoRequestSense
Definition: srb.h:575
BOOLEAN TaggedQueuing
Definition: srb.h:574
uint32_t ULONG_PTR
Definition: typedefs.h:63
VOID AhciProcessIO(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in UCHAR PathId, __in PSCSI_REQUEST_BLOCK Srb)
Definition: storahci.c:1555
BOOLEAN AhciAllocateResourceForAdapter(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PPORT_CONFIGURATION_INFORMATION ConfigInfo)
Definition: storahci.c:145
#define VPD_DEVICE_IDENTIFIERS
Definition: scsi.h:497
STOR_PHYSICAL_ADDRESS IdentifyDeviceDataPhysicalAddress
Definition: storahci.h:493
STORPORT_API BOOLEAN NTAPI StorPortSetDeviceQueueDepth(_In_ PVOID HwDeviceExtension, _In_ UCHAR PathId, _In_ UCHAR TargetId, _In_ UCHAR Lun, _In_ ULONG Depth)
Definition: storport.c:1383
BOOLEAN AhciAdapterReset(__in PAHCI_ADAPTER_EXTENSION AdapterExtension)
Definition: storahci.c:2393
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct _SCSI_PNP_REQUEST_BLOCK * PSCSI_PNP_REQUEST_BLOCK
BOOLEAN NeedPhysicalAddresses
Definition: srb.h:573
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
struct _AHCI_PORT_EXTENSION * PAHCI_PORT_EXTENSION
ULONG AE
Definition: storahci.h:258
#define ATA_FUNCTION_ATA_IDENTIFY
Definition: storahci.h:63
PHW_INTERRUPT HwInterrupt
Definition: srb.h:561
#define SCSIOP_READ
Definition: cdrw_hw.h:905
struct outstanding_list outstanding
Definition: adh-query.c:36
ULONG SERR
Definition: storahci.h:405
#define __out
Definition: dbghelp.h:62
struct _AHCI_ADAPTER_EXTENSION * PAHCI_ADAPTER_EXTENSION
UCHAR AhciATAPICommand(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:1843
UCHAR RemovableMedia
Definition: cdrw_hw.h:1119
#define AHCI_ATA_CFIS_FeaturesHigh
Definition: storahci.h:57
PAHCI_COMPLETION_ROUTINE CompletionRoutine
Definition: storahci.h:561
struct _IDENTIFY_DEVICE_DATA::@1811 CommandSetActive
ULONG CLBU
Definition: storahci.h:394
#define SRB_STATUS_PENDING
Definition: srb.h:332
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
unsigned char BOOLEAN
#define AHCI_Global_Port_CAP_NCS(x)
Definition: storahci.h:81
PHW_STARTIO HwStartIo
Definition: srb.h:560
struct _AHCI_SRB_EXTENSION AHCI_SRB_EXTENSION
smooth NULL
Definition: ftsmooth.c:416
#define INQUIRYDATABUFFERSIZE
Definition: cdrw_hw.h:1113
ULONG MRSM
Definition: storahci.h:256
union _CDB * PCDB
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
#define STOR_MAP_NON_READ_WRITE_BUFFERS
Definition: storport.h:395
UCHAR SupportedPageList[0]
Definition: scsi.h:2143
#define AHCI_ATA_CFIS_SectorCountLow
Definition: storahci.h:58
Definition: bufpool.h:45
struct _MODE_PARAMETER_HEADER * PMODE_PARAMETER_HEADER
UCHAR DeviceTypeQualifier
Definition: cdrw_hw.h:1117
GLuint index
Definition: glext.h:6031
#define IDE_COMMAND_ATAPI_IDENTIFY
Definition: atapi.h:110
UCHAR ModelNumber[40]
Definition: ata.h:26
#define IsAdapterCAPS64(CAP)
Definition: storahci.h:78
#define PCHAR
Definition: match.c:90
FORCEINLINE BOOLEAN StorPortEnablePassiveInitialization(_In_ PVOID DeviceExtension, _In_ PHW_PASSIVE_INITIALIZE_ROUTINE HwPassiveInitializeRoutine)
Definition: storport.h:2820
#define SCSIOP_INQUIRY
Definition: cdrw_hw.h:888
VOID AhciCompleteIssuedSrb(__in PAHCI_PORT_EXTENSION PortExtension, __in ULONG CommandsToComplete)
Definition: storahci.c:561
UCHAR DeviceRequestSense(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:1933
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
AHCI_QUEUE CompletionQueue
Definition: storahci.h:487
#define DIRECT_ACCESS_DEVICE
Definition: cdrw_hw.h:1144
UCHAR DeviceRequestCapacity(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:2098
#define SRB_STATUS_BAD_FUNCTION
Definition: srb.h:356
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
#define IDE_COMMAND_WRITE_DMA_EXT
Definition: ata.h:267
ULONG AhciATA_CFIS(__in PAHCI_PORT_EXTENSION PortExtension, __in PAHCI_SRB_EXTENSION SrbExtension)
Definition: storahci.c:1219
struct _IDENTIFY_DEVICE_DATA IDENTIFY_DEVICE_DATA
#define IDE_COMMAND_NOT_VALID
Definition: ata.h:299
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define AHCI_ATA_CFIS_LBA4
Definition: storahci.h:55
ULONG Status
Definition: storahci.h:261
struct _AHCI_PORT_EXTENSION::@1274 DeviceParams
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define FIS_TYPE_REG_H2D
Definition: storahci.h:38
UCHAR DeviceReportLuns(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:2196
#define BufferSize
Definition: classpnp.h:419
#define SCSIOP_REPORT_LUNS
Definition: scsi.h:921
STOR_DEVICE_POWER_STATE DevicePowerState
Definition: storahci.h:491
PIDENTIFY_DEVICE_DATA IdentifyDeviceData
Definition: storahci.h:492
#define AHCI_ATA_CFIS_FeaturesLow
Definition: storahci.h:49
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_opt_ GUID _In_ USHORT DataBufferLength
Definition: fltkernel.h:1270
UCHAR Versions
Definition: cdrw_hw.h:1120
VOID AhciInterruptHandler(__in PAHCI_PORT_EXTENSION PortExtension)
Definition: storahci.c:621
AHCI_COMMAND_HEADER_DESCRIPTION DI
Definition: storahci.h:369
#define SP_RETURN_FOUND
Definition: srb.h:514
#define DEVICE_CONNECTED
Definition: cdrw_hw.h:1159
SCSI_PHYSICAL_ADDRESS RangeStart
Definition: srb.h:41
STOR_SCATTER_GATHER_ELEMENT List[MAXIMUM_AHCI_PRDT_ENTRIES]
Definition: storahci.h:535
struct _READ_CAPACITY_DATA READ_CAPACITY_DATA
unsigned __int64 ULONG64
Definition: imports.h:198
unsigned char UCHAR
Definition: xmlstorage.h:181
BOOLEAN RangeInMemory
Definition: srb.h:43
char * PBOOLEAN
Definition: retypes.h:11
#define ATA_FLAGS_48BIT_COMMAND
Definition: uata_ctl.h:223
#define index(s, c)
Definition: various.h:29
STORPORT_API PSTOR_SCATTER_GATHER_LIST NTAPI StorPortGetScatterGatherList(_In_ PVOID DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: storport.c:843
#define StorPortCopyMemory(Destination, Source, Length)
Definition: storport.h:2318
ULONG FBU
Definition: storahci.h:396
PAHCI_RECEIVED_FIS ReceivedFIS
Definition: storahci.h:489
VOID InquiryCompletion(__in PVOID _Extension, __in PVOID _Srb)
Definition: storahci.c:1681
struct _PCI_COMMON_CONFIG PCI_COMMON_CONFIG
ULONG DBA
Definition: storahci.h:346
PAHCI_MEMORY_REGISTERS ABAR_Address
Definition: storahci.h:527
ULONG LowPart
Definition: typedefs.h:104
VOID(* PAHCI_COMPLETION_ROUTINE)(__in PVOID PortExtension, __in PVOID Srb)
Definition: storahci.h:89
struct _READ_CAPACITY_DATA * PREAD_CAPACITY_DATA
__inline VOID AhciZeroMemory(__out PCHAR Buffer, __in ULONG BufferSize)
Definition: storahci.c:2443
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:342
#define __inout
Definition: dbghelp.h:50
#define ATA_FUNCTION_ATAPI_COMMAND
Definition: storahci.h:67
STORPORT_API ULONG NTAPI StorPortGetBusData(_In_ PVOID DeviceExtension, _In_ ULONG BusDataType, _In_ ULONG SystemIoBusNumber, _In_ ULONG SlotNumber, _Out_ _When_(Length !=0, _Out_writes_bytes_(Length)) PVOID Buffer, _In_ ULONG Length)
Definition: storport.c:654
STORPORT_API ULONG NTAPI StorPortReadRegisterUlong(_In_ PVOID HwDeviceExtension, _In_ PULONG Register)
Definition: stubs.c:143
ULONG SectorCount
Definition: part_xbox.c:32
UCHAR AdditionalLength
Definition: cdrw_hw.h:1122
UCHAR DeviceTypeModifier
Definition: cdrw_hw.h:1118
ULONG NumberOfAccessRanges
Definition: srb.h:569
struct _LUN_LIST * PLUN_LIST
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
UCHAR DeviceType
Definition: cdrw_hw.h:1116
VOID AhciActivatePort(__in PAHCI_PORT_EXTENSION PortExtension)
Definition: storahci.c:1490
ULONG FB
Definition: storahci.h:395
__inline ULONG64 AhciGetLba(__in PCDB Cdb, __in ULONG CdbLength)
Definition: storahci.c:2595
ULONG DBC
Definition: storahci.h:350
#define AHCI_ATA_CFIS_Device
Definition: storahci.h:53
struct _IDENTIFY_DEVICE_DATA::@1812 PhysicalLogicalSectorSize
BOOLEAN NTAPI AhciHwInitialize(__in PVOID DeviceExtension)
Definition: storahci.c:521
BOOLEAN NTAPI AhciHwInterrupt(__in PVOID DeviceExtension)
Definition: storahci.c:719
#define SRB_FUNCTION_PNP
Definition: srb.h:94
UCHAR PathId
Definition: srb.h:245
struct _AHCI_COMMAND_TABLE * PAHCI_COMMAND_TABLE
UCHAR DeviceInquiryRequest(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:2250
STORPORT_API VOID NTAPI StorPortWriteRegisterUlong(_In_ PVOID HwDeviceExtension, _In_ PULONG Register, _In_ ULONG Value)
Definition: stubs.c:291
ULONG AhciBuild_PRDT(__in PAHCI_PORT_EXTENSION PortExtension, __in PAHCI_SRB_EXTENSION SrbExtension)
Definition: storahci.c:1314
AHCI_PRDT PRDT[MAXIMUM_AHCI_PRDT_ENTRIES]
Definition: storahci.h:363
ULONG RangeLength
Definition: srb.h:42
ULONG IE
Definition: storahci.h:255
struct _AHCI_COMMAND_HEADER AHCI_COMMAND_HEADER
ULONG SrbExtensionSize
Definition: srb.h:568
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:393
#define AHCI_ATA_CFIS_LBA3
Definition: storahci.h:54
PHW_INITIALIZE HwInitialize
Definition: srb.h:559
UCHAR DeviceRequestReadWrite(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:1988
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
AHCI_QUEUE SrbQueue
Definition: storahci.h:486
#define AHCI_ATA_CFIS_PMPort_C
Definition: storahci.h:47
#define SRB_PNP_FLAGS_ADAPTER_REQUEST
Definition: srb.h:168
STORPORT_API ULONG NTAPI StorPortInitialize(_In_ PVOID Argument1, _In_ PVOID Argument2, _In_ struct _HW_INITIALIZATION_DATA *HwInitializationData, _In_opt_ PVOID HwContext)
Definition: storport.c:946
STORPORT_API PVOID NTAPI StorPortGetDeviceBase(_In_ PVOID HwDeviceExtension, _In_ INTERFACE_TYPE BusType, _In_ ULONG SystemIoBusNumber, _In_ STOR_PHYSICAL_ADDRESS IoAddress, _In_ ULONG NumberOfBytes, _In_ BOOLEAN InIoSpace)
Definition: storport.c:698
#define READ_ONLY_DIRECT_ACCESS_DEVICE
Definition: cdrw_hw.h:1149
ULONG CMD
Definition: storahci.h:399
struct _IDENTIFY_DEVICE_DATA::@1810 CommandSetSupport
BOOLEAN NTAPI AhciPortInitialize(__in PVOID DeviceExtension)
Definition: storahci.c:23
ULONG UserAddressableSectors
Definition: ata.h:51
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
INTERFACE_TYPE AdapterInterfaceType
Definition: srb.h:557
struct _LUN_LIST LUN_LIST
#define IsAtaCommand(AtaFunction)
Definition: storahci.h:75
#define AHCI_ATA_CFIS_LBA1
Definition: storahci.h:51
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: fsrtlfuncs.h:673
unsigned int ULONG
Definition: retypes.h:1
#define VPD_SERIAL_NUMBER
Definition: scsi.h:496
#define AhciDebugPrint(format,...)
Definition: storahci.h:85
#define IDE_COMMAND_READ_DMA
Definition: atapi.h:114
#define ULONG_PTR
Definition: config.h:101
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
_In_ PUNICODE_STRING RegistryPath
Definition: wmip.h:27
#define SCSISTAT_GOOD
Definition: cdrw_hw.h:1078
#define IDE_COMMAND_ATAPI_PACKET
Definition: atapi.h:109
BOOLEAN MapBuffers
Definition: srb.h:572
struct _AHCI_RECEIVED_FIS * PAHCI_RECEIVED_FIS
#define AHCI_DEVICE_TYPE_NODEVICE
Definition: storahci.h:32
BOOLEAN NTAPI AhciHwResetBus(__in PVOID AdapterExtension, __in ULONG PathId)
Definition: storahci.c:930
struct _AHCI_ADAPTER_EXTENSION * AdapterExtension
Definition: storahci.h:494
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
#define SP_RETURN_ERROR
Definition: srb.h:515
return STATUS_SUCCESS
Definition: btrfs.c:2745
UCHAR SerialNumber[20]
Definition: ata.h:22
STORPORT_API VOID StorPortNotification(_In_ SCSI_NOTIFICATION_TYPE NotificationType, _In_ PVOID HwDeviceExtension,...)
Definition: storport.c:1090
#define __in
Definition: dbghelp.h:35
#define IsAtapiCommand(AtaFunction)
Definition: storahci.h:76
static SERVICE_STATUS status
Definition: service.c:31
UCHAR DeviceRequestComplete(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:2166
UCHAR Wide32Bit
Definition: cdrw_hw.h:1130
#define MODE_SENSE_CURRENT_VALUES
Definition: cdrw_hw.h:859
#define AHCI_ATA_CFIS_SectorCountHigh
Definition: storahci.h:59
AHCI_PORT PortList[MAXIMUM_AHCI_PORT_COUNT]
Definition: storahci.h:458
#define IDE_COMMAND_WRITE_DMA
Definition: atapi.h:115
PAHCI_COMMAND_HEADER CommandList
Definition: storahci.h:490
STOR_DPC CommandCompletion
Definition: storahci.h:484
#define ATA_FLAGS_DATA_OUT
Definition: uata_ctl.h:221
#define IsDataTransferNeeded(SrbExtension)
Definition: storahci.h:77
VOID AtapiInquiryCompletion(__in PVOID _Extension, __in PVOID _Srb)
Definition: storahci.c:1638
#define REVERSE_BYTES_QUAD(Destination, Source)
Definition: scsi.h:2694
FORCEINLINE BOOLEAN StorPortIssueDpc(_In_ PVOID DeviceExtension, _In_ PSTOR_DPC Dpc, _In_ PVOID SystemArgument1, _In_ PVOID SystemArgument2)
Definition: storport.h:2848
STORPORT_API PVOID NTAPI StorPortGetUncachedExtension(_In_ PVOID HwDeviceExtension, _In_ PPORT_CONFIGURATION_INFORMATION ConfigInfo, _In_ ULONG NumberOfBytes)
Definition: storport.c:877
#define AHCI_ATA_CFIS_LBA0
Definition: storahci.h:50
#define DEVICE_ATA_BLOCK_SIZE
Definition: storahci.h:27
#define MAXIMUM_AHCI_PRDT_ENTRIES
Definition: storahci.h:22
#define MAXIMUM_QUEUE_BUFFER_SIZE
Definition: storahci.h:24
#define AHCI_DEVICE_TYPE_ATA
Definition: storahci.h:30
LOCAL_SCATTER_GATHER_LIST Sgl
Definition: storahci.h:559
struct _LOCAL_SCATTER_GATHER_LIST * PLOCAL_SCATTER_GATHER_LIST
FORCEINLINE VOID StorPortReleaseSpinLock(_In_ PVOID DeviceExtension, _Inout_ PSTOR_LOCK_HANDLE LockHandle)
Definition: storport.h:2882
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97