// // Login with current LSS information // Assume LspReconnect is called before this call. // NTSTATUS LspRelogin( IN OUT PLANSCSI_SESSION LSS, IN BOOLEAN IsEncryptBuffer, IN PLARGE_INTEGER TimeOut ) { NTSTATUS ntStatus; LSSLOGIN_INFO LoginInfo; LSPROTO_TYPE LSProto; ASSERT(LSS); NDASSCSI_ASSERT( TimeOut == NULL || TimeOut->QuadPart < 0 ); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); LoginInfo.LoginType = LOGIN_TYPE_NORMAL; RtlCopyMemory(&LoginInfo.UserID, &LSS->UserID, LSPROTO_USERID_LENGTH); RtlCopyMemory(&LoginInfo.Password, &LSS->Password, LSPROTO_PASSWORD_LENGTH); LoginInfo.MaxDataTransferLength = LSS->MaxDataTransferLength; LoginInfo.LanscsiTargetID = LSS->LanscsiTargetID; LoginInfo.LanscsiLU = LSS->LanscsiLU; LoginInfo.HWType = LSS->HWType; LoginInfo.HWVersion = LSS->HWVersion; LoginInfo.HWRevision = LSS->HWRevision; LoginInfo.IsEncryptBuffer = IsEncryptBuffer; ntStatus = LspLookupProtocol(LSS->HWType, LSS->HWVersion, &LSProto); if( !NT_SUCCESS(ntStatus) ) { KDPrintM(DBG_PROTO_ERROR, ("HWVersion wrong.\n")); return STATUS_NOT_IMPLEMENTED; } // Make sure the LanScsiSession is logged out. (VOID)LspLogout(LSS,IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut)); ntStatus = LspLogin( LSS, &LoginInfo, LSProto, IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut), TRUE ); if(!NT_SUCCESS(ntStatus)) { LspDisconnect(LSS); goto cleanup; } cleanup: return ntStatus; }
// // Login with current LSS information // Assume LspReconnect is called before this call. // NTSTATUS LspRelogin( IN OUT PLANSCSI_SESSION LSS, IN BOOLEAN IsEncryptBuffer ) { NTSTATUS ntStatus; LSSLOGIN_INFO LoginInfo; LSPROTO_TYPE LSProto; ASSERT(LSS); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); LoginInfo.LoginType = LOGIN_TYPE_NORMAL; RtlCopyMemory(&LoginInfo.UserID, &LSS->UserID, LSPROTO_USERID_LENGTH); RtlCopyMemory(&LoginInfo.Password, &LSS->Password, LSPROTO_PASSWORD_LENGTH); RtlCopyMemory((PVOID)LoginInfo.Password_v2, (PVOID)LSS->Password_v2, LSPROTO_PASSWORD_V2_LENGTH); LoginInfo.MaxBlocksPerRequest = LSS->MaxBlocksPerRequest; LoginInfo.LanscsiTargetID = LSS->LanscsiTargetID; LoginInfo.LanscsiLU = LSS->LanscsiLU; LoginInfo.HWType = LSS->HWType; LoginInfo.HWVersion = LSS->HWVersion; LoginInfo.HWRevision = LSS->HWRevision; LoginInfo.IsEncryptBuffer = IsEncryptBuffer; LoginInfo.BlockInBytes = LSS->BlockInBytes; ntStatus = LspLookupProtocol(LSS->HWType, LSS->HWVersion, &LSProto); if(!NT_SUCCESS(ntStatus)) { KDPrintM(DBG_PROTO_ERROR, ("HWVersion wrong.\n")); return STATUS_NOT_IMPLEMENTED; } ntStatus = LspLogin( LSS, &LoginInfo, LSProto, TRUE ); if(!NT_SUCCESS(ntStatus)) { LstransDisconnect(&LSS->ConnectionFile, 0); LstransDisassociate(&LSS->ConnectionFile); LstransCloseConnection(&LSS->ConnectionFile); LstransCloseAddress(&LSS->AddressFile); goto cleanup; } cleanup: return ntStatus; }
NTSTATUS LspReconnectAndLogin( IN OUT PLANSCSI_SESSION LSS, IN LSTRANS_TYPE LstransType ) { NTSTATUS ntStatus; LSSLOGIN_INFO LoginInfo; LSPROTO_TYPE LSProto; ASSERT(LSS); LoginInfo.LoginType = LOGIN_TYPE_NORMAL; RtlCopyMemory(&LoginInfo.UserID, &LSS->UserID, LSPROTO_USERID_LENGTH); RtlCopyMemory(&LoginInfo.Password, &LSS->Password, LSPROTO_PASSWORD_LENGTH); LoginInfo.MaxBlocksPerRequest = LSS->MaxBlocksPerRequest; LoginInfo.LanscsiTargetID = LSS->LanscsiTargetID; LoginInfo.LanscsiLU = LSS->LanscsiLU; LoginInfo.HWType = LSS->HWType; LoginInfo.HWVersion = LSS->HWVersion; ntStatus = LspLookupProtocol(LSS->HWType, LSS->HWVersion, &LSProto); if(!NT_SUCCESS(ntStatus)) { KDPrintM(DBG_PROTO_ERROR, ("HWVersion wrong.\n")); return STATUS_NOT_IMPLEMENTED; } ntStatus = LstransOpenAddress(&LSS->SourceAddress, &LSS->AddressFile); if( !NT_SUCCESS(ntStatus) ) { goto cleanup; } ntStatus = LstransOpenConnection(NULL, LstransType, &LSS->ConnectionFile); if( !NT_SUCCESS(ntStatus) ) { LstransCloseAddress(&LSS->AddressFile); goto cleanup; } ntStatus = LstransAssociate(&LSS->AddressFile, &LSS->ConnectionFile); if( !NT_SUCCESS(ntStatus) ) { LstransCloseConnection(&LSS->ConnectionFile); LstransCloseAddress(&LSS->AddressFile); goto cleanup; } ntStatus = LstransConnect(&LSS->ConnectionFile, &LSS->LSNodeAddress, &LSS->TimeOuts[0]); if( !NT_SUCCESS(ntStatus) ) { LstransDisassociate(&LSS->ConnectionFile); LstransCloseConnection(&LSS->ConnectionFile); LstransCloseAddress(&LSS->AddressFile); goto cleanup; } /* ntStatus = LstransRegisterDisconnectHandler( &LSS->AddressFile, LspDisconHandler, &LSS ); if( !NT_SUCCESS(ntStatus) ) { LstransDisassociate(&LSS->AddressFile, &LSS->ConnectionFile); LstransCloseConnection(&LSS->ConnectionFile); LstransCloseAddress(&LSS->AddressFile); goto cleanup; } */ ntStatus = LspLogin( LSS, &LoginInfo, LSProto ); if(!NT_SUCCESS(ntStatus)) { LstransDisconnect(&LSS->ConnectionFile, 0); LstransDisassociate(&LSS->ConnectionFile); LstransCloseConnection(&LSS->ConnectionFile); LstransCloseAddress(&LSS->AddressFile); goto cleanup; } cleanup: return ntStatus; }
////////////////////////////////////////////////////////////////////////// // // Lanscsi Protocol // NTSTATUS LsuConnectLogin( OUT PLANSCSI_SESSION LanScsiSession, IN PTA_LSTRANS_ADDRESS TargetAddress, IN PTA_LSTRANS_ADDRESS BindingAddress, IN PLSSLOGIN_INFO LoginInfo, OUT PLSTRANS_TYPE LstransType ) { NTSTATUS status; LARGE_INTEGER defaultTimeOut; LSPROTO_TYPE LSProto; // // Confirm address type. // Connect to the Lanscsi Node. // status = LstransAddrTypeToTransType( BindingAddress->Address[0].AddressType, LstransType); if(!NT_SUCCESS(status)) { KDPrintM(DBG_OTHER_ERROR, ("LstransAddrTypeToTransType(), Can't Connect to the LS node. STATUS:0x%08x\n", status)); goto error_out; } // // Set timeouts // Extend generic timeout // RtlZeroMemory(LanScsiSession, sizeof(LANSCSI_SESSION)); defaultTimeOut.QuadPart = LURNIDE_GENERIC_TIMEOUT * 15 / 10; LspSetDefaultTimeOut(LanScsiSession, &defaultTimeOut); status = LspConnect( LanScsiSession, BindingAddress, TargetAddress, NULL, NULL ); if(!NT_SUCCESS(status)) { KDPrintM(DBG_OTHER_ERROR, ("LspConnect(), Can't Connect to the LS node. STATUS:0x%08x\n", status)); goto error_out; } // // Login to the Lanscsi Node. // status = LspLookupProtocol(LoginInfo->HWType, LoginInfo->HWVersion, &LSProto); if(!NT_SUCCESS(status)) { goto error_out; } status = LspLogin( LanScsiSession, LoginInfo, LSProto, NULL, TRUE ); if(!NT_SUCCESS(status)) { KDPrintM(DBG_OTHER_ERROR, ("LspLogin(), Can't login to the LS node with UserID:%08lx. STATUS:0x%08x.\n", LoginInfo->UserID, status)); status = STATUS_ACCESS_DENIED; goto error_out; } error_out: 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; }