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)
11 * @name AhciPortInitialize
14 * Initialize port by setting up PxCLB & PxFB Registers
16 * @param portExtension
19 * Return true if intialization was successful
23 __in PAHCI_PORT_EXTENSION portExtension
27 PAHCI_MEMORY_REGISTERS abar
;
28 PAHCI_ADAPTER_EXTENSION adapterExtension
;
29 STOR_PHYSICAL_ADDRESS commandListPhysical
, receivedFISPhysical
;
31 DebugPrint("AhciPortInitialize()\n");
33 NT_ASSERT(portExtension
!= NULL
);
35 adapterExtension
= portExtension
->AdapterExtension
;
36 abar
= adapterExtension
->ABAR_Address
;
38 NT_ASSERT(abar
!= NULL
);
40 portExtension
->Port
= &abar
->PortList
[portExtension
->PortNumber
];
42 commandListPhysical
= StorPortGetPhysicalAddress( adapterExtension
,
44 portExtension
->CommandList
,
47 if ((mappedLength
) == 0 || ((commandListPhysical
.LowPart
% 1024) != 0))
49 DebugPrint("\tcommandListPhysical mappedLength:%d\n", mappedLength
);
53 receivedFISPhysical
= StorPortGetPhysicalAddress( adapterExtension
,
55 portExtension
->ReceivedFIS
,
58 if ((mappedLength
) == 0 || ((receivedFISPhysical
.LowPart
% 1024) != 0))
60 DebugPrint("\treceivedFISPhysical mappedLength:%d\n", mappedLength
);
64 if ((adapterExtension
->CAP
& AHCI_Global_HBA_CAP_S64A
) != 0)
66 DebugPrint("\tCAP.S64A not supported\n");
70 // 10.1.2 For each implemented port, system software shall allocate memory for and program:
71 // PxCLB and PxCLBU (if CAP.S64A is set to ‘1’)
72 // PxFB and PxFBU (if CAP.S64A is set to ‘1’)
73 // Note: Assuming 32bit support only
74 StorPortWriteRegisterUlong(adapterExtension
, &portExtension
->Port
->CLB
, commandListPhysical
.LowPart
);
75 StorPortWriteRegisterUlong(adapterExtension
, &portExtension
->Port
->FB
, receivedFISPhysical
.LowPart
);
77 // set device power state flag to D0
78 portExtension
->DevicePowerState
= StorPowerDeviceD0
;
80 // clear pending interrupts
81 StorPortWriteRegisterUlong(adapterExtension
, &portExtension
->Port
->SERR
, (ULONG
)-1);
82 StorPortWriteRegisterUlong(adapterExtension
, &portExtension
->Port
->IS
, (ULONG
)-1);
83 StorPortWriteRegisterUlong(adapterExtension
, portExtension
->AdapterExtension
->IS
, (1 << portExtension
->PortNumber
));
86 }// -- AhciPortInitialize();
89 * @name AhciAllocateResourceForAdapter
92 * Allocate memory from poll for required pointers
94 * @param adapterExtension
98 * return TRUE if allocation was successful
101 AhciAllocateResourceForAdapter (
102 __in PAHCI_ADAPTER_EXTENSION adapterExtension
,
103 __in PPORT_CONFIGURATION_INFORMATION ConfigInfo
106 PVOID portsExtension
= NULL
;
107 PCHAR nonCachedExtension
;
108 ULONG status
, index
, NCS
, AlignedNCS
;
109 ULONG portCount
, portImplemented
, nonCachedExtensionSize
;
111 DebugPrint("AhciAllocateResourceForAdapter()\n");
113 NCS
= AHCI_Global_Port_CAP_NCS(adapterExtension
->CAP
);
114 AlignedNCS
= ROUND_UP(NCS
, 8);
116 // get port count -- Number of set bits in `adapterExtension->PortImplemented`
118 portImplemented
= adapterExtension
->PortImplemented
;
119 while (portImplemented
> 0)
122 portImplemented
&= (portImplemented
- 1);
125 NT_ASSERT(portCount
!= 0);
126 DebugPrint("\tPort Count: %d\n", portCount
);
128 nonCachedExtensionSize
= sizeof(AHCI_COMMAND_HEADER
) * AlignedNCS
+ //should be 1K aligned
129 sizeof(AHCI_RECEIVED_FIS
);
131 // align nonCachedExtensionSize to 1024
132 nonCachedExtensionSize
= ROUND_UP(nonCachedExtensionSize
, 1024);
134 adapterExtension
->NonCachedExtension
= StorPortGetUncachedExtension( adapterExtension
,
136 nonCachedExtensionSize
* portCount
);
138 if (adapterExtension
->NonCachedExtension
== NULL
)
140 DebugPrint("\tadapterExtension->NonCachedExtension == NULL\n");
144 nonCachedExtension
= adapterExtension
->NonCachedExtension
;
145 AhciZeroMemory(nonCachedExtension
, nonCachedExtensionSize
* portCount
);
147 for (index
= 0; index
< MAXIMUM_AHCI_PORT_COUNT
; index
++)
149 adapterExtension
->PortExtension
[index
].IsActive
= FALSE
;
150 if ((adapterExtension
->PortImplemented
& (1 << index
)) != 0)
152 adapterExtension
->PortExtension
[index
].PortNumber
= index
;
153 adapterExtension
->PortExtension
[index
].IsActive
= TRUE
;
154 adapterExtension
->PortExtension
[index
].AdapterExtension
= adapterExtension
;
155 adapterExtension
->PortExtension
[index
].CommandList
= nonCachedExtension
;
156 adapterExtension
->PortExtension
[index
].ReceivedFIS
= (PAHCI_RECEIVED_FIS
)(nonCachedExtension
+ sizeof(AHCI_COMMAND_HEADER
) * AlignedNCS
);
157 nonCachedExtension
+= nonCachedExtensionSize
;
162 }// -- AhciAllocateResourceForAdapter();
165 * @name AhciHwInitialize
168 * initializes the HBA and finds all devices that are of interest to the miniport driver.
170 * @param adapterExtension
173 * return TRUE if intialization was successful
177 __in PVOID AdapterExtension
180 ULONG ghc
, messageCount
, status
;
181 PAHCI_ADAPTER_EXTENSION adapterExtension
;
183 DebugPrint("AhciHwInitialize()\n");
185 adapterExtension
= AdapterExtension
;
186 adapterExtension
->StateFlags
.MessagePerPort
= FALSE
;
188 // First check what type of interrupt/synchronization device is using
189 ghc
= StorPortReadRegisterUlong(adapterExtension
, &adapterExtension
->ABAR_Address
->GHC
);
191 // When set to ‘1’ by hardware, indicates that the HBA requested more than one MSI vector
192 // but has reverted to using the first vector only. When this bit is cleared to ‘0’,
193 // the HBA has not reverted to single MSI mode (i.e. hardware is already in single MSI mode,
194 // software has allocated the number of messages requested
195 if ((ghc
& AHCI_Global_HBA_CONTROL_MRSM
) == 0)
197 adapterExtension
->StateFlags
.MessagePerPort
= TRUE
;
198 DebugPrint("\tMultiple MSI based message not supported\n");
202 }// -- AhciHwInitialize();
205 * @name AhciInterruptHandler
208 * Interrupt Handler for portExtension
210 * @param portExtension
214 AhciInterruptHandler (
215 __in PAHCI_PORT_EXTENSION portExtension
218 DebugPrint("AhciInterruptHandler()\n");
219 DebugPrint("\tPort Number: %d\n", portExtension
->PortNumber
);
221 }// -- AhciInterruptHandler();
224 * @name AhciHwInterrupt
227 * The Storport driver calls the HwStorInterrupt routine after the HBA generates an interrupt request.
229 * @param adapterExtension
232 * return TRUE Indicates that an interrupt was pending on adapter.
233 * return FALSE Indicates the interrupt was not ours.
237 __in PVOID AdapterExtension
240 ULONG portPending
, nextPort
, i
;
241 PAHCI_ADAPTER_EXTENSION adapterExtension
;
243 DebugPrint("AhciHwInterrupt()\n");
245 adapterExtension
= AdapterExtension
;
247 if (adapterExtension
->StateFlags
.Removed
)
252 portPending
= StorPortReadRegisterUlong(adapterExtension
, adapterExtension
->IS
);
253 // we process interrupt for implemented ports only
254 portPending
= portPending
& adapterExtension
->PortImplemented
;
256 if (portPending
== 0)
261 for (i
= 1; i
<= MAXIMUM_AHCI_PORT_COUNT
; i
++)
263 nextPort
= (adapterExtension
->LastInterruptPort
+ i
) % MAXIMUM_AHCI_PORT_COUNT
;
265 if ((portPending
& (0x1 << nextPort
)) == 0)
268 if ((nextPort
== adapterExtension
->LastInterruptPort
)
269 || (adapterExtension
->PortExtension
[nextPort
].IsActive
== FALSE
))
274 // we can assign this interrupt to this port
275 adapterExtension
->LastInterruptPort
= nextPort
;
276 AhciInterruptHandler(&adapterExtension
->PortExtension
[nextPort
]);
280 DebugPrint("\tSomething wrong");
282 }// -- AhciHwInterrupt();
285 * @name AhciHwStartIo
288 * The Storport driver calls the HwStorStartIo routine one time for each incoming I/O request.
290 * @param adapterExtension
294 * return TRUE if the request was accepted
295 * return FALSE if the request must be submitted later
299 __in PVOID AdapterExtension
,
300 __in PSCSI_REQUEST_BLOCK Srb
303 UCHAR function
, pathId
;
304 PAHCI_ADAPTER_EXTENSION adapterExtension
;
306 DebugPrint("AhciHwStartIo()\n");
308 pathId
= Srb
->PathId
;
309 function
= Srb
->Function
;
310 adapterExtension
= AdapterExtension
;
312 if (!IsPortValid(adapterExtension
, pathId
))
314 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
315 StorPortNotification(RequestComplete
, adapterExtension
, Srb
);
319 // https://msdn.microsoft.com/windows/hardware/drivers/storage/handling-srb-function-pnp
320 // If the function member of an SRB is set to SRB_FUNCTION_PNP,
321 // the SRB is a structure of type SCSI_PNP_REQUEST_BLOCK.
322 if (function
== SRB_FUNCTION_PNP
)
324 PSCSI_PNP_REQUEST_BLOCK pnpRequest
;
326 pnpRequest
= (PSCSI_PNP_REQUEST_BLOCK
)Srb
;
327 if ((pnpRequest
->SrbPnPFlags
& SRB_PNP_FLAGS_ADAPTER_REQUEST
) != 0)
329 if ((pnpRequest
->PnPAction
== StorRemoveDevice
) ||
330 (pnpRequest
->PnPAction
== StorSurpriseRemoval
))
332 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
333 adapterExtension
->StateFlags
.Removed
= 1;
334 DebugPrint("\tadapter removed\n");
336 else if (pnpRequest
->PnPAction
== StorStopDevice
)
338 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
339 DebugPrint("\tRequested to Stop the adapter\n");
343 Srb
->SrbStatus
= SRB_STATUS_INVALID_REQUEST
;
346 StorPortNotification(RequestComplete
, adapterExtension
, Srb
);
351 if (function
== SRB_FUNCTION_EXECUTE_SCSI
)
353 // https://msdn.microsoft.com/en-us/windows/hardware/drivers/storage/handling-srb-function-execute-scsi
354 // On receipt of an SRB_FUNCTION_EXECUTE_SCSI request, a miniport driver's HwScsiStartIo
355 // routine does the following:
357 // - Gets and/or sets up whatever context the miniport driver maintains in its device,
358 // logical unit, and/or SRB extensions
359 // For example, a miniport driver might set up a logical unit extension with pointers
360 // to the SRB itself and the SRB DataBuffer pointer, the SRB DataTransferLength value,
361 // and a driver-defined value (or CDB SCSIOP_XXX value) indicating the operation to be
362 // carried out on the HBA.
364 // - Calls an internal routine to program the HBA, as partially directed by the SrbFlags,
365 // for the requested operation
366 // For a device I/O operation, such an internal routine generally selects the target device
367 // and sends the CDB over the bus to the target logical unit.
368 if (Srb
->CdbLength
> 0)
370 PCDB cdb
= (PCDB
)&Srb
->Cdb
;
371 if (cdb
->CDB10
.OperationCode
== SCSIOP_INQUIRY
)
373 Srb
->SrbStatus
= DeviceInquiryRequest(adapterExtension
, Srb
, cdb
);
374 StorPortNotification(RequestComplete
, adapterExtension
, Srb
);
381 Srb
->SrbStatus
= SRB_STATUS_BAD_FUNCTION
;
382 StorPortNotification(RequestComplete
, adapterExtension
, Srb
);
387 DebugPrint("\tUnknow function code recieved: %x\n", function
);
388 Srb
->SrbStatus
= SRB_STATUS_BAD_FUNCTION
;
389 StorPortNotification(RequestComplete
, adapterExtension
, Srb
);
391 }// -- AhciHwStartIo();
394 * @name AhciHwResetBus
397 * The HwStorResetBus routine is called by the port driver to clear error conditions.
399 * @param adapterExtension
403 * return TRUE if bus was successfully reset
407 __in PVOID AdapterExtension
,
411 PAHCI_ADAPTER_EXTENSION adapterExtension
;
413 DebugPrint("AhciHwResetBus()\n");
415 adapterExtension
= AdapterExtension
;
418 }// -- AhciHwResetBus();
421 * @name AhciHwFindAdapter
424 * The HwStorFindAdapter routine uses the supplied configuration to determine whether a specific
425 * HBA is supported and, if it is, to return configuration information about that adapter.
427 * 10.1 Platform Communication
428 * http://www.intel.in/content/dam/www/public/us/en/documents/technical-specifications/serial-ata-ahci-spec-rev1_2.pdf
430 * @param DeviceExtension
432 * @param BusInformation
433 * @param ArgumentString
439 * Indicates that a supported HBA was found and that the HBA-relevant configuration information was successfully determined and set in the PORT_CONFIGURATION_INFORMATION structure.
442 * Indicates that an HBA was found but there was an error obtaining the configuration information. If possible, such an error should be logged with StorPortLogError.
444 * SP_RETURN_BAD_CONFIG
445 * Indicates that the supplied configuration information was invalid for the adapter.
447 * SP_RETURN_NOT_FOUND
448 * Indicates that no supported HBA was found for the supplied configuration information.
450 * @remarks Called by Storport.
454 __in PVOID AdapterExtension
,
455 __in PVOID HwContext
,
456 __in PVOID BusInformation
,
457 __in PVOID ArgumentString
,
458 __inout PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
459 __in PBOOLEAN Reserved3
464 ULONG portCount
, portImplemented
;
466 UCHAR pci_cfg_buf
[sizeof(PCI_COMMON_CONFIG
)];
467 PACCESS_RANGE accessRange
;
469 PAHCI_MEMORY_REGISTERS abar
;
470 PPCI_COMMON_CONFIG pciConfigData
;
471 PAHCI_ADAPTER_EXTENSION adapterExtension
;
473 DebugPrint("AhciHwFindAdapter()\n");
475 adapterExtension
= AdapterExtension
;
476 adapterExtension
->SlotNumber
= ConfigInfo
->SlotNumber
;
477 adapterExtension
->SystemIoBusNumber
= ConfigInfo
->SystemIoBusNumber
;
479 // get PCI configuration header
480 pci_cfg_len
= StorPortGetBusData(
483 adapterExtension
->SystemIoBusNumber
,
484 adapterExtension
->SlotNumber
,
486 sizeof(PCI_COMMON_CONFIG
));
488 if (pci_cfg_len
!= sizeof(PCI_COMMON_CONFIG
))
490 DebugPrint("\tpci_cfg_len != %d :: %d", sizeof(PCI_COMMON_CONFIG
), pci_cfg_len
);
491 return SP_RETURN_ERROR
;//Not a valid device at the given bus number
494 pciConfigData
= pci_cfg_buf
;
495 adapterExtension
->VendorID
= pciConfigData
->VendorID
;
496 adapterExtension
->DeviceID
= pciConfigData
->DeviceID
;
497 adapterExtension
->RevisionID
= pciConfigData
->RevisionID
;
498 // 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).
499 adapterExtension
->AhciBaseAddress
= pciConfigData
->u
.type0
.BaseAddresses
[5] & (0xFFFFFFF0);
501 DebugPrint("\tVendorID:%d DeviceID:%d RevisionID:%d\n", adapterExtension
->VendorID
, adapterExtension
->DeviceID
, adapterExtension
->RevisionID
);
505 if (ConfigInfo
->NumberOfAccessRanges
> 0)
507 for (index
= 0; index
< ConfigInfo
->NumberOfAccessRanges
; index
++)
509 accessRange
= *ConfigInfo
->AccessRanges
;
510 if (accessRange
[index
].RangeStart
.QuadPart
== adapterExtension
->AhciBaseAddress
)
512 abar
= StorPortGetDeviceBase(
514 ConfigInfo
->AdapterInterfaceType
,
515 ConfigInfo
->SystemIoBusNumber
,
516 accessRange
[index
].RangeStart
,
517 accessRange
[index
].RangeLength
,
518 !accessRange
[index
].RangeInMemory
);
526 DebugPrint("\tabar == NULL\n");
527 return SP_RETURN_ERROR
; // corrupted information supplied
530 adapterExtension
->ABAR_Address
= abar
;
531 adapterExtension
->CAP
= StorPortReadRegisterUlong(adapterExtension
, &abar
->CAP
);
532 adapterExtension
->CAP2
= StorPortReadRegisterUlong(adapterExtension
, &abar
->CAP2
);
533 adapterExtension
->Version
= StorPortReadRegisterUlong(adapterExtension
, &abar
->VS
);
534 adapterExtension
->LastInterruptPort
= -1;
537 // 1. Indicate that system software is AHCI aware by setting GHC.AE to ‘1’.
538 // 3.1.2 -- AE bit is read-write only if CAP.SAM is '0'
539 ghc
= StorPortReadRegisterUlong(adapterExtension
, &abar
->GHC
);
540 // AE := Highest Significant bit of GHC
541 if ((ghc
& AHCI_Global_HBA_CONTROL_AE
) != 0)//Hmm, controller was already in power state
543 // reset controller to have it in known state
544 DebugPrint("\tAE Already set, Reset()\n");
545 if (!AhciAdapterReset(adapterExtension
)){
546 DebugPrint("\tReset Failed!\n");
547 return SP_RETURN_ERROR
;// reset failed
551 ghc
= AHCI_Global_HBA_CONTROL_AE
;// only AE=1
552 StorPortWriteRegisterUlong(adapterExtension
, &abar
->GHC
, ghc
);
554 adapterExtension
->IS
= &abar
->IS
;
555 adapterExtension
->PortImplemented
= StorPortReadRegisterUlong(adapterExtension
, &abar
->PI
);
557 if (adapterExtension
->PortImplemented
== 0)
559 DebugPrint("\tadapterExtension->PortImplemented == 0\n");
560 return SP_RETURN_ERROR
;
563 ConfigInfo
->MaximumTransferLength
= MAXIMUM_TRANSFER_LENGTH
;//128 KB
564 ConfigInfo
->NumberOfPhysicalBreaks
= 0x21;
565 ConfigInfo
->MaximumNumberOfTargets
= 1;
566 ConfigInfo
->MaximumNumberOfLogicalUnits
= 1;
567 ConfigInfo
->ResetTargetSupported
= TRUE
;
568 ConfigInfo
->NumberOfBuses
= MAXIMUM_AHCI_PORT_COUNT
;
569 ConfigInfo
->SynchronizationModel
= StorSynchronizeFullDuplex
;
570 ConfigInfo
->ScatterGather
= TRUE
;
572 // Turn IE -- Interrupt Enabled
573 ghc
|= AHCI_Global_HBA_CONTROL_IE
;
574 StorPortWriteRegisterUlong(adapterExtension
, &abar
->GHC
, ghc
);
576 // allocate necessary resource for each port
577 if (!AhciAllocateResourceForAdapter(adapterExtension
, ConfigInfo
))
579 DebugPrint("\tAhciAllocateResourceForAdapter() == FALSE\n");
580 return SP_RETURN_ERROR
;
583 for (index
= 0; index
< MAXIMUM_AHCI_PORT_COUNT
; index
++)
585 if ((adapterExtension
->PortImplemented
& (0x1<<index
)) != 0)
586 AhciPortInitialize(&adapterExtension
->PortExtension
[index
]);
589 return SP_RETURN_FOUND
;
590 }// -- AhciHwFindAdapter();
596 * Initial Entrypoint for storahci miniport driver
598 * @param DriverObject
599 * @param RegistryPath
602 * NT_STATUS in case of driver loaded successfully.
606 __in PVOID DriverObject
,
607 __in PVOID RegistryPath
610 HW_INITIALIZATION_DATA hwInitializationData
;
613 DebugPrint("Storahci Loaded\n");
615 // initialize the hardware data structure
616 AhciZeroMemory(&hwInitializationData
, sizeof(HW_INITIALIZATION_DATA
));
618 // set size of hardware initialization structure
619 hwInitializationData
.HwInitializationDataSize
= sizeof(HW_INITIALIZATION_DATA
);
621 // identity required miniport entry point routines
622 hwInitializationData
.HwStartIo
= AhciHwStartIo
;
623 hwInitializationData
.HwResetBus
= AhciHwResetBus
;
624 hwInitializationData
.HwInterrupt
= AhciHwInterrupt
;
625 hwInitializationData
.HwInitialize
= AhciHwInitialize
;
626 hwInitializationData
.HwFindAdapter
= AhciHwFindAdapter
;
628 // adapter specific information
629 hwInitializationData
.NeedPhysicalAddresses
= TRUE
;
630 hwInitializationData
.TaggedQueuing
= TRUE
;
631 hwInitializationData
.AutoRequestSense
= TRUE
;
632 hwInitializationData
.MultipleRequestPerLu
= TRUE
;
634 hwInitializationData
.NumberOfAccessRanges
= 6;
635 hwInitializationData
.AdapterInterfaceType
= PCIBus
;
636 hwInitializationData
.MapBuffers
= STOR_MAP_NON_READ_WRITE_BUFFERS
;
638 // set required extension sizes
639 hwInitializationData
.SrbExtensionSize
= sizeof(AHCI_SRB_EXTENSION
);
640 hwInitializationData
.DeviceExtensionSize
= sizeof(AHCI_ADAPTER_EXTENSION
);
642 // register our hw init data
643 status
= StorPortInitialize(
646 &hwInitializationData
,
649 DebugPrint("\tstatus:%x\n", status
);
651 }// -- DriverEntry();
654 * @name AhciAdapterReset
658 * If the HBA becomes unusable for multiple ports, and a software reset or port reset does not correct the
659 * problem, software may reset the entire HBA by setting GHC.HR to ‘1’. When software sets the GHC.HR
660 * bit to ‘1’, the HBA shall perform an internal reset action. The bit shall be cleared to ‘0’ by the HBA when
661 * the reset is complete. A software write of ‘0’ to GHC.HR shall have no effect. To perform the HBA reset,
662 * software sets GHC.HR to ‘1’ and may poll until this bit is read to be ‘0’, at which point software knows that
663 * the HBA reset has completed.
664 * If the HBA has not cleared GHC.HR to ‘0’ within 1 second of software setting GHC.HR to ‘1’, the HBA is in
665 * a hung or locked state.
667 * @param adapterExtension
670 * TRUE in case AHCI Controller RESTARTED successfully. i.e GHC.HR == 0
674 __in PAHCI_ADAPTER_EXTENSION adapterExtension
678 PAHCI_MEMORY_REGISTERS abar
= NULL
;
680 DebugPrint("AhciAdapterReset()\n");
682 abar
= adapterExtension
->ABAR_Address
;
683 if (abar
== NULL
) // basic sanity
688 // HR -- Very first bit (lowest significant)
689 ghc
= AHCI_Global_HBA_CONTROL_HR
;
690 StorPortWriteRegisterUlong(adapterExtension
, &abar
->GHC
, ghc
);
692 for (ticks
= 0; ticks
< 50; ++ticks
)
694 if ((StorPortReadRegisterUlong(adapterExtension
, &abar
->GHC
) & AHCI_Global_HBA_CONTROL_HR
) == 0)
698 StorPortStallExecution(20000);
701 if (ticks
== 50)// 1 second
703 DebugPrint("\tDevice Timeout\n");
708 }// -- AhciAdapterReset();
711 * @name AhciZeroMemory
714 * Clear buffer by filling zeros
722 __in ULONG bufferSize
726 for (i
= 0; i
< bufferSize
; i
++)
728 }// -- AhciZeroMemory();
734 * Tells wheather given port is implemented or not
736 * @param adapterExtension
740 * return TRUE if provided port is valid (implemented) or not
745 __in PAHCI_ADAPTER_EXTENSION adapterExtension
,
749 NT_ASSERT(pathId
>= 0);
751 if (pathId
>= MAXIMUM_AHCI_PORT_COUNT
)
756 return adapterExtension
->PortExtension
[pathId
].IsActive
;
760 * @name DeviceInquiryRequest
763 * Tells wheather given port is implemented or not
765 * @param adapterExtension
770 * return STOR status for DeviceInquiryRequest
773 * http://www.seagate.com/staticfiles/support/disc/manuals/Interface%20manuals/100293068c.pdf
776 DeviceInquiryRequest (
777 __in PAHCI_ADAPTER_EXTENSION adapterExtension
,
778 __in PSCSI_REQUEST_BLOCK Srb
,
783 ULONG DataBufferLength
;
785 DebugPrint("DeviceInquiryRequest()\n");
788 // If the EVPD bit is set to zero, the device server shall return the standard INQUIRY data
789 if (Cdb
->CDB6INQUIRY3
.EnableVitalProductData
== 0)
791 DebugPrint("\tEVPD Inquired\n");
795 DebugPrint("\tVPD Inquired\n");
797 DataBuffer
= Srb
->DataBuffer
;
798 DataBufferLength
= Srb
->DataTransferLength
;
800 if (DataBuffer
== NULL
)
801 return SRB_STATUS_INVALID_REQUEST
;
803 AhciZeroMemory(DataBuffer
, DataBufferLength
);
806 return SRB_STATUS_BAD_FUNCTION
;
807 }// -- DeviceInquiryRequest();