ReactOS 0.4.15-dev-6047-gb29e82d
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
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
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
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 {
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
420VOID
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
450 {
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
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);
502 }
503 }
504
505 return TRUE;
506}// -- AhciHwPassiveInitialize();
507
520NTAPI
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
560VOID
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 {
603 StorPortNotification(RequestComplete, AdapterExtension, Srb);
604 }
605 }
606 }
607
608 return;
609}// -- AhciCompleteIssuedSrb();
610
620VOID
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
718NTAPI
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
786NTAPI
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 {
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:
821 {
823 AdapterExtension->StateFlags.Removed = 1;
824 AhciDebugPrint("\tAdapter removed\n");
825 }
826 break;
827 case StorStopDevice:
828 {
830 AhciDebugPrint("\tRequested to Stop the adapter\n");
831 }
832 break;
833 default:
835 break;
836 }
837 }
838 else
839 {
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);
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;
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;
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);
895 break;
896 }
897 }
898 break;
899 default:
900 AhciDebugPrint("\tUnknown function code recieved: %x\n", Srb->Function);
902 break;
903 }
904
906 {
907 StorPortNotification(RequestComplete, AdapterExtension, Srb);
908 }
909 else
910 {
911 AhciProcessIO(AdapterExtension, Srb->PathId, Srb);
912 }
913 return TRUE;
914}// -- AhciHwStartIo();
915
929NTAPI
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
988ULONG
989NTAPI
991 __in PVOID DeviceExtension,
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
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 {
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
1161ULONG
1162NTAPI
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
1199 &hwInitializationData,
1200 NULL);
1201
1203 return status;
1204}// -- DriverEntry();
1205
1218ULONG
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
1265ULONG
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
1313ULONG
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
1363VOID
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 {
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
1489VOID
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
1554VOID
1556 __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
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
1637VOID
1639 __in PVOID _Extension,
1640 __in PVOID _Srb
1641 )
1642{
1643 PAHCI_PORT_EXTENSION PortExtension;
1644 PAHCI_ADAPTER_EXTENSION AdapterExtension;
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
1680VOID
1682 __in PVOID _Extension,
1683 __in PVOID _Srb
1684 )
1685{
1686 PAHCI_PORT_EXTENSION PortExtension;
1688
1689// PCDB cdb;
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
1711 {
1713 {
1714 PortExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_NODEVICE;
1715 }
1716 return;
1717 }
1718
1719 NT_ASSERT(InquiryData != NULL);
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");
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");
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
1790 {
1791 AhciDebugPrint("\tDataBufferLength < sizeof(INQUIRYDATA), Could crash the driver.\n");
1793 }
1794
1795 // update data transfer length
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;
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
1842UCHAR
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);
1858 PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
1859
1860 NT_ASSERT(PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI);
1861
1862 NT_ASSERT(SrbExtension != NULL);
1863
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;
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
1932UCHAR
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
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
1987UCHAR
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
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 {
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
2097UCHAR
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
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
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
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");
2147 }
2148
2149 return SRB_STATUS_SUCCESS;
2150}// -- DeviceRequestCapacity();
2151
2165UCHAR
2167 __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
2169 __in PCDB Cdb
2170 )
2171{
2172 AhciDebugPrint("DeviceRequestComplete()\n");
2173
2174 UNREFERENCED_PARAMETER(AdapterExtension);
2176
2178
2179 return SRB_STATUS_SUCCESS;
2180}// -- DeviceRequestComplete();
2181
2195UCHAR
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
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
2228 Srb->DataTransferLength = sizeof(LUN_LIST);
2229
2230 return SRB_STATUS_SUCCESS;
2231}// -- DeviceReportLuns();
2232
2249UCHAR
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;
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;
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 {
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
2392BOOLEAN
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 }
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
2442VOID
2446 )
2447{
2448 ULONG i;
2449 for (i = 0; i < BufferSize; i++)
2450 {
2451 Buffer[i] = 0;
2452 }
2453
2454 return;
2455}// -- AhciZeroMemory();
2456
2470BOOLEAN
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
2500BOOLEAN
2503 __in PVOID Srb
2504 )
2505{
2508
2509 if (Queue->Tail == ((Queue->Head + 1) % MAXIMUM_QUEUE_BUFFER_SIZE))
2510 return FALSE;
2511
2512 Queue->Buffer[Queue->Head++] = Srb;
2514
2515 return TRUE;
2516}// -- AddQueue();
2517
2531PVOID
2534 )
2535{
2536 PVOID Srb;
2537
2540
2541 if (Queue->Head == Queue->Tail)
2542 return NULL;
2543
2544 Srb = Queue->Buffer[Queue->Tail++];
2546
2547 return Srb;
2548}// -- RemoveQueue();
2549
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
2594ULONG64
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();
unsigned char BOOLEAN
struct outstanding_list outstanding
Definition: adh-query.c:36
#define IDE_COMMAND_READ_DMA_EXT
Definition: ata.h:262
#define IDE_COMMAND_NOT_VALID
Definition: ata.h:299
#define IDE_LBA_MODE
Definition: ata.h:255
struct _IDENTIFY_DEVICE_DATA * PIDENTIFY_DEVICE_DATA
#define IDE_COMMAND_WRITE_DMA_EXT
Definition: ata.h:267
struct _IDENTIFY_DEVICE_DATA IDENTIFY_DEVICE_DATA
#define IDE_COMMAND_ATAPI_IDENTIFY
Definition: atapi.h:110
#define IDE_COMMAND_WRITE_DMA
Definition: atapi.h:115
#define IDE_COMMAND_IDENTIFY
Definition: atapi.h:118
#define IDE_COMMAND_READ_DMA
Definition: atapi.h:114
#define IDE_COMMAND_ATAPI_PACKET
Definition: atapi.h:109
#define index(s, c)
Definition: various.h:29
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
struct _READ_CAPACITY_DATA * PREAD_CAPACITY_DATA
#define DEVICE_CONNECTED
Definition: cdrw_hw.h:1159
#define SCSIOP_INQUIRY
Definition: cdrw_hw.h:888
#define SCSISTAT_GOOD
Definition: cdrw_hw.h:1078
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
struct _READ_CAPACITY_DATA READ_CAPACITY_DATA
#define DIRECT_ACCESS_DEVICE
Definition: cdrw_hw.h:1144
struct _MODE_PARAMETER_HEADER MODE_PARAMETER_HEADER
#define READ_ONLY_DIRECT_ACCESS_DEVICE
Definition: cdrw_hw.h:1149
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
#define MODE_SENSE_CURRENT_VALUES
Definition: cdrw_hw.h:859
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
union _CDB * PCDB
struct _MODE_PARAMETER_BLOCK MODE_PARAMETER_BLOCK
struct _MODE_PARAMETER_HEADER * PMODE_PARAMETER_HEADER
#define SCSIOP_READ
Definition: cdrw_hw.h:905
#define INQUIRYDATABUFFERSIZE
Definition: cdrw_hw.h:1113
Definition: bufpool.h:45
_In_ ULONG _In_ BOOLEAN _In_ ULONG _In_ UCHAR PathId
Definition: classpnp.h:1313
#define __in
Definition: dbghelp.h:35
#define __inout
Definition: dbghelp.h:50
#define __out
Definition: dbghelp.h:62
#define BufferSize
Definition: mmc.h:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
#define ULONG_PTR
Definition: config.h:101
#define SCSIOP_REPORT_LUNS
Definition: scsi.h:921
#define SP_RETURN_ERROR
Definition: srb.h:523
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:401
#define SP_RETURN_FOUND
Definition: srb.h:522
#define SRB_STATUS_PENDING
Definition: srb.h:340
struct _HW_INITIALIZATION_DATA HW_INITIALIZATION_DATA
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define SRB_FLAGS_DATA_IN
Definition: srb.h:400
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
#define SRB_STATUS_BAD_FUNCTION
Definition: srb.h:364
@ RequestComplete
Definition: srb.h:531
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:348
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:346
STORPORT_API ULONG NTAPI StorPortReadRegisterUlong(_In_ PVOID HwDeviceExtension, _In_ PULONG Register)
Definition: stubs.c:143
STORPORT_API VOID NTAPI StorPortWriteRegisterUlong(_In_ PVOID HwDeviceExtension, _In_ PULONG Register, _In_ ULONG Value)
Definition: stubs.c:291
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_opt_ GUID _In_ USHORT DataBufferLength
Definition: fltkernel.h:1270
GLuint index
Definition: glext.h:6031
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
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
@ PCIBus
Definition: hwresource.cpp:142
if(dx< 0)
Definition: linetemp.h:194
#define PCHAR
Definition: match.c:90
unsigned __int64 ULONG64
Definition: imports.h:198
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
ULONG SectorCount
Definition: part_xbox.c:31
@ Reserved3
Definition: sacdrv.h:1471
_In_opt_ WDFREQUEST _In_ ULONG _In_ BOOLEAN _In_ PCDB Cdb
Definition: scratch.h:159
@ Width32Bits
Definition: miniport.h:107
@ PCIConfiguration
Definition: miniport.h:93
struct _VPD_SUPPORTED_PAGES_PAGE VPD_SUPPORTED_PAGES_PAGE
struct _LUN_LIST LUN_LIST
struct _VPD_SUPPORTED_PAGES_PAGE * PVPD_SUPPORTED_PAGES_PAGE
struct _LUN_LIST * PLUN_LIST
#define VPD_SUPPORTED_PAGES
Definition: scsi.h:2404
#define REVERSE_BYTES_QUAD(Destination, Source)
Definition: scsi.h:3452
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
#define VPD_SERIAL_NUMBER
Definition: scsi.h:2405
#define VPD_DEVICE_IDENTIFIERS
Definition: scsi.h:2406
struct _SCSI_PNP_REQUEST_BLOCK * PSCSI_PNP_REQUEST_BLOCK
@ StorRemoveDevice
Definition: srb.h:392
@ StorStopDevice
Definition: srb.h:393
@ StorSurpriseRemoval
Definition: srb.h:397
#define SRB_PNP_FLAGS_ADAPTER_REQUEST
Definition: srb.h:179
_Must_inspect_result_ _In_ PVOID _In_ struct _HW_INITIALIZATION_DATA _In_ PVOID HwContext
Definition: srb.h:898
#define SRB_FUNCTION_PNP
Definition: srb.h:96
@ StorPowerDeviceD0
Definition: srb.h:348
#define STATUS_SUCCESS
Definition: shellext.h:65
BOOLEAN AhciHwPassiveInitialize(__in PVOID DeviceExtension)
Definition: storahci.c:483
UCHAR DeviceReportLuns(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:2196
BOOLEAN AhciAdapterReset(__in PAHCI_ADAPTER_EXTENSION AdapterExtension)
Definition: storahci.c:2393
UCHAR DeviceInquiryRequest(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:2250
BOOLEAN NTAPI AhciHwInterrupt(__in PVOID DeviceExtension)
Definition: storahci.c:719
BOOLEAN NTAPI AhciHwStartIo(__in PVOID DeviceExtension, __in PSCSI_REQUEST_BLOCK Srb)
Definition: storahci.c:787
VOID AhciInterruptHandler(__in PAHCI_PORT_EXTENSION PortExtension)
Definition: storahci.c:621
BOOLEAN NTAPI AhciPortInitialize(__in PVOID DeviceExtension)
Definition: storahci.c:23
FORCEINLINE BOOLEAN AddQueue(__inout PAHCI_QUEUE Queue, __in PVOID Srb)
Definition: storahci.c:2501
ULONG AhciBuild_PRDT(__in PAHCI_PORT_EXTENSION PortExtension, __in PAHCI_SRB_EXTENSION SrbExtension)
Definition: storahci.c:1314
FORCEINLINE ULONG64 AhciGetLba(__in PCDB Cdb, __in ULONG CdbLength)
Definition: storahci.c:2595
UCHAR DeviceRequestSense(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:1933
FORCEINLINE BOOLEAN IsPortValid(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in ULONG pathId)
Definition: storahci.c:2471
ULONG AhciATAPI_CFIS(__in PAHCI_PORT_EXTENSION PortExtension, __in PAHCI_SRB_EXTENSION SrbExtension)
Definition: storahci.c:1266
UCHAR DeviceRequestReadWrite(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:1988
VOID AhciCommandCompletionDpcRoutine(__in PSTOR_DPC Dpc, __in PVOID HwDeviceExtension, __in PVOID SystemArgument1, __in PVOID SystemArgument2)
Definition: storahci.c:421
FORCEINLINE PVOID RemoveQueue(__inout PAHCI_QUEUE Queue)
Definition: storahci.c:2532
VOID AhciProcessSrb(__in PAHCI_PORT_EXTENSION PortExtension, __in PSCSI_REQUEST_BLOCK Srb, __in ULONG SlotIndex)
Definition: storahci.c:1364
UCHAR AhciATAPICommand(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:1843
BOOLEAN NTAPI AhciHwResetBus(__in PVOID AdapterExtension, __in ULONG PathId)
Definition: storahci.c:930
VOID InquiryCompletion(__in PVOID _Extension, __in PVOID _Srb)
Definition: storahci.c:1681
FORCEINLINE VOID AhciZeroMemory(__out PCHAR Buffer, __in ULONG BufferSize)
Definition: storahci.c:2443
BOOLEAN NTAPI AhciHwInitialize(__in PVOID DeviceExtension)
Definition: storahci.c:521
VOID AhciActivatePort(__in PAHCI_PORT_EXTENSION PortExtension)
Definition: storahci.c:1490
FORCEINLINE PAHCI_SRB_EXTENSION GetSrbExtension(__in PSCSI_REQUEST_BLOCK Srb)
Definition: storahci.c:2564
BOOLEAN AhciAllocateResourceForAdapter(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PPORT_CONFIGURATION_INFORMATION ConfigInfo)
Definition: storahci.c:145
ULONG AhciATA_CFIS(__in PAHCI_PORT_EXTENSION PortExtension, __in PAHCI_SRB_EXTENSION SrbExtension)
Definition: storahci.c:1219
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
VOID AhciProcessIO(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in UCHAR PathId, __in PSCSI_REQUEST_BLOCK Srb)
Definition: storahci.c:1555
VOID AhciCompleteIssuedSrb(__in PAHCI_PORT_EXTENSION PortExtension, __in ULONG CommandsToComplete)
Definition: storahci.c:561
UCHAR DeviceRequestCapacity(__in PAHCI_ADAPTER_EXTENSION AdapterExtension, __in PSCSI_REQUEST_BLOCK Srb, __in PCDB Cdb)
Definition: storahci.c:2098
BOOLEAN AhciStartPort(__in PAHCI_PORT_EXTENSION PortExtension)
Definition: storahci.c:228
VOID AtapiInquiryCompletion(__in PVOID _Extension, __in PVOID _Srb)
Definition: storahci.c:1638
#define AHCI_ATA_CFIS_Device
Definition: storahci.h:53
struct _AHCI_COMMAND_TABLE * PAHCI_COMMAND_TABLE
#define IsAdapterCAPS64(CAP)
Definition: storahci.h:78
#define AHCI_ATA_CFIS_FeaturesLow
Definition: storahci.h:49
#define MAXIMUM_AHCI_PORT_COUNT
Definition: storahci.h:21
#define FIS_TYPE_REG_H2D
Definition: storahci.h:38
struct _AHCI_PORT_EXTENSION * PAHCI_PORT_EXTENSION
#define DEVICE_ATA_BLOCK_SIZE
Definition: storahci.h:27
#define AHCI_DEVICE_TYPE_NODEVICE
Definition: storahci.h:32
#define AHCI_Global_Port_CAP_NCS(x)
Definition: storahci.h:81
#define AHCI_ATA_CFIS_LBA1
Definition: storahci.h:51
#define ATA_FUNCTION_ATA_READ
Definition: storahci.h:64
#define ATA_FUNCTION_ATAPI_COMMAND
Definition: storahci.h:67
#define MAXIMUM_TRANSFER_LENGTH
Definition: storahci.h:25
#define IsAtapiCommand(AtaFunction)
Definition: storahci.h:76
struct _AHCI_COMMAND_HEADER * PAHCI_COMMAND_HEADER
#define AHCI_ATA_CFIS_LBA2
Definition: storahci.h:52
#define AHCI_ATA_CFIS_LBA4
Definition: storahci.h:55
#define AHCI_ATA_CFIS_CommandReg
Definition: storahci.h:48
#define AHCI_ATA_CFIS_LBA3
Definition: storahci.h:54
#define AHCI_ATA_CFIS_FisType
Definition: storahci.h:46
#define AHCI_DEVICE_TYPE_ATA
Definition: storahci.h:30
struct _AHCI_RECEIVED_FIS * PAHCI_RECEIVED_FIS
struct _AHCI_SRB_EXTENSION AHCI_SRB_EXTENSION
#define AHCI_ATA_CFIS_SectorCountHigh
Definition: storahci.h:59
VOID(* PAHCI_COMPLETION_ROUTINE)(__in PVOID PortExtension, __in PVOID Srb)
Definition: storahci.h:89
struct _LOCAL_SCATTER_GATHER_LIST * PLOCAL_SCATTER_GATHER_LIST
#define IsAtaCommand(AtaFunction)
Definition: storahci.h:75
struct _AHCI_ADAPTER_EXTENSION AHCI_ADAPTER_EXTENSION
#define AHCI_ATA_CFIS_PMPort_C
Definition: storahci.h:47
struct _AHCI_ADAPTER_EXTENSION * PAHCI_ADAPTER_EXTENSION
#define AHCI_ATA_CFIS_SectorCountLow
Definition: storahci.h:58
#define AHCI_DEVICE_TYPE_ATAPI
Definition: storahci.h:31
#define AHCI_ATA_CFIS_LBA5
Definition: storahci.h:56
#define IsDataTransferNeeded(SrbExtension)
Definition: storahci.h:77
#define AhciDebugPrint(format,...)
Definition: storahci.h:85
#define ATA_FUNCTION_ATA_IDENTIFY
Definition: storahci.h:63
struct _AHCI_COMMAND_HEADER AHCI_COMMAND_HEADER
#define AHCI_ATA_CFIS_FeaturesHigh
Definition: storahci.h:57
#define AHCI_ATA_CFIS_LBA0
Definition: storahci.h:50
#define MAXIMUM_QUEUE_BUFFER_SIZE
Definition: storahci.h:24
#define MAXIMUM_AHCI_PRDT_ENTRIES
Definition: storahci.h:22
STORPORT_API BOOLEAN NTAPI StorPortSetDeviceQueueDepth(_In_ PVOID HwDeviceExtension, _In_ UCHAR PathId, _In_ UCHAR TargetId, _In_ UCHAR Lun, _In_ ULONG Depth)
Definition: storport.c:1398
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:657
STORPORT_API PSTOR_SCATTER_GATHER_LIST NTAPI StorPortGetScatterGatherList(_In_ PVOID DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: storport.c:846
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:791
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:701
STORPORT_API ULONG NTAPI StorPortInitialize(_In_ PVOID Argument1, _In_ PVOID Argument2, _In_ struct _HW_INITIALIZATION_DATA *HwInitializationData, _In_opt_ PVOID HwContext)
Definition: storport.c:949
STORPORT_API VOID NTAPI StorPortStallExecution(_In_ ULONG Delay)
Definition: storport.c:1417
STORPORT_API VOID StorPortNotification(_In_ SCSI_NOTIFICATION_TYPE NotificationType, _In_ PVOID HwDeviceExtension,...)
Definition: storport.c:1093
STORPORT_API PVOID NTAPI StorPortGetUncachedExtension(_In_ PVOID HwDeviceExtension, _In_ PPORT_CONFIGURATION_INFORMATION ConfigInfo, _In_ ULONG NumberOfBytes)
Definition: storport.c:880
FORCEINLINE VOID StorPortReleaseSpinLock(_In_ PVOID DeviceExtension, _Inout_ PSTOR_LOCK_HANDLE LockHandle)
Definition: storport.h:2919
#define StorPortCopyMemory(Destination, Source, Length)
Definition: storport.h:2355
FORCEINLINE BOOLEAN StorPortIssueDpc(_In_ PVOID DeviceExtension, _In_ PSTOR_DPC Dpc, _In_ PVOID SystemArgument1, _In_ PVOID SystemArgument2)
Definition: storport.h:2885
@ StorSynchronizeFullDuplex
Definition: storport.h:427
FORCEINLINE VOID StorPortAcquireSpinLock(_In_ PVOID DeviceExtension, _In_ STOR_SPINLOCK SpinLock, _In_ PVOID LockContext, _Inout_ PSTOR_LOCK_HANDLE LockHandle)
Definition: storport.h:2904
@ InterruptLock
Definition: storport.h:442
#define STOR_MAP_NON_READ_WRITE_BUFFERS
Definition: storport.h:395
FORCEINLINE BOOLEAN StorPortEnablePassiveInitialization(_In_ PVOID DeviceExtension, _In_ PHW_PASSIVE_INITIALIZE_ROUTINE HwPassiveInitializeRoutine)
Definition: storport.h:2857
FORCEINLINE VOID StorPortInitializeDpc(_In_ PVOID DeviceExtension, _Out_ PSTOR_DPC Dpc, _In_ PHW_DPC_ROUTINE HwDpcRoutine)
Definition: storport.h:2872
@ DeviceRequestComplete
Definition: strmini.h:330
ULONG RangeLength
Definition: srb.h:42
BOOLEAN RangeInMemory
Definition: srb.h:43
SCSI_PHYSICAL_ADDRESS RangeStart
Definition: srb.h:41
PAHCI_MEMORY_REGISTERS ABAR_Address
Definition: storahci.h:527
AHCI_PORT_EXTENSION PortExtension[MAXIMUM_AHCI_PORT_COUNT]
Definition: storahci.h:528
struct _AHCI_ADAPTER_EXTENSION::@1327 StateFlags
AHCI_COMMAND_HEADER_DESCRIPTION DI
Definition: storahci.h:369
UCHAR CFIS[64]
Definition: storahci.h:360
AHCI_PRDT PRDT[MAXIMUM_AHCI_PRDT_ENTRIES]
Definition: storahci.h:363
AHCI_PORT PortList[MAXIMUM_AHCI_PORT_COUNT]
Definition: storahci.h:458
PAHCI_PORT Port
Definition: storahci.h:485
struct _AHCI_ADAPTER_EXTENSION * AdapterExtension
Definition: storahci.h:494
PIDENTIFY_DEVICE_DATA IdentifyDeviceData
Definition: storahci.h:492
AHCI_QUEUE CompletionQueue
Definition: storahci.h:487
STOR_PHYSICAL_ADDRESS IdentifyDeviceDataPhysicalAddress
Definition: storahci.h:493
struct _AHCI_PORT_EXTENSION::@1326 DeviceParams
STOR_DEVICE_POWER_STATE DevicePowerState
Definition: storahci.h:491
ULONG CommandIssuedSlots
Definition: storahci.h:466
PAHCI_RECEIVED_FIS ReceivedFIS
Definition: storahci.h:489
PAHCI_COMMAND_HEADER CommandList
Definition: storahci.h:490
STOR_DPC CommandCompletion
Definition: storahci.h:484
AHCI_QUEUE SrbQueue
Definition: storahci.h:486
ULONG CLB
Definition: storahci.h:393
ULONG IS
Definition: storahci.h:397
ULONG FB
Definition: storahci.h:395
ULONG FBU
Definition: storahci.h:396
ULONG CMD
Definition: storahci.h:399
ULONG SERR
Definition: storahci.h:405
ULONG CLBU
Definition: storahci.h:394
ULONG DBA
Definition: storahci.h:346
ULONG DBAU
Definition: storahci.h:347
ULONG DBC
Definition: storahci.h:350
PAHCI_COMPLETION_ROUTINE CompletionRoutine
Definition: storahci.h:561
PLOCAL_SCATTER_GATHER_LIST pSgl
Definition: storahci.h:560
LOCAL_SCATTER_GATHER_LIST Sgl
Definition: storahci.h:559
PHW_INTERRUPT HwInterrupt
Definition: srb.h:569
BOOLEAN TaggedQueuing
Definition: srb.h:582
BOOLEAN AutoRequestSense
Definition: srb.h:583
PHW_RESET_BUS HwResetBus
Definition: srb.h:571
PHW_STARTIO HwStartIo
Definition: srb.h:568
BOOLEAN MultipleRequestPerLu
Definition: srb.h:584
BOOLEAN NeedPhysicalAddresses
Definition: srb.h:581
ULONG SrbExtensionSize
Definition: srb.h:576
ULONG HwInitializationDataSize
Definition: srb.h:550
PHW_INITIALIZE HwInitialize
Definition: srb.h:567
ULONG DeviceExtensionSize
Definition: srb.h:574
INTERFACE_TYPE AdapterInterfaceType
Definition: srb.h:565
PHW_FIND_ADAPTER HwFindAdapter
Definition: srb.h:570
BOOLEAN MapBuffers
Definition: srb.h:580
ULONG NumberOfAccessRanges
Definition: srb.h:577
UCHAR FirmwareRevision[8]
Definition: ata.h:25
ULONG Max48BitLBA[2]
Definition: ata.h:168
struct _IDENTIFY_DEVICE_DATA::@1871 CommandSetActive
struct _IDENTIFY_DEVICE_DATA::@1868 GeneralConfiguration
UCHAR ModelNumber[40]
Definition: ata.h:26
UCHAR SerialNumber[20]
Definition: ata.h:22
struct _IDENTIFY_DEVICE_DATA::@1870 CommandSetSupport
ULONG UserAddressableSectors
Definition: ata.h:51
struct _IDENTIFY_DEVICE_DATA::@1872 PhysicalLogicalSectorSize
UCHAR Versions
Definition: cdrw_hw.h:1120
UCHAR CommandQueue
Definition: cdrw_hw.h:1125
UCHAR RemovableMedia
Definition: cdrw_hw.h:1119
UCHAR ProductId[16]
Definition: cdrw_hw.h:1133
UCHAR ProductRevisionLevel[4]
Definition: cdrw_hw.h:1134
UCHAR DeviceTypeModifier
Definition: cdrw_hw.h:1118
UCHAR Wide32Bit
Definition: cdrw_hw.h:1130
UCHAR VendorId[8]
Definition: cdrw_hw.h:1132
UCHAR ResponseDataFormat
Definition: cdrw_hw.h:1121
UCHAR DeviceType
Definition: cdrw_hw.h:1116
UCHAR DeviceTypeQualifier
Definition: cdrw_hw.h:1117
UCHAR AdditionalLength
Definition: cdrw_hw.h:1122
STOR_SCATTER_GATHER_ELEMENT List[MAXIMUM_AHCI_PRDT_ENTRIES]
Definition: storahci.h:535
UCHAR LunListLength[4]
Definition: scsi.h:3177
UCHAR DeviceSpecificParameter
Definition: cdrw_hw.h:2507
ULONG LogicalBlockAddress
Definition: cdrw_hw.h:1471
STOR_PNP_ACTION PnPAction
Definition: srb.h:422
UCHAR TargetId
Definition: srb.h:254
PVOID DataBuffer
Definition: srb.h:263
UCHAR PathId
Definition: srb.h:253
UCHAR CdbLength
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:279
UCHAR Function
Definition: srb.h:250
UCHAR ScsiStatus
Definition: srb.h:252
ULONG DataTransferLength
Definition: srb.h:261
PVOID SrbExtension
Definition: srb.h:267
ULONG SrbFlags
Definition: srb.h:260
UCHAR SrbStatus
Definition: srb.h:251
STOR_PHYSICAL_ADDRESS PhysicalAddress
Definition: storport.h:2047
UCHAR SupportedPageList[0]
Definition: scsi.h:2633
Definition: ftp_var.h:139
Definition: ps.c:97
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
#define ATA_FLAGS_USE_DMA
Definition: uata_ctl.h:226
#define ATA_FLAGS_DATA_OUT
Definition: uata_ctl.h:221
#define ATA_FLAGS_DATA_IN
Definition: uata_ctl.h:222
#define ATA_FLAGS_48BIT_COMMAND
Definition: uata_ctl.h:223
#define lba
ULONG Status
Definition: storahci.h:261
ULONG IE
Definition: storahci.h:255
ULONG HR
Definition: storahci.h:254
ULONG AE
Definition: storahci.h:258
ULONG MRSM
Definition: storahci.h:256
struct _AHCI_TASK_FILE_DATA::@1322::_STS STS
Definition: cdrw_hw.h:28
struct _CDB::_CDB10 CDB10
struct _CDB::_CDB6INQUIRY3 CDB6INQUIRY3
struct _CDB::_MODE_SENSE MODE_SENSE
struct _CDB::_CDB16 CDB16
ULONG LowPart
Definition: typedefs.h:106
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2225
_In_ WDFDEVICE _In_ PPNP_BUS_INFORMATION BusInformation
Definition: wdfdevice.h:3915
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:895
#define FORCEINLINE
Definition: wdftypes.h:67
struct _PCI_COMMON_CONFIG * PPCI_COMMON_CONFIG
struct _PCI_COMMON_CONFIG PCI_COMMON_CONFIG
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:676
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:677
#define NT_ASSERT
Definition: rtlfuncs.h:3310
unsigned char UCHAR
Definition: xmlstorage.h:181