//*************************************************************************** // // method.c // // Module: Windows HBA API implmentation // // Purpose: Contains routines for doing things // // Copyright (c) 2001 Microsoft Corporation // //*************************************************************************** #include "hbaapip.h" HBA_STATUS HBA_GetDiscoveredPortAttributesX( HBA_HANDLE HbaHandle, HBA_UINT32 PortIndex, HBA_UINT32 DiscoveredPortIndex, HBA_PORTATTRIBUTES *HbaPortAttributes, BOOLEAN IsAnsi ) { HANDLE Handle; PADAPTER_HANDLE HandleData; ULONG Status; HBA_STATUS HbaStatus = HBA_STATUS_ERROR; PUCHAR Buffer; ULONG DataLength; GetDiscoveredPortAttributes_IN InData; PGetDiscoveredPortAttributes_OUT OutData; HandleData = GetDataByHandle(HbaHandle); if (HandleData != NULL) { Status = WmiOpenBlock((LPGUID)&MSFC_HBAPortMethods_GUID, GENERIC_READ | GENERIC_EXECUTE, &Handle); if (Status == ERROR_SUCCESS) { DataLength = sizeof(GetDiscoveredPortAttributes_OUT); Buffer = AllocMemory(DataLength); if (Buffer != NULL) { InData.PortIndex = PortIndex; InData.DiscoveredPortIndex = DiscoveredPortIndex; OutData = (PGetDiscoveredPortAttributes_OUT)Buffer; Status = WmiExecuteMethodW(Handle, HandleData->InstanceName, GetDiscoveredPortAttributes, sizeof(GetDiscoveredPortAttributes_IN), &InData, &DataLength, OutData); if (Status == ERROR_SUCCESS) { // // Copy port attribs from buffer into // // // Get the HBA status returned from the miniport. // If the status is HBA_STATUS_OK then the miniport // has successfully completed the operation and has // returned results to us. If the status is not // HBA_STATUS_OK then the miniport is returning an // HBA api error which we will in turn return to // the caller. In this case the additional results // are not valid. // HbaStatus = OutData->HBAStatus; if (HbaStatus == HBA_STATUS_OK) { CopyPortAttributes(HbaPortAttributes, (PUCHAR)&OutData->PortAttributes, IsAnsi); } } FreeMemory(Buffer); } WmiCloseBlock(Handle); } } return(HbaStatus); } HBA_STATUS HBA_API HBA_GetDiscoveredPortAttributes( HBA_HANDLE HbaHandle, HBA_UINT32 PortIndex, HBA_UINT32 DiscoveredPortIndex, HBA_PORTATTRIBUTES *HbaPortAttribute ) { return(HBA_GetDiscoveredPortAttributesX(HbaHandle, PortIndex, DiscoveredPortIndex, HbaPortAttribute, TRUE)); } HBA_STATUS HBA_GetPortAttributesByWWNX( HBA_HANDLE HbaHandle, HBA_WWN PortWWN, HBA_PORTATTRIBUTES *HbaPortAttributes, BOOLEAN IsAnsi ) { HANDLE Handle; PADAPTER_HANDLE HandleData; ULONG Status; HBA_STATUS HbaStatus = HBA_STATUS_ERROR; PUCHAR Buffer; ULONG DataLength; PGetPortAttributesByWWN_IN InData; PGetPortAttributesByWWN_OUT OutData; HandleData = GetDataByHandle(HbaHandle); if (HandleData != NULL) { Status = WmiOpenBlock((LPGUID)&MSFC_HBAPortMethods_GUID, GENERIC_READ | GENERIC_EXECUTE, &Handle); if (Status == ERROR_SUCCESS) { DataLength = sizeof(GetPortAttributesByWWN_OUT); Buffer = (PUCHAR)AllocMemory(DataLength); if (Buffer != NULL) { InData = (PGetPortAttributesByWWN_IN)&PortWWN; OutData = (PGetPortAttributesByWWN_OUT)Buffer; Status = WmiExecuteMethodW(Handle, HandleData->InstanceName, GetPortAttributesByWWN, sizeof(GetPortAttributesByWWN_IN), InData, &DataLength, OutData); if (Status == ERROR_SUCCESS) { // // Copy port attribs from buffer into // // // Get the HBA status returned from the miniport. // If the status is HBA_STATUS_OK then the miniport // has successfully completed the operation and has // returned results to us. If the status is not // HBA_STATUS_OK then the miniport is returning an // HBA api error which we will in turn return to // the caller. In this case the additional results // are not valid. // HbaStatus = OutData->HBAStatus; if (HbaStatus == HBA_STATUS_OK) { CopyPortAttributes(HbaPortAttributes, (PUCHAR)&OutData->PortAttributes, IsAnsi); } } FreeMemory(Buffer); } WmiCloseBlock(Handle); } } return(HbaStatus); } HBA_STATUS HBA_API HBA_GetPortAttributesByWWN( HBA_HANDLE HbaHandle, HBA_WWN PortWWN, HBA_PORTATTRIBUTES *HbaPortAttributes ) { return(HBA_GetPortAttributesByWWNX(HbaHandle, PortWWN, HbaPortAttributes, TRUE)); } HBA_STATUS HBA_API HBA_SendCTPassThru( HBA_HANDLE HbaHandle, void * pReqBuffer, HBA_UINT32 ReqBufferSize, void * pRspBuffer, HBA_UINT32 RspBufferSize ) { HANDLE Handle; PADAPTER_HANDLE HandleData; ULONG Status; HBA_STATUS HbaStatus = HBA_STATUS_ERROR; PUCHAR Buffer; ULONG DataLength, InDataLength, OutDataLength; PSendCTPassThru_OUT OutData; PSendCTPassThru_IN InData; HandleData = GetDataByHandle(HbaHandle); if (HandleData != NULL) { Status = WmiOpenBlock((LPGUID)&MSFC_HBAFc3MgmtMethods_GUID, GENERIC_READ | GENERIC_EXECUTE, &Handle); if (Status == ERROR_SUCCESS) { if (ReqBufferSize > RspBufferSize) { DataLength = ReqBufferSize; } else { DataLength = RspBufferSize; } DataLength += sizeof(SendCTPassThru_OUT); Buffer = AllocMemory(DataLength); if (Buffer != NULL) { InData = (PSendCTPassThru_IN)Buffer; OutData = (PSendCTPassThru_OUT)Buffer; InDataLength = sizeof(SendCTPassThru_IN) + ReqBufferSize - 1; InData->RequestBufferCount = ReqBufferSize; memcpy(InData->RequestBuffer, pReqBuffer, ReqBufferSize); OutDataLength = sizeof(SendCTPassThru_OUT) + RspBufferSize - 1; Status = WmiExecuteMethodW(Handle, HandleData->InstanceName, SendCTPassThru, InDataLength, InData, &OutDataLength, OutData); if (Status == ERROR_SUCCESS) { if (OutData->ResponseBufferCount <= RspBufferSize) { RspBufferSize = OutData->ResponseBufferCount; } else { DebugPrint(("HBAAPI: Response size from SendCTPass is %d and is larger than %d\n", OutData->ResponseBufferCount, RspBufferSize)); } // // Get the HBA status returned from the miniport. // If the status is HBA_STATUS_OK then the miniport // has successfully completed the operation and has // returned results to us. If the status is not // HBA_STATUS_OK then the miniport is returning an // HBA api error which we will in turn return to // the caller. In this case the additional results // are not valid. // HbaStatus = OutData->HBAStatus; if ((HbaStatus == HBA_STATUS_OK) || (HbaStatus == HBA_STATUS_ERROR_MORE_DATA)) { memcpy(pRspBuffer, OutData->ResponseBuffer, RspBufferSize); } } FreeMemory(Buffer); } WmiCloseBlock(Handle); } } return(HbaStatus); } HBA_STATUS HBA_API HBA_SendRNID( HBA_HANDLE HbaHandle, HBA_WWN wwn, HBA_WWNTYPE wwntype, void * pRspBuffer, HBA_UINT32 *RspBufferSize ) { HANDLE Handle; PADAPTER_HANDLE HandleData; ULONG Status; HBA_STATUS HbaStatus = HBA_STATUS_ERROR; PUCHAR Buffer; ULONG DataLength; SendRNID_IN InData; PSendRNID_OUT OutData; HandleData = GetDataByHandle(HbaHandle); if (HandleData != NULL) { Status = WmiOpenBlock((LPGUID)&MSFC_HBAFc3MgmtMethods_GUID, GENERIC_READ | GENERIC_EXECUTE, &Handle); if (Status == ERROR_SUCCESS) { DataLength = sizeof(SendRNID_OUT) -1 + *RspBufferSize; Buffer = AllocMemory(DataLength); if (Buffer != NULL) { memcpy(InData.wwn, &wwn.wwn, sizeof(HBA_WWN)); InData.wwntype = (ULONG)wwntype; OutData = (PSendRNID_OUT)Buffer; Status = WmiExecuteMethodW(Handle, HandleData->InstanceName, SendRNID, sizeof(SendRNID_IN), &InData, &DataLength, OutData); if (Status == ERROR_SUCCESS) { // // Get the HBA status returned from the miniport. // If the status is HBA_STATUS_OK then the miniport // has successfully completed the operation and has // returned results to us. If the status is not // HBA_STATUS_OK then the miniport is returning an // HBA api error which we will in turn return to // the caller. In this case the additional results // are not valid. // HbaStatus = OutData->HBAStatus; if ((HbaStatus == HBA_STATUS_OK) || (HbaStatus == HBA_STATUS_ERROR_MORE_DATA)) { if (OutData->ResponseBufferCount <= *RspBufferSize) { *RspBufferSize = OutData->ResponseBufferCount; } else { DebugPrint(("HBAAPI: Response size from SendRNID is %d and is larger than %d\n", OutData->ResponseBufferCount, *RspBufferSize)); } memcpy(pRspBuffer, OutData->ResponseBuffer, *RspBufferSize); } } FreeMemory(Buffer); } WmiCloseBlock(Handle); } } return(HbaStatus); } _inline void CopyScsiId( PHBA_SCSIID HbaScsiId, PHBAScsiID WmiScsiId, BOOLEAN IsAnsi ) { PUCHAR p; p = (PUCHAR)WmiScsiId->OSDeviceName; CopyString(HbaScsiId->OSDeviceName, &p, 256, IsAnsi); HbaScsiId->ScsiBusNumber = WmiScsiId->ScsiBusNumber; HbaScsiId->ScsiTargetNumber = WmiScsiId->ScsiTargetNumber; HbaScsiId->ScsiOSLun = WmiScsiId->ScsiOSLun; } _inline void CopyFcpId( PHBA_FCPID HbaFcpId, PHBAFCPID WmiFcpId ) { HbaFcpId->FcId = WmiFcpId->Fcid; HbaFcpId->FcpLun = WmiFcpId->FcpLun; memcpy(&HbaFcpId->NodeWWN, &WmiFcpId->NodeWWN, sizeof(HBA_WWN)); memcpy(&HbaFcpId->PortWWN, &WmiFcpId->PortWWN, sizeof(HBA_WWN)); } HBA_STATUS HBA_GetFcpTargetMappingX ( HBA_HANDLE HbaHandle, PHBA_FCPTARGETMAPPING Mapping, BOOLEAN IsAnsi ) { HANDLE Handle; PADAPTER_HANDLE HandleData; ULONG Status; HBA_STATUS HbaStatus = HBA_STATUS_ERROR; ULONG DataLength; PGetFcpTargetMapping_OUT OutData; ULONG MapCount, ActualCount, i; PHBA_FCPSCSIENTRY MapEntry; PHBAFCPScsiEntry OutEntry; HandleData = GetDataByHandle(HbaHandle); if (HandleData != NULL) { Status = WmiOpenBlock((LPGUID)&(MSFC_HBAFCPInfo_GUID), GENERIC_READ | GENERIC_EXECUTE, &Handle); if (Status == ERROR_SUCCESS) { Status = ExecuteMethod(Handle, HandleData->InstanceName, GetFcpTargetMapping, 0, NULL, &DataLength, (PUCHAR *)&OutData); if (Status == ERROR_SUCCESS) { // // Get the HBA status returned from the miniport. // If the status is HBA_STATUS_OK then the miniport // has successfully completed the operation and has // returned results to us. If the status is not // HBA_STATUS_OK then the miniport is returning an // HBA api error which we will in turn return to // the caller. In this case the additional results // are not valid. // HbaStatus = OutData->HBAStatus; if (HbaStatus == HBA_STATUS_OK) { MapCount = Mapping->NumberOfEntries; ActualCount = OutData->EntryCount; Mapping->NumberOfEntries = ActualCount; if (MapCount > ActualCount) { MapCount = ActualCount; HbaStatus = HBA_STATUS_ERROR_MORE_DATA; } for (i = 0; i < MapCount; i++) { MapEntry = &Mapping->entry[i]; OutEntry = &OutData->Entry[i]; CopyScsiId(&MapEntry->ScsiId, &OutEntry->ScsiId, IsAnsi); CopyFcpId(&MapEntry->FcpId, &OutEntry->FCPId); } } FreeMemory(OutData); } WmiCloseBlock(Handle); } } return(HbaStatus); } HBA_STATUS HBA_API HBA_GetFcpTargetMapping ( HBA_HANDLE HbaHandle, PHBA_FCPTARGETMAPPING Mapping ) { return(HBA_GetFcpTargetMappingX(HbaHandle, Mapping, TRUE)); } HBA_STATUS HBA_GetFcpPersistentBindingX ( HBA_HANDLE HbaHandle, PHBA_FCPBINDING binding, BOOLEAN IsAnsi ) { HANDLE Handle; PADAPTER_HANDLE HandleData; ULONG Status; HBA_STATUS HbaStatus = HBA_STATUS_ERROR; ULONG DataLength; PGetFcpPersistentBinding_OUT OutData; ULONG MapCount, ActualCount, i; PHBA_FCPBINDINGENTRY MapEntry; PHBAFCPBindingEntry OutEntry; HandleData = GetDataByHandle(HbaHandle); if (HandleData != NULL) { Status = WmiOpenBlock((LPGUID)&MSFC_HBAFCPInfo_GUID, GENERIC_READ | GENERIC_EXECUTE, &Handle); if (Status == ERROR_SUCCESS) { Status = ExecuteMethod(Handle, HandleData->InstanceName, GetFcpTargetMapping, 0, NULL, &DataLength, (PUCHAR *)&OutData); if (Status == ERROR_SUCCESS) { // // Get the HBA status returned from the miniport. // If the status is HBA_STATUS_OK then the miniport // has successfully completed the operation and has // returned results to us. If the status is not // HBA_STATUS_OK then the miniport is returning an // HBA api error which we will in turn return to // the caller. In this case the additional results // are not valid. // HbaStatus = OutData->HBAStatus; if (HbaStatus == HBA_STATUS_OK) { MapCount = binding->NumberOfEntries; ActualCount = OutData->EntryCount; binding->NumberOfEntries = ActualCount; if (MapCount > ActualCount) { MapCount = ActualCount; HbaStatus = HBA_STATUS_ERROR_MORE_DATA; } for (i = 0; i < MapCount; i++) { MapEntry = &binding->entry[i]; OutEntry = &OutData->Entry[i]; MapEntry->type = OutEntry->Type; CopyScsiId(&MapEntry->ScsiId, &OutEntry->ScsiId, IsAnsi); CopyFcpId(&MapEntry->FcpId, &OutEntry->FCPId); } } FreeMemory(OutData); } WmiCloseBlock(Handle); } } return(HbaStatus); } HBA_STATUS HBA_API HBA_GetFcpPersistentBinding ( HBA_HANDLE handle, PHBA_FCPBINDING binding ) { return(HBA_GetFcpPersistentBindingX(handle, binding, TRUE)); } void HBA_API HBA_ResetStatistics( HBA_HANDLE HbaHandle, HBA_UINT32 PortIndex ) { HANDLE Handle; PADAPTER_HANDLE HandleData; ULONG Status; PWCHAR InstanceName; ULONG DataLength; HandleData = GetDataByHandle(HbaHandle); if (HandleData != NULL) { Status = WmiOpenBlock((LPGUID)&MSFC_FibrePortHBAMethods_GUID, GENERIC_READ | GENERIC_EXECUTE, &Handle); if (Status == ERROR_SUCCESS) { InstanceName = CreatePortInstanceNameW(HandleData->InstanceName, PortIndex); if (InstanceName != NULL) { DataLength = 0; Status = WmiExecuteMethodW(Handle, InstanceName, ResetStatistics, 0, NULL, &DataLength, NULL); #if DBG if (Status != ERROR_SUCCESS) { DebugPrint(("HBAAPI: ResetStatistics method failed %d\n", Status)); } #endif FreeMemory(InstanceName); } WmiCloseBlock(Handle); } } } HBA_STATUS HBA_API HBA_SetRNIDMgmtInfo( HBA_HANDLE HbaHandle, HBA_MGMTINFO *HbaMgmtInfo ) { HANDLE Handle; PADAPTER_HANDLE HandleData; ULONG Status; HBA_STATUS HbaStatus = HBA_STATUS_ERROR; ULONG DataLength; SetFC3MgmtInfo_IN InData; SetFC3MgmtInfo_OUT OutData; HandleData = GetDataByHandle(HbaHandle); if (HandleData != NULL) { Status = WmiOpenBlock((LPGUID)&MSFC_HBAFc3MgmtMethods_GUID, GENERIC_EXECUTE, &Handle); if (Status == ERROR_SUCCESS) { // // We have got our Management info, so copy them // over to the input buffer // memcpy(InData.MgmtInfo.wwn, &HbaMgmtInfo->wwn, sizeof(HBA_WWN)); InData.MgmtInfo.unittype = HbaMgmtInfo->unittype; InData.MgmtInfo.PortId = HbaMgmtInfo->PortId; InData.MgmtInfo.NumberOfAttachedNodes = HbaMgmtInfo->NumberOfAttachedNodes; InData.MgmtInfo.IPVersion = HbaMgmtInfo->IPVersion; InData.MgmtInfo.UDPPort = HbaMgmtInfo->UDPPort; memcpy(InData.MgmtInfo.IPAddress, HbaMgmtInfo->IPAddress, 16); InData.MgmtInfo.reserved = HbaMgmtInfo->reserved; InData.MgmtInfo.TopologyDiscoveryFlags = HbaMgmtInfo->TopologyDiscoveryFlags; DataLength = sizeof(SetFC3MgmtInfo_OUT); Status = WmiExecuteMethodW(Handle, HandleData->InstanceName, SetFC3MgmtInfo, sizeof(SetFC3MgmtInfo_IN), &InData, &DataLength, &OutData); if (Status == ERROR_SUCCESS) { // // Get the HBA status returned from the miniport. // If the miniport returns HBA_STATUS_OK then all // data is filled in the data block. If any other // HBA status is returned then the miniport is // reporting an error and we want to return that // HBA error code to the caller // HbaStatus = OutData.HBAStatus; } WmiCloseBlock(Handle); } } else { HbaStatus = HBA_STATUS_ERROR_INVALID_HANDLE; } return(HbaStatus); } HBA_STATUS HBA_API HBA_GetRNIDMgmtInfo( HBA_HANDLE HbaHandle, HBA_MGMTINFO *HbaMgmtInfo ) { HANDLE Handle; PADAPTER_HANDLE HandleData; ULONG Status; HBA_STATUS HbaStatus = HBA_STATUS_ERROR; ULONG DataLength; GetFC3MgmtInfo_OUT OutData; HandleData = GetDataByHandle(HbaHandle); if (HandleData != NULL) { Status = WmiOpenBlock((LPGUID)&MSFC_HBAFc3MgmtMethods_GUID, GENERIC_EXECUTE, &Handle); if (Status == ERROR_SUCCESS) { DataLength = sizeof(GetFC3MgmtInfo_OUT); Status = WmiExecuteMethodW(Handle, HandleData->InstanceName, GetFC3MgmtInfo, 0, NULL, &DataLength, &OutData); if (Status == ERROR_SUCCESS) { // // Get the HBA status returned from the miniport. // If the miniport returns HBA_STATUS_OK then all // data is filled in the data block. If any other // HBA status is returned then the miniport is // reporting an error and we want to return that // HBA error code to the caller // HbaStatus = OutData.HBAStatus; if (HbaStatus == HBA_STATUS_OK) { // // We have got our Management info, so copy them // over to the output buffer // memcpy(&HbaMgmtInfo->wwn, OutData.MgmtInfo.wwn, sizeof(HBA_WWN)); HbaMgmtInfo->unittype = OutData.MgmtInfo.unittype; HbaMgmtInfo->PortId = OutData.MgmtInfo.PortId; HbaMgmtInfo->NumberOfAttachedNodes = OutData.MgmtInfo.NumberOfAttachedNodes; HbaMgmtInfo->IPVersion = OutData.MgmtInfo.IPVersion; HbaMgmtInfo->UDPPort = OutData.MgmtInfo.UDPPort; memcpy(HbaMgmtInfo->IPAddress, OutData.MgmtInfo.IPAddress, 16); HbaMgmtInfo->reserved = OutData.MgmtInfo.reserved; HbaMgmtInfo->TopologyDiscoveryFlags = OutData.MgmtInfo.TopologyDiscoveryFlags; } } WmiCloseBlock(Handle); } } else { HbaStatus = HBA_STATUS_ERROR_INVALID_HANDLE; } return(HbaStatus); } void HBA_API HBA_RefreshInformation( HBA_HANDLE HbaHandle ) { HANDLE Handle; PADAPTER_HANDLE HandleData; ULONG Status; ULONG DataLength; HandleData = GetDataByHandle(HbaHandle); if (HandleData != NULL) { Status = WmiOpenBlock((LPGUID)&MSFC_HBAPortMethods_GUID, GENERIC_READ | GENERIC_EXECUTE, &Handle); if (Status == ERROR_SUCCESS) { DataLength = 0; Status = WmiExecuteMethodW(Handle, HandleData->InstanceName, RefreshInformation, 0, NULL, &DataLength, NULL); #if DBG if (Status != ERROR_SUCCESS) { DebugPrint(("HBAAPI: RefreshInformation method failed %d\n", Status)); } #endif WmiCloseBlock(Handle); } } } // // Not implemented yet // HBA_STATUS HBA_API HBA_GetEventBuffer( HBA_HANDLE handle, PHBA_EVENTINFO EventBuffer, HBA_UINT32 *EventCount ) { return(HBA_STATUS_ERROR_NOT_SUPPORTED); } // // SCSI apis are not supported by design // HBA_STATUS HBA_API HBA_SendScsiInquiry ( HBA_HANDLE handle, HBA_WWN PortWWN, HBA_UINT64 fcLUN, HBA_UINT8 EVPD, HBA_UINT32 PageCode, void * pRspBuffer, HBA_UINT32 RspBufferSize, void * pSenseBuffer, HBA_UINT32 SenseBufferSize) { return(HBA_STATUS_ERROR_NOT_SUPPORTED); } HBA_STATUS HBA_API HBA_SendReportLUNs ( HBA_HANDLE handle, HBA_WWN portWWN, void * pRspBuffer, HBA_UINT32 RspBufferSize, void * pSenseBuffer, HBA_UINT32 SenseBufferSize ) { return(HBA_STATUS_ERROR_NOT_SUPPORTED); } HBA_STATUS HBA_API HBA_SendReadCapacity ( HBA_HANDLE handle, HBA_WWN portWWN, HBA_UINT64 fcLUN, void * pRspBuffer, HBA_UINT32 RspBufferSize, void * pSenseBuffer, HBA_UINT32 SenseBufferSize ) { return(HBA_STATUS_ERROR_NOT_SUPPORTED); }