NTSTATUS LspReleaseLock( IN PLANSCSI_SESSION LSS, IN ULONG LockNo, IN PBYTE LockData, IN PLARGE_INTEGER TimeOut ){ NTSTATUS status; LANSCSI_PDUDESC pduDesc; BYTE pduResponse; if(LSS->HWProtoVersion <= LSIDEPROTO_VERSION_1_0) { NDAS_ASSERT( FALSE ); return STATUS_NOT_SUPPORTED; } pduResponse = LANSCSI_RESPONSE_SUCCESS; RtlZeroMemory(&pduDesc, sizeof(LANSCSI_PDUDESC)); pduDesc.Command = VENDOR_OP_FREE_MUTEX; pduDesc.Param8[3] = (UCHAR)LockNo; pduDesc.TimeOut = IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut); status = LspVendorRequest( LSS, &pduDesc, &pduResponse ); if(NT_SUCCESS(status)) { if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Releasing lock #%u denied by NDAS device\n", LockNo)); status = STATUS_LOCK_NOT_GRANTED; } else { KDPrintM(DBG_LURN_TRACE, ("Released lock #%u\n", LockNo)); } // // Convert Network endian to the host endian here. // if(LockData) { UINT32 lockData = NTOHL(pduDesc.Param32[1]); // // NDAS chip 1.1 returns the increased lock counter. // Decrease it for the chip version abstraction. // if(LSS->HWVersion == LANSCSIIDE_VERSION_1_1) { lockData --; } if(LSS->HWProtoVersion == LSIDEPROTO_VERSION_1_1) { *(PUINT32)LockData = lockData; } } } return status; }
////////////////////////////////////////////////////////////////////////// // // NDAS device lock control // NTSTATUS LspAcquireLock( IN PLANSCSI_SESSION LSS, IN ULONG LockNo, OUT PBYTE LockData, IN PLARGE_INTEGER TimeOut ){ NTSTATUS status; LANSCSI_PDUDESC pduDesc; BYTE pduResponse; NDASSCSI_ASSERT( TimeOut == NULL || TimeOut->QuadPart <= 0 ); if(LSS->HWProtoVersion <= LSIDEPROTO_VERSION_1_0) { return STATUS_NOT_SUPPORTED; } pduResponse = LANSCSI_RESPONSE_SUCCESS; RtlZeroMemory(&pduDesc, sizeof(LANSCSI_PDUDESC)); pduDesc.Command = VENDOR_OP_SET_MUTEX; pduDesc.Param8[3] = (UCHAR)LockNo; pduDesc.TimeOut = IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut); if (pduDesc.TimeOut && pduDesc.TimeOut->QuadPart == 0) { pduDesc.TimeOut = IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, NULL); }; status = LspVendorRequest( LSS, &pduDesc, &pduResponse ); if(NT_SUCCESS(status)) { if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_TRACE, ("Acquiring lock #%u denied by NDAS device\n", LockNo)); status = STATUS_LOCK_NOT_GRANTED; } else { KDPrintM(DBG_LURN_TRACE, ("Acquired lock #%u\n", LockNo)); } // // Convert Network endian to the host endian here. // if(LockData) { if(LSS->HWProtoVersion == LSIDEPROTO_VERSION_1_1) { *(PUINT32)LockData = NTOHL(pduDesc.Param32[1]); } } } return status; }
NTSTATUS LspGetLockData( IN PLANSCSI_SESSION LSS, IN ULONG LockNo, IN PBYTE LockData, IN PLARGE_INTEGER TimeOut ){ NTSTATUS status; LANSCSI_PDUDESC pduDesc; BYTE pduResponse; NDASSCSI_ASSERT( TimeOut == NULL || TimeOut->QuadPart < 0 ); if(LSS->HWProtoVersion <= LSIDEPROTO_VERSION_1_0) { return STATUS_NOT_SUPPORTED; } pduResponse = LANSCSI_RESPONSE_SUCCESS; RtlZeroMemory(&pduDesc, sizeof(LANSCSI_PDUDESC)); pduDesc.Command = VENDOR_OP_FREE_SEMA; pduDesc.Param64 = ((UINT64)(LockNo & 0x3)) << 32; // Lock number: 32~33 bit. pduDesc.TimeOut = IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut); status = LspVendorRequest( LSS, &pduDesc, &pduResponse ); if(NT_SUCCESS(status)) { if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Releasing lock #%u denied by NDAS device\n", LockNo)); status = STATUS_LOCK_NOT_GRANTED; } else { KDPrintM(DBG_LURN_TRACE, ("Lock data of lock #%u\n", LockNo)); } // // Convert Network endian to the host endian here. // if(LockData) { if(LSS->HWProtoVersion == LSIDEPROTO_VERSION_1_1) { *(PUINT32)LockData = NTOHL(pduDesc.Param32[1]); } } } return status; }
NTSTATUS LspGetLockOwner( IN PLANSCSI_SESSION LSS, IN ULONG LockNo, IN PBYTE LockOwner, IN PLARGE_INTEGER TimeOut ){ NTSTATUS status; LANSCSI_PDUDESC pduDesc; BYTE pduResponse; NDASSCSI_ASSERT( TimeOut == NULL || TimeOut->QuadPart < 0 ); if(LSS->HWProtoVersion <= LSIDEPROTO_VERSION_1_0) { return STATUS_NOT_SUPPORTED; } pduResponse = LANSCSI_RESPONSE_SUCCESS; RtlZeroMemory(&pduDesc, sizeof(LANSCSI_PDUDESC)); pduDesc.Command = VENDOR_OP_OWNER_SEMA; pduDesc.Param64 = ((UINT64)(LockNo & 0x3)) << 32; // Lock number: 32~33 bit. pduDesc.TimeOut = IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut); status = LspVendorRequest( LSS, &pduDesc, &pduResponse ); if(NT_SUCCESS(status)) { if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Get owner of lock #%u denied by NDAS device\n", LockNo)); status = STATUS_LOCK_NOT_GRANTED; } else { KDPrintM(DBG_LURN_TRACE, ("owner #%u\n", LockNo)); } RtlCopyMemory(LockOwner, &pduDesc.Param64, 8); } return status; }
NTSTATUS LspReleaseLock( PLANSCSI_SESSION LSS, UCHAR LockNo, PUINT32 LockCount ){ NTSTATUS status; LANSCSI_PDUDESC pduDesc; BYTE pduResponse; if(LSS->HWProtoVersion <= LSIDEPROTO_VERSION_1_0) { return STATUS_NOT_SUPPORTED; } pduResponse = LANSCSI_RESPONSE_SUCCESS; RtlZeroMemory(&pduDesc, sizeof(LANSCSI_PDUDESC)); pduDesc.Command = VENDOR_OP_FREE_SEMA; pduDesc.Param64 = ((UINT64)(LockNo & 0x3)) << 32; // Lock number: 32~33 bit. status = LspVendorRequest( LSS, &pduDesc, &pduResponse ); if(NT_SUCCESS(status)) { KDPrintM(DBG_LURN_TRACE, ("Released lock #%u\n", LockNo)); if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Releasing lock #%u denied by NDAS device\n", LockNo)); status = STATUS_WAS_LOCKED; } if(LockCount) *LockCount = NTOHL(pduDesc.Param32[1]); } return status; }
////////////////////////////////////////////////////////////////////////// // // NDAS device lock control // NTSTATUS LspAcquireLock( PLANSCSI_SESSION LSS, UCHAR LockNo, PUINT32 LockCount ){ NTSTATUS status; LANSCSI_PDUDESC pduDesc; BYTE pduResponse; if(LSS->HWProtoVersion <= LSIDEPROTO_VERSION_1_0) { return STATUS_NOT_SUPPORTED; } pduResponse = LANSCSI_RESPONSE_SUCCESS; RtlZeroMemory(&pduDesc, sizeof(LANSCSI_PDUDESC)); pduDesc.Command = VENDOR_OP_SET_MUTEX; pduDesc.Param8[3] = (UCHAR)LockNo; status = LspVendorRequest( LSS, &pduDesc, &pduResponse ); if(NT_SUCCESS(status)) { KDPrintM(DBG_LURN_TRACE, ("Acquired lock #%u\n", LockNo)); if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Acquiring lock #%u denied by NDAS device\n", LockNo)); status = STATUS_WAS_LOCKED; } if(LockCount) *LockCount = NTOHL(pduDesc.Param32[1]); } return status; }
NTSTATUS LspWorkaroundCleanupLock( PLANSCSI_SESSION LSS, ULONG LockNo, PLARGE_INTEGER TimeOut ){ NTSTATUS status; LONG i; LANSCSI_PDUDESC pduDesc; BYTE pduResponse; PLANSCSI_SESSION tempLSS; LONG maxConn; UCHAR bindingBuffer[(FIELD_OFFSET(TA_ADDRESS, Address) + TDI_ADDRESS_LENGTH_LPX)]; UCHAR targetBuffer[(FIELD_OFFSET(TA_ADDRESS, Address) + TDI_ADDRESS_LENGTH_LPX)]; PTA_ADDRESS BindingAddress = (PTA_ADDRESS)bindingBuffer; PTA_ADDRESS TargetAddress = (PTA_ADDRESS)targetBuffer; LSSLOGIN_INFO loginInfo; LSPROTO_TYPE LSProto; ULONG cleaned; // // Parameter check // // Perform clean-up only for NDAS 2.0 rev 0. // if((LSS->HWVersion == LANSCSIIDE_VERSION_2_0 && LSS->HWRevision == LANSCSIIDE_VER20_REV_1G_ORIGINAL)) { // Get maximum connections excluding the current session/connection. maxConn = LANSCSIIDE_MAX_CONNECTION_VER11 - 1; } else { return STATUS_SUCCESS; } tempLSS = ExAllocatePoolWithTag( NonPagedPool, maxConn * sizeof(LANSCSI_SESSION), LSS_POOLTAG); if(tempLSS == NULL) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(tempLSS, maxConn * sizeof(LANSCSI_SESSION)); // // Init variables // status = STATUS_SUCCESS; RtlZeroMemory(&pduDesc, sizeof(LANSCSI_PDUDESC)); pduDesc.Param8[3] = (UCHAR)LockNo; pduDesc.TimeOut = IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut); LspGetAddresses(LSS, BindingAddress, TargetAddress); cleaned = 0; // // Try to make connections to fill up connection pool of the NDAS device. // So, we can clear invalid acquisition of the locks. // KDPrintM(DBG_LURN_ERROR,("Try to clean up lock\n")); for (i=0 ; i < maxConn; i++) { tempLSS[i].DefaultTimeOut.QuadPart = IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut)->QuadPart; // // Connect and log in with read-only access. // // connect status = LspConnect( &tempLSS[i], BindingAddress, TargetAddress, NULL, NULL, NULL, NULL ); if(!NT_SUCCESS(status)) { KDPrintM(DBG_LURN_ERROR, ("LspConnect(), Can't Connect to the LS node. STATUS:0x%08x\n", status)); break; } } for (i=0; i < maxConn; i++) { if(!LspIsConnected(&tempLSS[i])) { continue; } KDPrintM(DBG_LURN_TRACE, ("Con#%u\n", i)); cleaned++; // extract login information from the existing LSS. LspBuildLoginInfo(LSS, &loginInfo); status = LspLookupProtocol(loginInfo.HWType, loginInfo.HWVersion, &LSProto); if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("Wrong hardware version.\n")); continue; } // Log in with read-only access. loginInfo.UserID &= 0x0000ffff; status = LspLogin( &tempLSS[i], &loginInfo, LSProto, NULL, FALSE ); if(!NT_SUCCESS(status)) { KDPrintM(DBG_LURN_ERROR, ("LspLogin() failed. STATUS:0x%08x\n", status)); LspDisconnect(&tempLSS[i]); continue; } // Do need to acquire the lock to release. // NDAS chip 2.0 original allow to release the lock // regardless of the ownership if the connection number // in the lock information of NDAS chip 2.0 // is same. #if 0 // // Acquire the lock on the NDAS device. // pduDesc.Command = VENDOR_OP_SET_MUTEX; status = LspVendorRequest( &tempLSS[i], &pduDesc, &pduResponse ); if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Acquiring lock #%u denied by NDAS device\n", LockNo)); } if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("LspVendorRequest() failed. STATUS=%08lx\n", status)); continue; } #endif // // Release the lock on the NDAS device. // pduDesc.Command = VENDOR_OP_FREE_MUTEX; status = LspVendorRequest( &tempLSS[i], &pduDesc, &pduResponse ); if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Releasing lock #%u denied by NDAS device\n", LockNo)); } if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("LspVendorRequest() failed. STATUS=%08lx\n", status)); continue; } // // Log out and disconnect. // LspLogout( &tempLSS[i], NULL ); LspDisconnect( &tempLSS[i] ); // // Init PDU // pduDesc.Retransmits = 0; pduDesc.PacketLoss = 0; } KDPrintM(DBG_LURN_INFO, ("Cleaned #%u\n", cleaned)); ExFreePool(tempLSS); return status; }
NTSTATUS LspCleanupLock( PLANSCSI_SESSION LSS, UCHAR LockNo ){ NTSTATUS status; LONG i; LANSCSI_PDUDESC pduDesc; BYTE pduResponse; PLANSCSI_SESSION tempLSS; LONG maxConn; LARGE_INTEGER GenericTimeOut; TA_LSTRANS_ADDRESS BindingAddress, TargetAddress; LSSLOGIN_INFO loginInfo; LSPROTO_TYPE LSProto; ULONG cleaned; // // Parameter check // if(LSS->HWProtoVersion <= LSIDEPROTO_VERSION_1_0) { return STATUS_NOT_SUPPORTED; } if(LSS->HWVersion >= 1) { maxConn = LANSCSIIDE_MAX_CONNECTION_VER11 - 1; } else { return STATUS_NOT_SUPPORTED; } tempLSS = ExAllocatePoolWithTag( NonPagedPool, maxConn * sizeof(LANSCSI_SESSION), LSS_POOLTAG); RtlZeroMemory(tempLSS, maxConn * sizeof(LANSCSI_SESSION)); // // Init variables // status = STATUS_SUCCESS; RtlZeroMemory(&pduDesc, sizeof(LANSCSI_PDUDESC)); pduDesc.Param64 = ((UINT64)(LockNo & 0x3)) << 32; // Lock number: 32~33 bit. LspGetAddresses(LSS, &BindingAddress, &TargetAddress); GenericTimeOut.QuadPart = NANO100_PER_SEC * 5; cleaned = 0; // // Try to make connections to fill up connection pool of the NDAS device. // So, we can clear invalid acquisition of the locks. // KDPrintM(DBG_LURN_ERROR,("Try to clean up lock\n")); for (i=0 ; i < maxConn; i++) { // // Connect and log in with read-only access. // // connect LspSetTimeOut(&tempLSS[i], &GenericTimeOut); status = LspConnect( &tempLSS[i], &BindingAddress, &TargetAddress ); if(!NT_SUCCESS(status)) { KDPrintM(DBG_LURN_ERROR, ("LspConnect(), Can't Connect to the LS node. STATUS:0x%08x\n", status)); break; } } for (i=0; i < maxConn; i++) { if(!LspIsConnected(&tempLSS[i])) { continue; } KDPrintM(DBG_LURN_TRACE, ("Con#%u\n", i)); cleaned++; // extract login information from the existing LSS. LspBuildLoginInfo(LSS, &loginInfo); status = LspLookupProtocol(loginInfo.HWType, loginInfo.HWVersion, &LSProto); if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("Wrong hardware version.\n")); continue; } // Log in with read-only access. loginInfo.UserID &= 0x0000ffff; status = LspLogin( &tempLSS[i], &loginInfo, LSProto, FALSE ); if(!NT_SUCCESS(status)) { KDPrintM(DBG_LURN_ERROR, ("LspLogin() failed. STATUS:0x%08x\n", status)); LspDisconnect(&tempLSS[i]); ASSERT(FALSE); continue; } // // Acquire the lock on the NDAS device. // pduDesc.Command = VENDOR_OP_SET_SEMA; status = LspVendorRequest( &tempLSS[i], &pduDesc, &pduResponse ); if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Acquiring lock #%u denied by NDAS device\n", LockNo)); } if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("LspVendorRequest() failed. STATUS=%08lx\n", status)); continue; } // // Release the lock on the NDAS device. // pduDesc.Command = VENDOR_OP_FREE_SEMA; status = LspVendorRequest( &tempLSS[i], &pduDesc, &pduResponse ); if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Releasing lock #%u denied by NDAS device\n", LockNo)); } if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("LspVendorRequest() failed. STATUS=%08lx\n", status)); continue; } // // Log out and disconnect. // LspLogout( &tempLSS[i] ); LspDisconnect( &tempLSS[i] ); } KDPrintM(DBG_LURN_INFO, ("Cleaned #%u\n", cleaned)); ExFreePool(tempLSS); return status; }