NTSTATUS CompletionIrpCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PCOMPLETION_DATA Context ) { PMINIPORT_DEVICE_EXTENSION HwDeviceExtension = Context->HwDeviceExtension; PSCSI_REQUEST_BLOCK completionSrb = Context->CompletionSrb; PCCB shippedCcb = Context->ShippedCcb; KDPrint(4, ("Entered\n")); UNREFERENCED_PARAMETER(DeviceObject); if(completionSrb->DataBuffer) { KDPrint(2, ("Unexpected IRP completion!!! " "Maybe completion SRB did not reach NDASSCSI's StartIo routine.\n")); ASSERT(completionSrb->DataBuffer); InterlockedDecrement(&HwDeviceExtension->RequestExecuting); LsuDecrementTdiClientInProgress(); InitializeListHead(&shippedCcb->ListEntry); LsCcbSetStatusFlag(shippedCcb, CCBSTATUS_FLAG_TIMER_COMPLETE); ExInterlockedInsertTailList( &HwDeviceExtension->CcbTimerCompletionList, &shippedCcb->ListEntry, &HwDeviceExtension->CcbTimerCompletionListSpinLock ); completionSrb->DataBuffer = NULL; } else { // // Free the CCB if it is not going to the timer completion routine // and allocated from the system pool by NDASSCSI. // if(Context->ShippedCcbAllocatedFromPool) LsCcbPostCompleteCcb(shippedCcb); } // Free resources ExFreePoolWithTag(completionSrb, NDSC_PTAG_SRB); ExFreePoolWithTag(Context, NDSC_PTAG_CMPDATA); IoFreeIrp(Irp); return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS NdasDluSrbIoctlSendCCBWithComp( IN PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension, IN PNDAS_DLU_EXTENSION NdasDluLuExtension, IN PSCSI_REQUEST_BLOCK Srb, IN UINT32 CcbOpCode, IN PVOID CmdBuffer, IN ULONG CmdBufferLen ){ NTSTATUS status; PCCB ccb; // // Query to the LUR // status = LsCcbAllocate(&ccb); if(!NT_SUCCESS(status)) { Srb->SrbStatus = SRB_STATUS_ERROR; KDPrint(1,("LsCcbAllocate() failed.\n")); return STATUS_SUCCESS; } LSCCB_INITIALIZE(ccb); ccb->OperationCode = CcbOpCode; LsCcbSetFlag(ccb, CCB_FLAG_ALLOCATED); ccb->Srb = Srb; ccb->DataBufferLength = CmdBufferLen; ccb->DataBuffer = CmdBuffer; LsCcbSetCompletionRoutine(ccb, NdasDluCcbCompletion, LogicalUnitExtension); InterlockedIncrement(&NdasDluLuExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); status = LurRequest( NdasDluLuExtension->LUR, ccb ); if(!NT_SUCCESS(status)) { LsCcbFree(ccb); Srb->SrbStatus = SRB_STATUS_ERROR; LsuDecrementTdiClientInProgress(); KDPrint(1,("LurRequest() failed.\n")); return STATUS_SUCCESS; } return STATUS_PENDING; }
// // Open a device parameter registry. // NTSTATUS DrOpenDeviceRegistry( PDEVICE_OBJECT DeviceObject, HANDLE *DeviceParamReg, ACCESS_MASK AccessMask ){ HANDLE regKey; NTSTATUS status; // // Create or open the key. // status = IoOpenDeviceRegistryKey( DeviceObject, PLUGPLAY_REGKEY_DEVICE, AccessMask, ®Key); if(!NT_SUCCESS(status)) { KDPrint(1, ("IoOpenDeviceRegistryKey() failed. NTSTATUS:%08lx\n", status)); regKey = NULL; } *DeviceParamReg = regKey; return status; }
VOID NdasMiniLogError( IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb OPTIONAL, IN UCHAR PathId, IN UCHAR TargetId, IN UCHAR Lun, IN ULONG ErrorCode, IN ULONG UniqueId ){ PDEVICE_OBJECT DeviceObject = HwDeviceExtension->ScsiportFdoObject; LSU_ERROR_LOG_ENTRY errorLogEntry; UNREFERENCED_PARAMETER(Srb); if(HwDeviceExtension == NULL) { KDPrint(2, ("HwDeviceExtension NULL!! \n")); return; } if(DeviceObject == NULL) { KDPrint(2, ("DeviceObject NULL!! \n")); return; } // // Save the error log data in the log entry. // errorLogEntry.ErrorCode = ErrorCode; errorLogEntry.MajorFunctionCode = IRP_MJ_SCSI; errorLogEntry.IoctlCode = 0; errorLogEntry.UniqueId = UniqueId; errorLogEntry.SequenceNumber = 0; errorLogEntry.ErrorLogRetryCount = 0; errorLogEntry.Parameter2 = HwDeviceExtension->SlotNumber; errorLogEntry.DumpDataEntry = 4; errorLogEntry.DumpData[0] = TargetId; errorLogEntry.DumpData[1] = Lun; errorLogEntry.DumpData[2] = PathId; errorLogEntry.DumpData[3] = ErrorCode; LsuWriteLogErrorEntry(DeviceObject, &errorLogEntry); return; }
////////////////////////////////////////////////////////////////////////// // // Registry primitives. // NTSTATUS DrReadKeyValue( HANDLE RegKey, PWCHAR KeyName, ULONG KeyType, PVOID Buffer, ULONG BufferLength, PULONG BufferLengthNeeded ) { PKEY_VALUE_PARTIAL_INFORMATION keyValue; NTSTATUS status; ULONG outLength; UNICODE_STRING valueName; outLength = 0; keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, 512, DEVREG_POOTAG_KEYINFO); if(keyValue == NULL) return STATUS_INSUFFICIENT_RESOURCES; RtlInitUnicodeString(&valueName, KeyName); status = ZwQueryValueKey(RegKey, &valueName, KeyValuePartialInformation, keyValue, 512, &outLength); if(BufferLengthNeeded) { *BufferLengthNeeded = keyValue->DataLength; } if(!NT_SUCCESS(status)) { KDPrint(1, ("ZwQueryValueKey() failed. ValueKeyName:%ws\n", KeyName)); ExFreePool(keyValue); return status; } if(keyValue->Type != KeyType) { KDPrint(1, ("Wrong value key type. ValueKeyName:%ws\n", KeyName)); ExFreePool(keyValue); return status; } if(BufferLength < keyValue->DataLength) { KDPrint(1, ("Buffer too small. ValueKeyName:%ws\n", KeyName)); ExFreePool(keyValue); return STATUS_BUFFER_TOO_SMALL; } RtlCopyMemory(Buffer, keyValue->Data, keyValue->DataLength); ExFreePool(keyValue); return STATUS_SUCCESS; }
NTSTATUS RemoveDeviceFromMiniport( IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension, IN PMINIPORT_LU_EXTENSION LuExtension, IN PSCSI_REQUEST_BLOCK Srb, IN ULONG CurSrbSequence ) { NDSC_WORKITEM_INIT WorkitemCtx; NTSTATUS status; PCCB Ccb; // // initilize Ccb in srb. // KDPrint(1, ("Entered.\n")); status = LSCcbAllocate(&Ccb); if(!NT_SUCCESS(status)) { KDPrint(1, ("failed.\n")); return status; } LSCcbInitialize( Srb, HwDeviceExtension, CurSrbSequence, Ccb ); InterlockedIncrement(&HwDeviceExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); LSCcbSetCompletionRoutine(Ccb, NdscAdapterCompletion, HwDeviceExtension); LSCcbSetNextStackLocation(Ccb); // // Queue a workitem // NDSC_INIT_WORKITEM(&WorkitemCtx, RemoveDeviceFromMiniport_Worker, Ccb, LuExtension, NULL, HwDeviceExtension); status = MiniQueueWorkItem(&_NdscGlobals, HwDeviceExtension->ScsiportFdoObject, &WorkitemCtx); if(NT_SUCCESS(status)) { status = STATUS_PENDING; } return status; }
// // Complement Windows 2000's IoGetDeviceProperty() // NTSTATUS DrGetDeviceProperty( IN PDEVICE_OBJECT DeviceObject, IN DEVICE_REGISTRY_PROPERTY DeviceProperty, IN ULONG BufferLength, OUT PVOID PropertyBuffer, OUT PULONG ResultLength, IN BOOLEAN Win2K ) { NTSTATUS status; ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); if(!DeviceObject) return STATUS_INVALID_PARAMETER; if(Win2K) { status = DrGetDeviceProperty_ExtW2K( DeviceObject, DeviceProperty, BufferLength, PropertyBuffer, ResultLength ); } else { __try { status = IoGetDeviceProperty( DeviceObject, DeviceProperty, BufferLength, PropertyBuffer, ResultLength ); } __except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); KDPrint(1, ("IoGetDeviceProperty() Exception: %08lx\n", status)); } } return status; }
NTSTATUS NdasDluSendSrbIoCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ){ PMINISENDSRB_CONTEXT sendSrb = (PMINISENDSRB_CONTEXT)Context; UNREFERENCED_PARAMETER(DeviceObject); KDPrint(1,("STATUS=%08lx\n", Irp->IoStatus.Status)); // // get the result // if(Irp->IoStatus.Status == STATUS_SUCCESS) { if(sendSrb->UserBuffer && sendSrb->UserBufferLen) RtlCopyMemory( sendSrb->UserBuffer, (PUCHAR)&sendSrb->SrbIoctl + sizeof(SRB_IO_CONTROL), sendSrb->UserBufferLen); } // Free the IRP resources if(Irp->AssociatedIrp.SystemBuffer) ExFreePool(Irp->AssociatedIrp.SystemBuffer); if( Irp->MdlAddress != NULL ) { MmUnlockPages( Irp->MdlAddress ); IoFreeMdl( Irp->MdlAddress ); Irp->MdlAddress = NULL; } // Free the IRP IoFreeIrp(Irp); ExFreePool(sendSrb); return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS NdasDluIoctlDeviceLock( IN PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension, IN PNDAS_DLU_EXTENSION DluLuExtension, IN PNDSCIOCTL_DEVICELOCK DeviceLockControl, IN PSCSI_REQUEST_BLOCK Srb ){ NTSTATUS status; PLURN_DEVLOCK_CONTROL lurnDeviceLock; PCCB ccb; PNDAS_DLU_EXTENSION ndasDluExtension = NdasDluGetExtension(LogicalUnitExtension); // // Create a CCB // status = LsCcbAllocate(&ccb); if(!NT_SUCCESS(status)) { Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; KDPrint(1,("LsCcbAllocate() failed.\n")); return status; } lurnDeviceLock = (PLURN_DEVLOCK_CONTROL)ExAllocatePoolWithTag(NonPagedPool, sizeof(LURN_DEVLOCK_CONTROL), NDAS_DLU_PTAG_IOCTL); if(!lurnDeviceLock) { Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; KDPrint(1,("ExAllocatePoolWithTag() failed.\n")); return STATUS_INSUFFICIENT_RESOURCES; } LSCCB_INITIALIZE(ccb); ccb->OperationCode = CCB_OPCODE_DEVLOCK; ccb->DataBuffer = lurnDeviceLock; ccb->DataBufferLength = sizeof(LURN_DEVLOCK_CONTROL); LsCcbSetFlag(ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED); // Ioctl Srb will complete asynchronously. ccb->Srb = Srb; InterlockedIncrement(&DluLuExtension->RequestExecuting); // // Increment in-progress count // LsuIncrementTdiClientInProgress(); LsCcbSetCompletionRoutine(ccb, NdasDluCcbCompletion, LogicalUnitExtension); // // Set up request // lurnDeviceLock->LockId = DeviceLockControl->LockId; lurnDeviceLock->LockOpCode = DeviceLockControl->LockOpCode; lurnDeviceLock->AdvancedLock = DeviceLockControl->AdvancedLock; lurnDeviceLock->AddressRangeValid = DeviceLockControl->AddressRangeValid; lurnDeviceLock->RequireLockAcquisition = DeviceLockControl->RequireLockAcquisition; lurnDeviceLock->StartingAddress = DeviceLockControl->StartingAddress; lurnDeviceLock->ContentionTimeOut = DeviceLockControl->ContentionTimeOut; RtlCopyMemory(lurnDeviceLock->LockData, DeviceLockControl->LockData, NDSCLOCK_LOCKDATA_LENGTH); ASSERT(NDSCLOCK_LOCKDATA_LENGTH == LURNDEVLOCK_LOCKDATA_LENGTH); // // Send the request // status = LurRequest( ndasDluExtension->LUR, ccb ); if(!NT_SUCCESS(status)) { KDPrint(1,("LurnRequest() failed.\n")); LsCcbFree(ccb); ExFreePoolWithTag(lurnDeviceLock, NDSC_PTAG_IOCTL); status = STATUS_SUCCESS; Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; } else { status = STATUS_PENDING; } return status; }
NTSTATUS NdasDluSrbIoctlQueryInfo( PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension, PNDAS_DLU_EXTENSION DluLuExtension, PSCSI_REQUEST_BLOCK Srb, PNDASSCSI_QUERY_INFO_DATA QueryInfo, ULONG OutputBufferLength, PUCHAR OutputBuffer, PULONG SrbIoctlReturnCode, PUCHAR SrbStatus ) { NTSTATUS status; PCCB Ccb; // KIRQL oldIrql; UNREFERENCED_PARAMETER(LogicalUnitExtension); UNREFERENCED_PARAMETER(DluLuExtension); *SrbIoctlReturnCode = SRB_STATUS_SUCCESS; *SrbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; switch(QueryInfo->InfoClass) { case NdscPrimaryUnitDiskInformation: { PNDSCIOCTL_PRIMUNITDISKINFO primUnitDisk = (PNDSCIOCTL_PRIMUNITDISKINFO)OutputBuffer; PLUR_QUERY lurQuery; PLURN_PRIMARYINFORMATION lurPrimaryInfo; PBYTE lurBuffer; KDPrint(1,("NdscPrimaryUnitDiskInformation\n")); if(OutputBufferLength < sizeof(NDSCIOCTL_PRIMUNITDISKINFO)) { KDPrint(1,("Too small output buffer\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_BUFFER_TOO_SMALL; if (OutputBufferLength > sizeof(UINT32)) primUnitDisk->Length = sizeof(NDSCIOCTL_PRIMUNITDISKINFO); break; } // // Query to the LUR // status = LsCcbAllocate(&Ccb); if(!NT_SUCCESS(status)) { KDPrint(1,("LsCcbAllocate() failed.\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INSUFFICIENT_RESOURCES; break; } lurBuffer = ExAllocatePoolWithTag( NonPagedPool, SIZE_OF_LURQUERY(0, sizeof(LURN_PRIMARYINFORMATION)), LURN_IOCTL_POOL_TAG); if(lurBuffer == NULL) { KDPrint(1,("LsCcbAllocate() failed.\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INSUFFICIENT_RESOURCES; break; } // // Set up asynchronous CCB // LSCCB_INITIALIZE(Ccb); Ccb->Srb = Srb; Ccb->OperationCode = CCB_OPCODE_QUERY; LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED); Ccb->DataBuffer = lurBuffer; Ccb->DataBufferLength = sizeof(LURN_PRIMARYINFORMATION); LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, DluLuExtension); InterlockedIncrement(&DluLuExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); lurQuery = (PLUR_QUERY)lurBuffer; lurQuery->InfoClass = LurPrimaryLurnInformation; lurQuery->Length = SIZE_OF_LURQUERY(0, sizeof(LURN_PRIMARYINFORMATION)); lurQuery->QueryDataLength = 0; lurPrimaryInfo = (PLURN_PRIMARYINFORMATION)LUR_QUERY_INFORMATION(lurQuery); if(DluLuExtension->LUR == NULL) { LsuDecrementTdiClientInProgress(); InterlockedDecrement(&DluLuExtension->RequestExecuting); ExFreePoolWithTag(lurBuffer, LURN_IOCTL_POOL_TAG); LsCcbFree(Ccb); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } status = LurRequest( DluLuExtension->LUR, Ccb ); if(!NT_SUCCESS(status)) { LsuDecrementTdiClientInProgress(); InterlockedDecrement(&DluLuExtension->RequestExecuting); ExFreePoolWithTag(lurBuffer, LURN_IOCTL_POOL_TAG); LsCcbFree(Ccb); KDPrint(1,("LurRequest() failed.\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } status = STATUS_PENDING; break; } case NdscLurInformation: { PNDSCIOCTL_LURINFO info = (PNDSCIOCTL_LURINFO)OutputBuffer; PLUR_QUERY lurQuery; UINT32 lurnEnumInfoLen; UINT32 nodeCount; KDPrint(1,("NdscLurInformation\n")); if(OutputBufferLength < FIELD_OFFSET(NDSCIOCTL_LURINFO, Lurns)) { KDPrint(2,("LurInfo: Buffer size %d is less than required %d bytes\n", OutputBufferLength, FIELD_OFFSET(NDSCIOCTL_LURINFO, Lurns))); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } // // allocate a CCB // status = LsCcbAllocate(&Ccb); if(!NT_SUCCESS(status)) { KDPrint(1,("LsCcbAllocate() failed.\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; break; } // // initialize query CCB // LSCCB_INITIALIZE(Ccb); Ccb->Srb = Srb; Ccb->OperationCode = CCB_OPCODE_QUERY; LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED); if (DluLuExtension->LUR) { nodeCount = DluLuExtension->LUR->NodeCount; } else { nodeCount = 0; ASSERT(FALSE); } lurnEnumInfoLen = FIELD_OFFSET(LURN_ENUM_INFORMATION, Lurns) + sizeof(LURN_INFORMATION) * nodeCount; // Allocate memory and initialize it. LUR_QUERY_INITIALIZE(lurQuery, LurEnumerateLurn, 0, lurnEnumInfoLen); if(!lurQuery) { LsCcbFree(Ccb); KDPrint(1,("allocating DataBuffer failed.\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INSUFFICIENT_RESOURCES; break; } Ccb->DataBuffer = lurQuery; Ccb->DataBufferLength = lurQuery->Length; // // Set completion routine // LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, DluLuExtension); InterlockedIncrement(&DluLuExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); // // send the CCB down // status = LurRequest( DluLuExtension->LUR, Ccb ); if(!NT_SUCCESS(status)) { InterlockedDecrement(&DluLuExtension->RequestExecuting); LsuDecrementTdiClientInProgress(); LsCcbFree(Ccb); KDPrint(1,("LurRequest() failed.\n")); ExFreePoolWithTag(lurQuery, NDSC_PTAG_IOCTL); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } status = STATUS_PENDING; break; } case NdscSystemBacl: case NdscUserBacl: { ULONG requiredBufLen; PNDAS_BLOCK_ACL ndasBacl = (PNDAS_BLOCK_ACL)OutputBuffer; PLSU_BLOCK_ACL targetBacl; KDPrint(1,("NdscSystemBacl/UserBacl: going to default LuExtention 0.\n")); if(DluLuExtension->LUR == NULL) { *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } if(QueryInfo->InfoClass == NdscSystemBacl) targetBacl = &DluLuExtension->LUR->SystemBacl; else targetBacl = &DluLuExtension->LUR->UserBacl; status = LsuConvertLsuBaclToNdasBacl( ndasBacl, OutputBufferLength, &requiredBufLen, targetBacl); if(status == STATUS_BUFFER_TOO_SMALL) { // // Set required field. // if(OutputBufferLength >= FIELD_OFFSET(NDAS_BLOCK_ACL, BlockACECnt)) { ndasBacl->Length = requiredBufLen; } // // Set error code to the srb ioctl, but return success // *SrbIoctlReturnCode = SRB_STATUS_DATA_OVERRUN; } else if(!NT_SUCCESS(status)) { *SrbStatus = SRB_STATUS_ERROR; break; } *SrbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; } default: KDPrint(1,("Invalid Information Class!!\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; } return status; }
NTSTATUS NdscAdapterCompletion( IN PCCB Ccb, IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension ) { KIRQL oldIrql; static LONG SrbSeq; LONG srbSeqIncremented; PSCSI_REQUEST_BLOCK srb; PCCB abortCcb; NTSTATUS return_status; UINT32 AdapterStatus, AdapterStatusBefore; UINT32 NeedToUpdatePdoInfoInLSBus; BOOLEAN busResetOccured; KDPrint(4,("RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting)); srb = Ccb->Srb; if(!srb) { KDPrint(2,("Ccb:%p CcbStatus %d. No srb assigned.\n", Ccb, Ccb->CcbStatus)); ASSERT(srb); return STATUS_SUCCESS; } // // NDASSCSI completion routine will do post operation to complete CCBs. // return_status = STATUS_MORE_PROCESSING_REQUIRED; // // Set SRB completion sequence for debugging // srbSeqIncremented = InterlockedIncrement(&SrbSeq); #if 0 if(KeGetCurrentIrql() == PASSIVE_LEVEL) { if((srbSeqIncremented%100) == 0) { LARGE_INTEGER interval; KDPrint(2,("Interval for debugging.\n")); interval.QuadPart = - 11 * 10000000; // 10 seconds KeDelayExecutionThread(KernelMode, FALSE, &interval); } } #endif // // Update Adapter status flag // NeedToUpdatePdoInfoInLSBus = FALSE; ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); // Save the bus-reset flag if(ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_BUSRESET_PENDING)) { busResetOccured = TRUE; } else { busResetOccured = FALSE; } // Save the current flag AdapterStatusBefore = HwDeviceExtension->AdapterStatus; // Check reconnecting process. if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RECONNECTING)) { ADAPTER_SETSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING); } else { ADAPTER_RESETSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING); } if (!LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_FLAG_VALID)) { NDAS_ASSERT( Ccb->NdasrStatusFlag8 == 0 ); } else { NDAS_ASSERT( Ccb->NdasrStatusFlag8 == CCBSTATUS_FLAG_RAID_DEGRADED >> 8 || Ccb->NdasrStatusFlag8 == CCBSTATUS_FLAG_RAID_RECOVERING >> 8 || Ccb->NdasrStatusFlag8 == CCBSTATUS_FLAG_RAID_FAILURE >> 8 || Ccb->NdasrStatusFlag8 == CCBSTATUS_FLAG_RAID_NORMAL >> 8 ); } // Update adapter status only when CCBSTATUS_FLAG_RAID_FLAG_VALID is on. // In other case, Ccb has no chance to get flag information from RAID. if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_FLAG_VALID)) { // Check to see if the associate member is in error. if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_DEGRADED)) { if (!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT)) { KDPrint(2, ("NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT is Set\n") ); } ADAPTER_SETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT ); } else { ADAPTER_RESETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT ); } // Check recovering process. if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_RECOVERING)) { if (!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING)) { KDPrint(2, ("NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING is Set\n") ); } ADAPTER_SETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING ); } else { ADAPTER_RESETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING ); } // Check RAID failure if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_FAILURE)) { if (!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE)) { KDPrint(2, ("NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE is Set\n") ); } ADAPTER_SETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE ); } else { ADAPTER_RESETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE ); } // Set RAID normal status if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_NORMAL)) { if (!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_NORMAL)) { KDPrint(2, ("NDASSCSI_ADAPTER_STATUSFLAG_RAID_NORMAL is Set\n") ); } ADAPTER_SETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_NORMAL ); } else { ADAPTER_RESETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_NORMAL ); } } // power-recycle occurred. if(LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_POWERRECYLE_OCCUR)) { ADAPTER_SETSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED); } else { ADAPTER_RESETSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED); } if (ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED)) { //NDAS_ASSERT( FALSE ); } AdapterStatus = HwDeviceExtension->AdapterStatus; RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); if(AdapterStatus != AdapterStatusBefore) { if( !(AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT) && (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT) ) { // NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT on SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_MEMBER_FAULT, EVTLOG_MEMBER_IN_ERROR); KDPrint(2,("Ccb:%p CcbStatus %d. Set member fault.\n", Ccb, Ccb->CcbStatus)); } if( (AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT) && !(AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT) ) { // NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT off SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_MEMBER_FAULT_RECOVERED, EVTLOG_MEMBER_RECOVERED); KDPrint(2,("Ccb:%p CcbStatus %d. Reset member fault.\n", Ccb, Ccb->CcbStatus)); } if( !(AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING) && (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING) ) { // NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING on SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_RECONNECT_START, EVTLOG_START_RECONNECTION); KDPrint(2,("Ccb:%p CcbStatus %d. Start reconnecting\n", Ccb, Ccb->CcbStatus)); } if( (AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING) && !(AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING) ) { // NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING off SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_RECONNECTED, EVTLOG_END_RECONNECTION); KDPrint(2,("Ccb:%p CcbStatus %d. Finish reconnecting\n", Ccb, Ccb->CcbStatus)); } if( !(AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING) && (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING) ) { // NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING on SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_RECOVERY_START, EVTLOG_START_RECOVERING); KDPrint(2,("Ccb:%p CcbStatus %d. Started recovering\n", Ccb, Ccb->CcbStatus)); } if( (AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING) && !(AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING) && !(AdapterStatus & (NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE|NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT)) && (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RAID_NORMAL)) { // NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING off SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_RECOVERED, EVTLOG_END_RECOVERING); KDPrint(2,("Ccb:%p CcbStatus %d. Ended recovering\n", Ccb, Ccb->CcbStatus)); } if ( (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE) && !(AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE)) { SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_RAID_FAILURE, EVTLOG_RAID_FAILURE); KDPrint(2,("Ccb:%p CcbStatus %d. RAID failure\n", Ccb, Ccb->CcbStatus)); } if( !(AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED) && (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED) ) { // NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED on SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_DISK_POWERRECYCLE, EVTLOG_DISK_POWERRECYCLED); KDPrint(2,("Ccb:%p CcbStatus %d. Started recovering\n", Ccb, Ccb->CcbStatus)); } NeedToUpdatePdoInfoInLSBus = TRUE; } // // If CCB_OPCODE_UPDATE is successful, update adapter status in LanscsiBus // if(Ccb->OperationCode == CCB_OPCODE_UPDATE) { if(Ccb->CcbStatus == CCB_STATUS_SUCCESS) { SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_UPGRADE_SUCC, EVTLOG_SUCCEED_UPGRADE); } else { SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_UPGRADE_FAIL, EVTLOG_FAIL_UPGRADE); } NeedToUpdatePdoInfoInLSBus = TRUE; } // // Copy IO control results to the SRB buffer. // // If device lock CCB is successful, copy the result to the SRB. // if(Ccb->OperationCode == CCB_OPCODE_DEVLOCK) { if(Ccb->CcbStatus == CCB_STATUS_SUCCESS) { PSRB_IO_CONTROL srbIoctlHeader; PUCHAR lockIoctlBuffer; PNDSCIOCTL_DEVICELOCK ioCtlAcReDeviceLock; PLURN_DEVLOCK_CONTROL lurnAcReDeviceLock; // // Get the Ioctl buffer. // srbIoctlHeader = (PSRB_IO_CONTROL)srb->DataBuffer; srbIoctlHeader->ReturnCode = SRB_STATUS_SUCCESS; lockIoctlBuffer = (PUCHAR)(srbIoctlHeader + 1); ioCtlAcReDeviceLock = (PNDSCIOCTL_DEVICELOCK)lockIoctlBuffer; lurnAcReDeviceLock = (PLURN_DEVLOCK_CONTROL)Ccb->DataBuffer; // Copy the result RtlCopyMemory( ioCtlAcReDeviceLock->LockData, lurnAcReDeviceLock->LockData, NDSCLOCK_LOCKDATA_LENGTH); } } else if(Ccb->OperationCode == CCB_OPCODE_QUERY) { if(Ccb->CcbStatus == CCB_STATUS_SUCCESS) { PSRB_IO_CONTROL srbIoctlHeader; NTSTATUS copyStatus; srbIoctlHeader = (PSRB_IO_CONTROL)srb->DataBuffer; copyStatus = NdscCopyQueryOutputToSrb( HwDeviceExtension, Ccb->DataBufferLength, Ccb->DataBuffer, srbIoctlHeader->Length, (PUCHAR)(srbIoctlHeader + 1) ); if(copyStatus == STATUS_BUFFER_TOO_SMALL) { srbIoctlHeader->ReturnCode = SRB_STATUS_DATA_OVERRUN; }else if(NT_SUCCESS(copyStatus)) { srbIoctlHeader->ReturnCode = SRB_STATUS_SUCCESS; } else { srbIoctlHeader->ReturnCode = SRB_STATUS_ERROR; } } } KDPrint(4,("CcbStatus %d\n", Ccb->CcbStatus)); // // Translate CcbStatus to SrbStatus // CcbStatusToSrbStatus(Ccb, srb); // // Perform stop process when we get stop status. // if(Ccb->CcbStatus == CCB_STATUS_STOP) { // // Stop in the timer routine. // KDPrint(2, ("Stop status. Stop in the timer routine.\n")); } else { // // Update PDO information on the NDAS bus. // if(NeedToUpdatePdoInfoInLSBus) { KDPrint(2, ("<<<<<<<<<<<<<<<< %08lx -> %08lx ADAPTER STATUS CHANGED" " >>>>>>>>>>>>>>>>\n", AdapterStatusBefore, AdapterStatus)); UpdatePdoInfoInLSBus(HwDeviceExtension, HwDeviceExtension->AdapterStatus); } } // // Process Abort CCB. // abortCcb = Ccb->AbortCcb; if(abortCcb != NULL) { KDPrint(2,("abortSrb\n")); ASSERT(FALSE); srb->SrbStatus = SRB_STATUS_SUCCESS; LsCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); InitializeListHead(&Ccb->ListEntry); ExInterlockedInsertTailList( &HwDeviceExtension->CcbTimerCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbTimerCompletionListSpinLock ); ((PSCSI_REQUEST_BLOCK)abortCcb->Srb)->SrbStatus = SRB_STATUS_ABORTED; LsCcbSetStatusFlag(abortCcb, CCBSTATUS_FLAG_TIMER_COMPLETE); InitializeListHead(&abortCcb->ListEntry); ExInterlockedInsertTailList( &HwDeviceExtension->CcbTimerCompletionList, &abortCcb->ListEntry, &HwDeviceExtension->CcbTimerCompletionListSpinLock ); } else { BOOLEAN criticalSrb; // // We should not use completion IRP method with disable-disconnect flag. // A SRB with DISABLE_DISCONNECT flag causes the SCSI port queue locked. // criticalSrb = (srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) != 0 || (srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) != 0 || (srb->SrbFlags & SRB_FLAGS_BYPASS_LOCKED_QUEUE) != 0; #if DBG if(criticalSrb) { KDPrint(2, ("Critical Srb:%p\n", srb)); } #if 0 NdscPrintSrb("Comp:", srb); #endif #endif // // Make Complete IRP and Send it. // // // In case of HostStatus == CCB_STATUS_SUCCESS_TIMER, CCB will go to the timer to complete. // if( (Ccb->CcbStatus == CCB_STATUS_SUCCESS || Ccb->CcbStatus == CCB_STATUS_DATA_OVERRUN) && !LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE) && !LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_BUSCHANGE) && !busResetOccured && !criticalSrb ) { PDEVICE_OBJECT pDeviceObject = HwDeviceExtension->ScsiportFdoObject; PIRP pCompletionIrp = NULL; PIO_STACK_LOCATION pIoStack; NTSTATUS ntStatus; PSCSI_REQUEST_BLOCK completionSrb = NULL; PCOMPLETION_DATA completionData = NULL; completionSrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK), NDSC_PTAG_SRB); if(completionSrb == NULL) goto Out; RtlZeroMemory( completionSrb, sizeof(SCSI_REQUEST_BLOCK) ); // Build New IRP. pCompletionIrp = IoAllocateIrp((CCHAR)(pDeviceObject->StackSize + 1), FALSE); if(pCompletionIrp == NULL) { ExFreePoolWithTag(completionSrb, NDSC_PTAG_SRB); goto Out; } completionData = ExAllocatePoolWithTag(NonPagedPool, sizeof(COMPLETION_DATA), NDSC_PTAG_CMPDATA); if(completionData == NULL) { ExFreePoolWithTag(completionSrb, NDSC_PTAG_SRB); IoFreeIrp(pCompletionIrp); pCompletionIrp = NULL; goto Out; } pCompletionIrp->MdlAddress = NULL; // Set IRP stack location. pIoStack = IoGetNextIrpStackLocation(pCompletionIrp); pIoStack->DeviceObject = pDeviceObject; pIoStack->MajorFunction = IRP_MJ_SCSI; pIoStack->Parameters.DeviceIoControl.InputBufferLength = 0; pIoStack->Parameters.DeviceIoControl.OutputBufferLength = 0; pIoStack->Parameters.Scsi.Srb = completionSrb; // Set SRB. completionSrb->Length = sizeof(SCSI_REQUEST_BLOCK); completionSrb->Function = SRB_FUNCTION_EXECUTE_SCSI; completionSrb->PathId = srb->PathId; completionSrb->TargetId = srb->TargetId; completionSrb->Lun = srb->Lun; completionSrb->QueueAction = SRB_SIMPLE_TAG_REQUEST; completionSrb->DataBuffer = Ccb; completionSrb->SrbFlags |= SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE; completionSrb->OriginalRequest = pCompletionIrp; completionSrb->CdbLength = MAXIMUM_CDB_SIZE; completionSrb->Cdb[0] = SCSIOP_COMPLETE; completionSrb->Cdb[1] = (UCHAR)srbSeqIncremented; completionSrb->TimeOutValue = 20; completionSrb->SrbStatus = SRB_STATUS_SUCCESS; // // Set completion data for the completion IRP. // completionData->HwDeviceExtension = HwDeviceExtension; completionData->CompletionSrb = completionSrb; completionData->ShippedCcb = Ccb; completionData->ShippedCcbAllocatedFromPool = LsCcbIsFlagOn(Ccb, CCB_FLAG_ALLOCATED); Out: KDPrint(5,("Before Completion\n")); IoSetCompletionRoutine( pCompletionIrp, CompletionIrpCompletionRoutine, completionData, TRUE, TRUE, TRUE); ASSERT(HwDeviceExtension->RequestExecuting != 0); #if 0 { LARGE_INTEGER interval; ULONG SrbTimeout; static DebugCount = 0; DebugCount ++; SrbTimeout = ((PSCSI_REQUEST_BLOCK)(Ccb->Srb))->TimeOutValue; if( SrbTimeout>9 && (DebugCount%1000) == 0 ) { KDPrint(2,("Experiment!!!!!!! Delay completion. SrbTimeout:%d\n", SrbTimeout)); interval.QuadPart = - (INT64)SrbTimeout * 11 * 1000000; KeDelayExecutionThread(KernelMode, FALSE, &interval); } } #endif // // call Scsiport FDO. // ntStatus = IoCallDriver(pDeviceObject, pCompletionIrp); ASSERT(NT_SUCCESS(ntStatus)); if(ntStatus!= STATUS_SUCCESS && ntStatus!= STATUS_PENDING) { KDPrint(2,("ntStatus = 0x%x\n", ntStatus)); SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_COMPIRP_FAIL, EVTLOG_FAIL_COMPLIRP); KDPrint(2,("IoCallDriver() error. CCB(%p) and SRB(%p) is going to the timer." " CcbStatus:%x CcbFlag:%x\n", Ccb, Ccb->Srb, Ccb->CcbStatus, Ccb->Flags)); InitializeListHead(&Ccb->ListEntry); LsCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); ExInterlockedInsertTailList( &HwDeviceExtension->CcbTimerCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbTimerCompletionListSpinLock ); } } else { KDPrint(2,("CCB(%p) and SRB(%p) is going to the timer." " CcbStatus:%x CcbFlag:%x\n", Ccb, Ccb->Srb, Ccb->CcbStatus, Ccb->Flags)); InitializeListHead(&Ccb->ListEntry); LsCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); ExInterlockedInsertTailList( &HwDeviceExtension->CcbTimerCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbTimerCompletionListSpinLock ); } } return return_status; }
VOID UpdatePdoInfoInLSBus( PMINIPORT_DEVICE_EXTENSION HwDeviceExtension, UINT32 AdapterStatus ) { PBUSENUM_SETPDOINFO BusSet; UINT32 DesiredAccess; UINT32 GrantedAccess; ASSERT(HwDeviceExtension); // // Query to the LUR // if(HwDeviceExtension->LURs[0]) { KDPrint(3,("going to default LuExtention 0.\n")); DesiredAccess = HwDeviceExtension->LURs[0]->DesiredAccess; GrantedAccess = HwDeviceExtension->LURs[0]->GrantedAccess; } else { KDPrint(1,("No LUR available..\n")); DesiredAccess = GrantedAccess = 0; return; } // // Send to LSBus // BusSet = (PBUSENUM_SETPDOINFO)ExAllocatePoolWithTag(NonPagedPool, sizeof(BUSENUM_SETPDOINFO), LSMP_PTAG_IOCTL); if(BusSet == NULL) { return; } BusSet->Size = sizeof(BUSENUM_SETPDOINFO); BusSet->SlotNo = HwDeviceExtension->SlotNumber; BusSet->AdapterStatus = AdapterStatus; BusSet->DesiredAccess = DesiredAccess; BusSet->GrantedAccess = GrantedAccess; if(KeGetCurrentIrql() == PASSIVE_LEVEL) { IoctlToLanscsiBus( IOCTL_LANSCSI_SETPDOINFO, BusSet, sizeof(BUSENUM_SETPDOINFO), NULL, 0, NULL); if(HwDeviceExtension->AlarmEventToService) { KeSetEvent(HwDeviceExtension->AlarmEventToService, IO_NO_INCREMENT, FALSE); } ExFreePoolWithTag(BusSet, LSMP_PTAG_IOCTL); } else { // // IoctlToLanscsiBus_Worker() will free memory of BusSet. // IoctlToLanscsiBusByWorker( HwDeviceExtension->ScsiportFdoObject, IOCTL_LANSCSI_SETPDOINFO, BusSet, sizeof(BUSENUM_SETPDOINFO), HwDeviceExtension->AlarmEventToService ); } }
// // query scsiport PDO // ULONG GetScsiAdapterPdoEnumInfo( IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension, IN ULONG SystemIoBusNumber, OUT PLONG AddTargetDataLength, OUT PLANSCSI_ADD_TARGET_DATA *AddTargetData ) { NTSTATUS status; BUSENUM_QUERY_INFORMATION BusQuery; PBUSENUM_INFORMATION BusInfo; LONG BufferNeeded; LONG addTargetDataLength; PLANSCSI_ADD_TARGET_DATA addTargetData; KDPrint(1,("SystemIoBusNumber:%d\n", SystemIoBusNumber)); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); BusQuery.Size = sizeof(BUSENUM_QUERY_INFORMATION); BusQuery.InfoClass = INFORMATION_PDOENUM; BusQuery.SlotNo = SystemIoBusNumber; // // Get a buffer length needed. // status = IoctlToLanscsiBus( IOCTL_BUSENUM_QUERY_INFORMATION, &BusQuery, sizeof(BUSENUM_QUERY_INFORMATION), NULL, 0, &BufferNeeded ); if(status != STATUS_BUFFER_TOO_SMALL || BufferNeeded <= 0) { KDPrint(1,("IoctlToLanscsiBus() Failed.\n")); return SP_RETURN_NOT_FOUND; } // // // BusInfo= (PBUSENUM_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, BufferNeeded, LSMP_PTAG_IOCTL); status = IoctlToLanscsiBus( IOCTL_BUSENUM_QUERY_INFORMATION, &BusQuery, sizeof(BUSENUM_QUERY_INFORMATION), BusInfo, BufferNeeded, &BufferNeeded ); if(!NT_SUCCESS(status)) { ExFreePoolWithTag(BusInfo, LSMP_PTAG_IOCTL); return SP_RETURN_NOT_FOUND; } ASSERT(BusInfo->PdoEnumInfo.DisconEventToService); ASSERT(BusInfo->PdoEnumInfo.AlarmEventToService); HwDeviceExtension->MaxBlocksPerRequest = BusInfo->PdoEnumInfo.MaxBlocksPerRequest; HwDeviceExtension->DisconEventToService = BusInfo->PdoEnumInfo.DisconEventToService; HwDeviceExtension->AlarmEventToService = BusInfo->PdoEnumInfo.AlarmEventToService; KDPrint(1,("MaxBlocksPerRequest:%d DisconEventToService:%p AlarmEventToService:%p\n", BusInfo->PdoEnumInfo.MaxBlocksPerRequest, BusInfo->PdoEnumInfo.DisconEventToService, BusInfo->PdoEnumInfo.AlarmEventToService )); // // copy LANSCSI_ADD_TARGET_DATA // addTargetDataLength = sizeof(LANSCSI_ADD_TARGET_DATA) + (BusInfo->PdoEnumInfo.AddTargetData.ulNumberOfUnitDiskList - 1) * sizeof(LSBUS_UNITDISK); addTargetData = (PLANSCSI_ADD_TARGET_DATA)ExAllocatePoolWithTag(NonPagedPool, addTargetDataLength, LSMP_PTAG_IOCTL); if(addTargetData == NULL) { ExFreePoolWithTag(BusInfo,LSMP_PTAG_IOCTL); return SP_RETURN_NOT_FOUND; } RtlCopyMemory(addTargetData, &BusInfo->PdoEnumInfo.AddTargetData, addTargetDataLength); *AddTargetData = addTargetData; *AddTargetDataLength = addTargetDataLength; ExFreePoolWithTag(BusInfo,LSMP_PTAG_IOCTL); return SP_RETURN_FOUND; }
NTSTATUS LurProcessWrite ( PLURELATION Lur, PCCB WriteCommand ) { NTSTATUS status; UINT64 writeAddr; UINT32 writeLen; // Check to see if the write check (NDAS chip 2.0 bug patch) is required. // Anyway this option is activated only when HW is 2.0 rev.0. // if (Lur->LurFlags & LURFLAG_WRITE_CHECK_REQUIRED) { LsCcbSetFlag(WriteCommand, CCB_FLAG_WRITE_CHECK); } else { LsCcbResetFlag(WriteCommand, CCB_FLAG_WRITE_CHECK); } if (WriteCommand->CdbLength == 10 || WriteCommand->CdbLength == 16) { LsCcbGetAddressAndLength( &WriteCommand->SrbCdb, &writeAddr, &writeLen ); } else { NDAS_ASSERT(FALSE); return STATUS_NOT_SUPPORTED; } if (writeAddr < Lur->MaxChildrenSectorCount && (writeAddr + writeLen) > Lur->UnitBlocks ) { NDAS_ASSERT(FALSE); WriteCommand->CcbStatus = CCB_STATUS_INVALID_COMMAND; LsCcbCompleteCcb( WriteCommand ); status = STATUS_SUCCESS; } do { // Layer 0 // User BACL status = FilterWriteByBACL( Lur, &Lur->UserBacl, (Lur->EnabledNdasFeatures & NDASFEATURE_RO_FAKE_WRITE) != 0, writeAddr, writeLen, WriteCommand ); if (status != STATUS_NO_MORE_ENTRIES) { // If an BACE found, break here no matter what status // it returns. If not, go to the next layer break; } // Layer 1 // out-of-bound access if (writeAddr > Lur->EndingBlockAddr) { NDAS_ASSERT(FALSE); // If OOB write is neither enabled nor writable device access mode, // deny it. if (!(Lur->EnabledNdasFeatures & NDASFEATURE_OOB_WRITE) && !(Lur->DeviceMode & NDASACCRIGHT_WRITE)) { // Complete the write command with an error. WriteCommand->CcbStatus = CCB_STATUS_INVALID_COMMAND; LsCcbCompleteCcb(WriteCommand); status = STATUS_SUCCESS; break; } // If the write command is in safety area, // deny it. if (writeAddr <= Lur->EndingBlockAddr + 256) { // Complete the write command with an error. WriteCommand->CcbStatus = CCB_STATUS_INVALID_COMMAND; LsCcbCompleteCcb(WriteCommand); status = STATUS_SUCCESS; break; } // Turn off write-check for OOB access LsCcbResetFlag(WriteCommand, CCB_FLAG_WRITE_CHECK); status = LurnRequest(LUR_GETROOTNODE(Lur), WriteCommand); break; } // Layer 2 // Device mode if (Lur->DeviceMode == DEVMODE_SHARED_READONLY) { NDAS_ASSERT(FALSE); if (Lur->EnabledNdasFeatures & NDASFEATURE_RO_FAKE_WRITE) { // Complete the write command KDPrint(1, ("Readonly fake write: command %p\n", WriteCommand)); WriteCommand->CcbStatus = CCB_STATUS_SUCCESS; LsCcbCompleteCcb(WriteCommand); status = STATUS_SUCCESS; break; } WriteCommand->CcbStatus = CCB_STATUS_INVALID_COMMAND; LsCcbCompleteCcb(WriteCommand); status = STATUS_SUCCESS; break; } else if (Lur->DeviceMode == DEVMODE_SHARED_READWRITE) { // If secondary, return write operation without actual write. // If secondary wants to write, insert writable BACE. if (Lur->EnabledNdasFeatures & NDASFEATURE_SECONDARY) { NDAS_ASSERT(FALSE); // Complete the write command KDPrint( 1, ("Secondary fake write: command %p\n", WriteCommand) ); WriteCommand->CcbStatus = CCB_STATUS_SUCCESS; LsCcbCompleteCcb(WriteCommand); status = STATUS_SUCCESS; break; } } else if(Lur->DeviceMode == DEVMODE_EXCLUSIVE_READWRITE) { // Nothing to do } else if(Lur->DeviceMode == DEVMODE_SUPER_READWRITE) { // Nothing to do } else { // Complete the write command WriteCommand->CcbStatus = CCB_STATUS_INVALID_COMMAND; LsCcbCompleteCcb(WriteCommand); status = STATUS_SUCCESS; break; } // Layer 3 // Disk DIB BACL status = FilterWriteByBACL( Lur, &Lur->SystemBacl, (Lur->EnabledNdasFeatures & NDASFEATURE_RO_FAKE_WRITE) != 0, writeAddr, writeLen, WriteCommand ); if (status == STATUS_NO_MORE_ENTRIES) { // No BACL filtered. Just write it. status = LurnRequest( LUR_GETROOTNODE(Lur), WriteCommand ); } } while(0); return status; }
NTSTATUS DrGetDevicePropertyInstallState( IN PDEVICE_OBJECT DeviceObject, IN ULONG BufferLength, OUT PVOID PropertyBuffer, OUT PULONG ResultLength ) { NTSTATUS status; HANDLE devparamRegKey; HANDLE devInstRegKey; UNICODE_STRING valueName; UCHAR keyValueBuffer[KVLEN_PARTIAL]; PKEY_VALUE_PARTIAL_INFORMATION keyValue; ULONG resultLength; PULONG configFlags; DEVICE_INSTALL_STATE deviceInstallState; PVOID Object; UCHAR ObjectNameBuffer[512]; POBJECT_NAME_INFORMATION ObjectNameInfo; OBJECT_ATTRIBUTES objectAttributes; // // init // devInstRegKey = NULL; devparamRegKey = NULL; keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)keyValueBuffer; if(BufferLength < sizeof(DEVICE_INSTALL_STATE)) { return STATUS_INSUFFICIENT_RESOURCES; } // // open the device registry's parameter key // status = IoOpenDeviceRegistryKey( DeviceObject, PLUGPLAY_REGKEY_DEVICE, KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &devparamRegKey ); if(!NT_SUCCESS(status)) { devInstRegKey = NULL; goto cleanup; } status = ObReferenceObjectByHandle( devparamRegKey, GENERIC_READ, NULL, KernelMode, &Object, NULL ); if(!NT_SUCCESS(status)) { goto cleanup; } ObjectNameInfo = (POBJECT_NAME_INFORMATION)ObjectNameBuffer; status = ObQueryNameString(Object, ObjectNameInfo, sizeof(ObjectNameBuffer), &resultLength ); ObDereferenceObject(Object); if(!NT_SUCCESS(status) || ObjectNameInfo->Name.Buffer == NULL) { goto cleanup; } KDPrint(1, ("Device parameter path: %ws. len=%d\n", ObjectNameInfo->Name.Buffer,ObjectNameInfo->Name.Length)); ASSERT(ObjectNameInfo->Name.Length < sizeof(ObjectNameBuffer) - 20); // trim down to the first parent. for(; ObjectNameInfo->Name.Length > 1; ObjectNameInfo->Name.Length-=sizeof(WCHAR) ) { if( ObjectNameInfo->Name.Buffer[ObjectNameInfo->Name.Length/sizeof(WCHAR) - 1] == '\\') { ObjectNameInfo->Name.Length-=sizeof(WCHAR); KDPrint(1, ("Trimed at the index %d\n", ObjectNameInfo->Name.Length)); break; } } KDPrint(1, ("Device parameter path: %ws. len=%d\n", ObjectNameInfo->Name.Buffer,ObjectNameInfo->Name.Length)); if(ObjectNameInfo->Name.Length <= 1) { goto cleanup; } // // Open device registry. // InitializeObjectAttributes( &objectAttributes, &ObjectNameInfo->Name, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL ); status = ZwOpenKey(&devInstRegKey, KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &objectAttributes); if(!NT_SUCCESS(status)) { goto cleanup; } // // Query the value of CONFIGFLAGS // RtlInitUnicodeString(&valueName, REGSTR_VAL_CONFIGFLAGS); status = ZwQueryValueKey( devInstRegKey, &valueName, KeyValuePartialInformation, keyValue, KVLEN_PARTIAL, &resultLength ); if(!NT_SUCCESS(status)) { goto cleanup; } if(keyValue->Type != REG_DWORD) { goto cleanup; } if(keyValue->DataLength != sizeof(ULONG)) { goto cleanup; } // // determine deviceInstallState // // TODO: If the device object is root device, // always return InstallStateInstalled. // configFlags = (PULONG)keyValue->Data; if ((*configFlags) & CONFIGFLAG_REINSTALL) { deviceInstallState = InstallStateNeedsReinstall; } else if ((*configFlags) & CONFIGFLAG_FAILEDINSTALL) { deviceInstallState = InstallStateFailedInstall; } else if ((*configFlags) & CONFIGFLAG_FINISH_INSTALL) { deviceInstallState = InstallStateFinishInstall; } else { deviceInstallState = InstallStateInstalled; } // // set the result // (*(PDEVICE_INSTALL_STATE)PropertyBuffer) = deviceInstallState; *ResultLength = sizeof(DEVICE_INSTALL_STATE); cleanup: if(devInstRegKey) ZwClose(devInstRegKey); if(devparamRegKey) ZwClose(devparamRegKey); return status; }
NTSTATUS DrDeleteAllSubKeys( HANDLE ParentKey ) { NTSTATUS status; PKEY_BASIC_INFORMATION keyInfo; ULONG outLength; ULONG idxKey; OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING objectName; HANDLE childKey; keyInfo = (PKEY_BASIC_INFORMATION)ExAllocatePoolWithTag(PagedPool, 512, DEVREG_POOTAG_KEYINFO); if(!keyInfo) { KDPrint(1, ("ExAllocatePoolWithTag(KEY_BASIC_INFORMATION) failed.\n")); return STATUS_INSUFFICIENT_RESOURCES; } status = STATUS_SUCCESS; for(idxKey = 0 ; idxKey < DEVREG_MAX_REGISTRY_KEY; idxKey ++) { status = ZwEnumerateKey( ParentKey, idxKey, KeyBasicInformation, keyInfo, 512, &outLength ); if(status == STATUS_NO_MORE_ENTRIES) { KDPrint(1, ("No more entries.\n")); status = STATUS_SUCCESS; break; } if(status != STATUS_SUCCESS) { ASSERT(status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL); KDPrint(1, ("ZwEnumerateKey() failed. NTSTATUS:%08lx\n", status)); ExFreePool(keyInfo); return STATUS_SUCCESS; } // // Open a sub key // objectName.Length = objectName.MaximumLength = (USHORT)keyInfo->NameLength; objectName.Buffer = keyInfo->Name; InitializeObjectAttributes( &objectAttributes, &objectName, OBJ_KERNEL_HANDLE, ParentKey, NULL ); status = ZwOpenKey(&childKey, KEY_ALL_ACCESS, &objectAttributes); if(!NT_SUCCESS(status)) { KDPrint(1, ("ZwOpenKey() failed. NTSTATUS:%08lx\n", status)); continue; } // // Delete all subkeys // status = DrDeleteAllSubKeys(childKey); if(!NT_SUCCESS(status)) { KDPrint(1, ("Recursive DrDeleteAllSubKeys() failed. NTSTATUS:%08lx\n", status)); ZwClose(childKey); continue; } // // Delete NDAS device instance. // status = ZwDeleteKey(childKey); #if DBG if(!NT_SUCCESS(status)) { KDPrint(1, ("ZwDeleteKey() failed. NTSTATUS:%08lx\n", status)); } #endif ZwClose(childKey); // // One key was deleted, decrement key index. // idxKey--; } ExFreePool(keyInfo); return STATUS_SUCCESS; }
VOID CcbStatusToSrbStatus(PCCB Ccb, PSCSI_REQUEST_BLOCK Srb) { Srb->DataTransferLength -= Ccb->ResidualDataLength; switch(Ccb->CcbStatus) { case CCB_STATUS_SUCCESS: Srb->SrbStatus = SRB_STATUS_SUCCESS; Srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_NOT_EXIST: Srb->SrbStatus = SRB_STATUS_NO_DEVICE; Srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_INVALID_COMMAND: Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; Srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_LOST_LOCK: case CCB_STATUS_COMMAND_FAILED: Srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID; Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; break; case CCB_STATUS_COMMMAND_DONE_SENSE2: Srb->SrbStatus = SRB_STATUS_BUSY | SRB_STATUS_AUTOSENSE_VALID ; Srb->DataTransferLength = 0; Srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_COMMMAND_DONE_SENSE: Srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID ; Srb->DataTransferLength = 0; Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; break; case CCB_STATUS_RESET: Srb->SrbStatus = SRB_STATUS_BUS_RESET; Srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_DATA_OVERRUN: Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; Srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_COMMUNICATION_ERROR: { PSENSE_DATA senseData; Srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID; Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; Srb->DataTransferLength = 0; senseData = Srb->SenseInfoBuffer; senseData->ErrorCode = 0x70; senseData->Valid = 1; //senseData->SegmentNumber = 0; senseData->SenseKey = SCSI_SENSE_HARDWARE_ERROR; //SCSI_SENSE_MISCOMPARE; //senseData->IncorrectLength = 0; //senseData->EndOfMedia = 0; //senseData->FileMark = 0; senseData->AdditionalSenseLength = 0xb; senseData->AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE; senseData->AdditionalSenseCodeQualifier = 0; } break; case CCB_STATUS_BUSY: Srb->SrbStatus = SRB_STATUS_BUSY; Srb->ScsiStatus = SCSISTAT_GOOD; KDPrint(2,("CCB_STATUS_BUSY\n")); break; // // Stop one LUR // case CCB_STATUS_STOP: { Srb->SrbStatus = SRB_STATUS_BUS_RESET; Srb->ScsiStatus = SCSISTAT_GOOD; Srb->DataTransferLength = 0; KDPrint(2,("CCB_STATUS_STOP. Stopping!\n")); break; } default: ASSERT(FALSE); // Error in Connection... // CCB_STATUS_UNKNOWN_STATUS, CCB_STATUS_RESET, and so on. Srb->SrbStatus = SRB_STATUS_ERROR; Srb->ScsiStatus = SCSISTAT_GOOD; Srb->DataTransferLength = 0; } }
VOID MiniTimer( IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension ) { BOOLEAN BusChanged; MiniCounter ++; BusChanged = FALSE; do { PLIST_ENTRY listEntry; PCCB ccb; PSCSI_REQUEST_BLOCK srb; // Get Completed CCB listEntry = ExInterlockedRemoveHeadList( &HwDeviceExtension->CcbCompletionList, &HwDeviceExtension->CcbCompletionListSpinLock ); if(listEntry == NULL) break; ccb = CONTAINING_RECORD(listEntry, CCB, ListEntry); srb = ccb->Srb; ASSERT(srb); ASSERT(LSCcbIsStatusFlagOn(ccb, CCBSTATUS_FLAG_TIMER_COMPLETE)); KDPrint(1,("completed SRB:%p SCSIOP:%x\n", srb, srb->Cdb[0])); if(LSCcbIsStatusFlagOn(ccb, CCBSTATUS_FLAG_BUSRESET_REQUIRED)) { BusChanged = TRUE; } // // Free a CCB // LSCcbPostCompleteCcb(ccb); ScsiPortNotification( RequestComplete, HwDeviceExtension, srb ); InterlockedDecrement(&HwDeviceExtension->RequestExecuting); } while(1); if(BusChanged) { KDPrint(1,("Bus change detected. RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting)); ScsiPortNotification( BusChangeDetected, HwDeviceExtension, NULL ); } if((MiniCounter % 1000) == 0) KDPrint(4,("RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting)); if(HwDeviceExtension->RequestExecuting != 0) { ScsiPortNotification( RequestTimerCall, HwDeviceExtension, MiniTimer, 1 ); } else { HwDeviceExtension->TimerOn = FALSE; if(ADAPTER_ISSTATUS(HwDeviceExtension,ADAPTER_STATUS_RUNNING)) ScsiPortNotification( RequestTimerCall, HwDeviceExtension, MiniTimer, 1 //1000 ); } ScsiPortNotification( NextRequest, HwDeviceExtension, NULL ); return; }
static NTSTATUS NdscCopyQueryOutputToSrb( PMINIPORT_DEVICE_EXTENSION HwDeviceExtension, ULONG CcbBufferLength, PUCHAR CcbBuffer, ULONG SrbIoctlBufferLength, PUCHAR SrbIoctlBuffer ){ NTSTATUS status; PLUR_QUERY lurQuery; lurQuery = (PLUR_QUERY)CcbBuffer; if(CcbBufferLength < FIELD_OFFSET(LUR_QUERY, QueryDataLength)) { return STATUS_INVALID_PARAMETER; } status = STATUS_SUCCESS; switch(lurQuery->InfoClass) { case LurPrimaryLurnInformation: { // NdscPrimaryUnitDiskInformation PLURN_PRIMARYINFORMATION lurPrimaryInfo = (PLURN_PRIMARYINFORMATION)LUR_QUERY_INFORMATION(lurQuery); PNDSCIOCTL_PRIMUNITDISKINFO primUnitDisk = (PNDSCIOCTL_PRIMUNITDISKINFO)SrbIoctlBuffer; if(CcbBufferLength < sizeof(LURN_PRIMARYINFORMATION)) { return STATUS_INVALID_PARAMETER; } if(SrbIoctlBufferLength < sizeof(NDSCIOCTL_PRIMUNITDISKINFO)) { return STATUS_INVALID_PARAMETER; } // // Set length. // primUnitDisk->Length = sizeof(NDSCIOCTL_PRIMUNITDISKINFO); primUnitDisk->UnitDisk.Length = sizeof(NDSC_UNITDISK); // // Adapter information // primUnitDisk->EnabledTime.QuadPart = HwDeviceExtension->EnabledTime.QuadPart; // // LUR information ( Scsi LU information ) // primUnitDisk->Lur.Length = sizeof(NDSC_LUR); primUnitDisk->Lur.DevType = HwDeviceExtension->LURs[0]->DevType; primUnitDisk->Lur.TargetId = HwDeviceExtension->LURs[0]->LurId[1]; primUnitDisk->Lur.Lun = HwDeviceExtension->LURs[0]->LurId[2]; primUnitDisk->Lur.LurnCnt = HwDeviceExtension->LURs[0]->NodeCount; primUnitDisk->Lur.DeviceMode = HwDeviceExtension->LURs[0]->DeviceMode; primUnitDisk->Lur.SupportedFeatures = HwDeviceExtension->LURs[0]->SupportedNdasFeatures; primUnitDisk->Lur.EnabledFeatures = HwDeviceExtension->LURs[0]->EnabledNdasFeatures; // // Unit device // primUnitDisk->UnitDisk.UnitDiskId = lurPrimaryInfo->PrimaryLurn.UnitDiskId; primUnitDisk->UnitDisk.Connections = lurPrimaryInfo->PrimaryLurn.Connections; primUnitDisk->UnitDisk.GrantedAccess = lurPrimaryInfo->PrimaryLurn.AccessRight; RtlCopyMemory( primUnitDisk->UnitDisk.UserID, &lurPrimaryInfo->PrimaryLurn.UserID, sizeof(primUnitDisk->UnitDisk.UserID) ); RtlCopyMemory( primUnitDisk->UnitDisk.Password, &lurPrimaryInfo->PrimaryLurn.Password, sizeof(primUnitDisk->UnitDisk.Password) ); #if 0 RtlCopyMemory( &primUnitDisk->UnitDisk.NetDiskAddress, &lurPrimaryInfo->PrimaryLurn.NetDiskAddress, sizeof(TA_LSTRANS_ADDRESS) ); RtlCopyMemory( &primUnitDisk->UnitDisk.BindingAddress, &lurPrimaryInfo->PrimaryLurn.BindingAddress, sizeof(TA_LSTRANS_ADDRESS) ); #else primUnitDisk->UnitDisk.NetDiskAddress.TAAddressCount = 1; primUnitDisk->UnitDisk.NetDiskAddress.Address[0].AddressLength = lurPrimaryInfo->PrimaryLurn.NdasNetDiskAddress.AddressLength; primUnitDisk->UnitDisk.NetDiskAddress.Address[0].AddressType = lurPrimaryInfo->PrimaryLurn.NdasNetDiskAddress.AddressType; RtlCopyMemory( &primUnitDisk->UnitDisk.NetDiskAddress.Address[0].Address, &lurPrimaryInfo->PrimaryLurn.NdasNetDiskAddress.Address[0], lurPrimaryInfo->PrimaryLurn.NdasNetDiskAddress.AddressLength ); primUnitDisk->UnitDisk.BindingAddress.TAAddressCount = 1; primUnitDisk->UnitDisk.BindingAddress.Address[0].AddressLength = lurPrimaryInfo->PrimaryLurn.NdasBindingAddress.AddressLength; primUnitDisk->UnitDisk.BindingAddress.Address[0].AddressType = lurPrimaryInfo->PrimaryLurn.NdasBindingAddress.AddressType; RtlCopyMemory( &primUnitDisk->UnitDisk.BindingAddress.Address[0].Address, &lurPrimaryInfo->PrimaryLurn.NdasBindingAddress.Address[0], lurPrimaryInfo->PrimaryLurn.NdasBindingAddress.AddressLength ); #endif primUnitDisk->UnitDisk.UnitBlocks = (UINT32)lurPrimaryInfo->PrimaryLurn.UnitBlocks; primUnitDisk->UnitDisk.SlotNo = HwDeviceExtension->SlotNumber; RtlCopyMemory(primUnitDisk->NDSC_ID, lurPrimaryInfo->PrimaryLurn.PrimaryId, LURN_PRIMARY_ID_LENGTH); KDPrint(2,("NDSC_ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", primUnitDisk->NDSC_ID[0], primUnitDisk->NDSC_ID[1], primUnitDisk->NDSC_ID[2], primUnitDisk->NDSC_ID[3], primUnitDisk->NDSC_ID[4], primUnitDisk->NDSC_ID[5], primUnitDisk->NDSC_ID[6], primUnitDisk->NDSC_ID[7], primUnitDisk->NDSC_ID[8], primUnitDisk->NDSC_ID[9], primUnitDisk->NDSC_ID[10], primUnitDisk->NDSC_ID[11], primUnitDisk->NDSC_ID[12], primUnitDisk->NDSC_ID[13], primUnitDisk->NDSC_ID[14], primUnitDisk->NDSC_ID[15]) ); break; } case LurEnumerateLurn: { // NdscLurInformation PLURN_ENUM_INFORMATION lurnEnumInfo = (PLURN_ENUM_INFORMATION)LUR_QUERY_INFORMATION(lurQuery); PNDSCIOCTL_LURINFO info = (PNDSCIOCTL_LURINFO)SrbIoctlBuffer; NDAS_DEV_ACCESSMODE deviceMode; NDAS_FEATURES supportedNdasFeatures, enabledNdasFeatures; PNDSC_LURN_FULL unitDisk; ULONG idx_lurn; PLURN_INFORMATION lurnInformation; ULONG returnLength; UINT32 nodeCount; if(CcbBufferLength < sizeof(LURN_PRIMARYINFORMATION)) { return STATUS_INVALID_PARAMETER; } if(SrbIoctlBufferLength < FIELD_OFFSET(NDSCIOCTL_LURINFO, Reserved1)) { return STATUS_INVALID_PARAMETER; } if (HwDeviceExtension->LURs[0]) { ASSERT(HwDeviceExtension->LURs[0]->NodeCount >= 1); deviceMode = HwDeviceExtension->LURs[0]->DeviceMode; supportedNdasFeatures = HwDeviceExtension->LURs[0]->SupportedNdasFeatures; enabledNdasFeatures = HwDeviceExtension->LURs[0]->EnabledNdasFeatures; nodeCount = HwDeviceExtension->LURs[0]->NodeCount; } else { deviceMode = 0; supportedNdasFeatures = 0; enabledNdasFeatures = 0; nodeCount = 0; } // // Adapter information // info->Length = FIELD_OFFSET(NDSCIOCTL_LURINFO, Lurns) + sizeof(NDSC_LURN_FULL) * nodeCount; // return length check returnLength = FIELD_OFFSET(NDSCIOCTL_LURINFO, Lurns); if(SrbIoctlBufferLength < returnLength) { return STATUS_BUFFER_TOO_SMALL; } info->EnabledTime.QuadPart = HwDeviceExtension->EnabledTime.QuadPart; info->Lur.Length = sizeof(NDSC_LUR); info->Lur.DevType = HwDeviceExtension->LURs[0]->DevType; info->Lur.TargetId = HwDeviceExtension->LURs[0]->LurId[1]; info->Lur.Lun = HwDeviceExtension->LURs[0]->LurId[2]; info->Lur.LurnCnt = HwDeviceExtension->LURs[0]->NodeCount; info->LurnCnt = info->Lur.LurnCnt; info->Lur.DeviceMode = deviceMode; info->Lur.SupportedFeatures = supportedNdasFeatures; info->Lur.EnabledFeatures = enabledNdasFeatures; // // Set return values for each LURN. // for(idx_lurn = 0; idx_lurn < info->LurnCnt; idx_lurn++) { // // Add one LURN to return bytes and check the user buffer size. // returnLength += sizeof(NDSC_LURN_FULL); if(SrbIoctlBufferLength < returnLength) { status = STATUS_BUFFER_TOO_SMALL; // Do not exit. Must return full length. continue; } unitDisk = info->Lurns + idx_lurn; lurnInformation = lurnEnumInfo->Lurns + idx_lurn; unitDisk->Length = sizeof(NDSC_LURN_FULL); unitDisk->UnitDiskId = lurnInformation->UnitDiskId; unitDisk->Connections = lurnInformation->Connections; unitDisk->AccessRight = lurnInformation->AccessRight; unitDisk->UnitBlocks = lurnInformation->UnitBlocks; unitDisk->StatusFlags = lurnInformation->StatusFlags; unitDisk->LurnId = lurnInformation->LurnId; unitDisk->LurnType = lurnInformation->LurnType; unitDisk->StatusFlags = lurnInformation->StatusFlags; RtlCopyMemory( unitDisk->UserID, &lurnInformation->UserID, sizeof(unitDisk->UserID) ); RtlCopyMemory( unitDisk->Password, &lurnInformation->Password, sizeof(unitDisk->Password) ); #if 0 RtlCopyMemory( &unitDisk->NetDiskAddress, &lurnInformation->NetDiskAddress, sizeof(TA_LSTRANS_ADDRESS) ); RtlCopyMemory( &unitDisk->BindingAddress, &lurnInformation->BindingAddress, sizeof(TA_LSTRANS_ADDRESS) ); #else unitDisk->NetDiskAddress.TAAddressCount = 1; unitDisk->NetDiskAddress.Address[0].AddressLength = lurnInformation->NdasNetDiskAddress.AddressLength; unitDisk->NetDiskAddress.Address[0].AddressType = lurnInformation->NdasNetDiskAddress.AddressType; RtlCopyMemory( &unitDisk->NetDiskAddress.Address[0].Address, &lurnInformation->NdasNetDiskAddress.Address[0], lurnInformation->NdasNetDiskAddress.AddressLength ); unitDisk->BindingAddress.TAAddressCount = 1; unitDisk->BindingAddress.Address[0].AddressLength = lurnInformation->NdasBindingAddress.AddressLength; unitDisk->BindingAddress.Address[0].AddressType = lurnInformation->NdasBindingAddress.AddressType; RtlCopyMemory( &unitDisk->BindingAddress.Address[0].Address, &lurnInformation->NdasBindingAddress.Address[0], lurnInformation->NdasBindingAddress.AddressLength ); #endif } break; } default: status = STATUS_INVALID_PARAMETER; break; } return status; }
NTSTATUS LanscsiMiniportCompletion( IN PCCB Ccb, IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension ) { KIRQL oldIrql; static LONG SrbSeq; LONG srbSeqIncremented; PSCSI_REQUEST_BLOCK srb; PCCB abortCcb; NTSTATUS return_status; KDPrint(3,("RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting)); srb = Ccb->Srb; if(!srb) { KDPrint(1,("Ccb:%p CcbStatus %d. No srb assigned.\n", Ccb, Ccb->CcbStatus)); ASSERT(srb); return STATUS_SUCCESS; } // // LanscsiMiniport completion routine will do post operation to complete CCBs. // return_status = STATUS_MORE_PROCESSING_REQUIRED; srbSeqIncremented = InterlockedIncrement(&SrbSeq); // // check to see if this CCB was sent before BusReset occurs. // TODO: we need to calculate the accurate BUSRESET_EFFECT_TICKCOUNT. // ASSERT(Ccb->CreateTime.QuadPart); KDPrint(3,("!!!!! SRB:%p CCB:%p CCB->CreateTime: %I64u!!!!!!\n", srb, Ccb, Ccb->CreateTime.QuadPart)); ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); if( Ccb->CreateTime.QuadPart <= HwDeviceExtension->LastBusResetTime.QuadPart + BUSRESET_EFFECT_TICKCOUNT || ADAPTER_ISSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_BUSRESET_PENDING) ) { ADAPTER_RESETSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_BUSRESET_PENDING); RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); KDPrint(1,("!!!!!! BusReset occured after this CCB has entered." " Make it completed with Timer. CCB->CreateTime: %I64u!!!!!!\n", Ccb->CreateTime.QuadPart)); LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); } else { RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); } // // Check reconnecting process. // Translate CCB to SRB. // if(LSCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RECONNECTING)) { ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); if(!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_RECONNECTPENDING)) { UINT32 AdapterStatus; AdapterStatus = ADAPTER_SETSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_RECONNECTPENDING); RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); UpdatePdoInfoInLSBus(HwDeviceExtension, AdapterStatus); KDPrint(1,("Ccb:%p CcbStatus %d. Start reconnecting\n", Ccb, Ccb->CcbStatus)); } else { RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); } } else { // // If CCbStatus != CCB_STATUS_STOP, reconnecting is successful. // if(Ccb->CcbStatus != CCB_STATUS_STOP) { ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); if(ADAPTER_ISSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_RECONNECTPENDING)) { UINT32 AdapterStatus; AdapterStatus = ADAPTER_RESETSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_RECONNECTPENDING); RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); UpdatePdoInfoInLSBus(HwDeviceExtension, AdapterStatus); KDPrint(1,("Ccb:%p CcbStatus %d. Finish reconnecting\n", Ccb, Ccb->CcbStatus)); } else { RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); } } } // // If CCB_OPCODE_UPDATE is successful, update adapter status in LanscsiBus // if(Ccb->OperationCode == CCB_OPCODE_UPDATE && Ccb->CcbStatus == CCB_STATUS_SUCCESS) { UINT32 AdapterStatus; ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); AdapterStatus = HwDeviceExtension->AdapterStatus; RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); UpdatePdoInfoInLSBus(HwDeviceExtension, AdapterStatus); } KDPrint(3,("CcbStatus %d\n", Ccb->CcbStatus)); // // Translate CcbStatus to SrbStatus // switch(Ccb->CcbStatus) { case CCB_STATUS_SUCCESS: srb->SrbStatus = SRB_STATUS_SUCCESS; srb->ScsiStatus = SCSISTAT_GOOD; // // Check to see if the associate member is in error. // if(LSCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_LURN_STOP)) { ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); if(!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_MEMBER_FAULT)) { UINT32 AdapterStatus; AdapterStatus = ADAPTER_SETSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_MEMBER_FAULT); RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); UpdatePdoInfoInLSBus(HwDeviceExtension, AdapterStatus); KDPrint(1,("Ccb:%p CcbStatus %d. Associate member is in error.\n", Ccb, Ccb->CcbStatus)); // // Send DisconEvent to the service. // TODO: alternate to AlarmEvent. // KeSetEvent(HwDeviceExtension->DisconEventToService, IO_NO_INCREMENT, FALSE); } else { RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); } } break; case CCB_STATUS_NOT_EXIST: srb->SrbStatus = SRB_STATUS_NO_DEVICE; srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_INVALID_COMMAND: srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_COMMAND_FAILED: srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID; srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; srb->DataTransferLength -= Ccb->ResidualDataLength; break; // Added by ILGU HONG 2004_07_05 case CCB_STATUS_COMMMAND_DONE_SENSE: srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID ; srb->DataTransferLength = 0; srb->ScsiStatus = SCSISTAT_GOOD; break; // Added by ILGU HONG 2004_07_05 end case CCB_STATUS_RESET: srb->SrbStatus = SRB_STATUS_BUS_RESET; srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_COMMUNICATION_ERROR: { PSENSE_DATA senseData; srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID; srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; srb->DataTransferLength = 0; senseData = srb->SenseInfoBuffer; senseData->ErrorCode = 0x70; senseData->Valid = 1; //senseData->SegmentNumber = 0; senseData->SenseKey = SCSI_SENSE_HARDWARE_ERROR; //SCSI_SENSE_MISCOMPARE; //senseData->IncorrectLength = 0; //senseData->EndOfMedia = 0; //senseData->FileMark = 0; senseData->AdditionalSenseLength = 0xb; senseData->AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE; senseData->AdditionalSenseCodeQualifier = 0; } break; case CCB_STATUS_BUSY: srb->SrbStatus = SRB_STATUS_BUSY; srb->ScsiStatus = SCSISTAT_GOOD; KDPrint(1,("CCB_STATUS_BUSY\n")); break; // // Stop one LUR // case CCB_STATUS_STOP: { KDPrint(1,("CCB_STATUS_STOP. Stopping!\n")); srb->SrbStatus = SRB_STATUS_NO_DEVICE; srb->ScsiStatus = SCSISTAT_GOOD; MiniStopAdapter(HwDeviceExtension, TRUE); break; } default: // Error in Connection... // CCB_STATUS_UNKNOWN_STATUS, CCB_STATUS_RESET, and so on. srb->SrbStatus = SRB_STATUS_ERROR; srb->ScsiStatus = SCSISTAT_GOOD; } // // Process Abort CCB. // abortCcb = Ccb->AbortCcb; if(abortCcb != NULL) { KDPrint(1,("abortSrb\n")); ASSERT(FALSE); srb->SrbStatus = SRB_STATUS_SUCCESS; LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); InitializeListHead(&Ccb->ListEntry); ExInterlockedInsertTailList( &HwDeviceExtension->CcbCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbCompletionListSpinLock ); ((PSCSI_REQUEST_BLOCK)abortCcb->Srb)->SrbStatus = SRB_STATUS_ABORTED; LSCcbSetStatusFlag(abortCcb, CCBSTATUS_FLAG_TIMER_COMPLETE); InitializeListHead(&abortCcb->ListEntry); ExInterlockedInsertTailList( &HwDeviceExtension->CcbCompletionList, &abortCcb->ListEntry, &HwDeviceExtension->CcbCompletionListSpinLock ); } else { // // Make Complete IRP and Send it. // // // In case of HostStatus == CCB_STATUS_SUCCESS_TIMER, CCB will go to the timer to complete. // if( (Ccb->CcbStatus == CCB_STATUS_SUCCESS || Ccb->CcbStatus == CCB_STATUS_INVALID_COMMAND) && !LSCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE) && !LSCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_BUSRESET_REQUIRED) ) { PDEVICE_OBJECT pDeviceObject = HwDeviceExtension->ScsiportFdoObject; PIRP pCompletionIrp = NULL; PIO_STACK_LOCATION pIoStack; NTSTATUS ntStatus; PSCSI_REQUEST_BLOCK completionSrb = NULL; PCOMPLETION_DATA completionData = NULL; completionSrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK), LSMP_PTAG_SRB); if(completionSrb == NULL) goto Out; RtlZeroMemory( completionSrb, sizeof(SCSI_REQUEST_BLOCK) ); // Build New IRP. pCompletionIrp = IoAllocateIrp((CCHAR)(pDeviceObject->StackSize + 1), FALSE); if(pCompletionIrp == NULL) { ExFreePoolWithTag(completionSrb, LSMP_PTAG_SRB); goto Out; } completionData = ExAllocatePoolWithTag(NonPagedPool, sizeof(COMPLETION_DATA), LSMP_PTAG_CMPDATA); if(completionData == NULL) { ExFreePoolWithTag(completionSrb, LSMP_PTAG_SRB); IoFreeIrp(pCompletionIrp); pCompletionIrp = NULL; goto Out; } pCompletionIrp->MdlAddress = NULL; // Set IRP stack location. pIoStack = IoGetNextIrpStackLocation(pCompletionIrp); pIoStack->DeviceObject = pDeviceObject; pIoStack->MajorFunction = IRP_MJ_SCSI; pIoStack->Parameters.DeviceIoControl.InputBufferLength = 0; pIoStack->Parameters.DeviceIoControl.OutputBufferLength = 0; pIoStack->Parameters.Scsi.Srb = completionSrb; // Set SRB. completionSrb->Length = sizeof(SCSI_REQUEST_BLOCK); completionSrb->Function = SRB_FUNCTION_EXECUTE_SCSI; completionSrb->PathId = srb->PathId; completionSrb->TargetId = srb->TargetId; completionSrb->Lun = srb->Lun; completionSrb->QueueAction = SRB_SIMPLE_TAG_REQUEST; completionSrb->DataBuffer = srb; completionSrb->SrbFlags |= SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE; completionSrb->OriginalRequest = pCompletionIrp; completionSrb->CdbLength = MAXIMUM_CDB_SIZE; completionSrb->Cdb[0] = SCSIOP_COMPLETE; completionSrb->Cdb[1] = (UCHAR)srbSeqIncremented; completionSrb->TimeOutValue = 20; completionSrb->SrbStatus = SRB_STATUS_SUCCESS; // // Set compeltion data for the completion IRP. // completionData->HwDeviceExtension = HwDeviceExtension; completionData->CompletionSrb = completionSrb; completionData->ShippedCcb = Ccb; completionData->ShippedCcbAllocatedFromPool = LSCcbIsFlagOn(Ccb, CCB_FLAG_ALLOCATED); Out: KDPrint(4,("Before Completion\n")); if(pCompletionIrp) { IoSetCompletionRoutine(pCompletionIrp, CompletionIrpCompletionRoutine, completionData, TRUE, TRUE, TRUE); ASSERT(HwDeviceExtension->RequestExecuting != 0); // // call Scsiport FDO. // ntStatus = IoCallDriver(pDeviceObject, pCompletionIrp); ASSERT(NT_SUCCESS(ntStatus)); #if DBG if(ntStatus!= STATUS_SUCCESS && ntStatus!= STATUS_PENDING) { KDPrint(1,("ntStatus = 0x%x\n", ntStatus)); } #endif }else { KDPrint(1,("CompletionIRP NULL. CCB(%p) and SRB(%p) is going to the timer. CcbStatus:%x CcbFlag:%x\n", Ccb, Ccb->Srb, Ccb->CcbStatus, Ccb->Flags)); InitializeListHead(&Ccb->ListEntry); LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); ExInterlockedInsertTailList( &HwDeviceExtension->CcbCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbCompletionListSpinLock ); } } else { KDPrint(1,("CCB(%p) and SRB(%p) is going to the timer. CcbStatus:%x CcbFlag:%x\n", Ccb, Ccb->Srb, Ccb->CcbStatus, Ccb->Flags)); InitializeListHead(&Ccb->ListEntry); LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); ExInterlockedInsertTailList( &HwDeviceExtension->CcbCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbCompletionListSpinLock ); } } return return_status; }
NTSTATUS NdasDluSendIoctlSrb( IN PDEVICE_OBJECT DeviceObject, IN ULONG IoctlCode, IN PVOID InputBuffer, IN LONG InputBufferLength, OUT PVOID OutputBuffer, IN LONG OutputBufferLength ) { PIRP irp; KEVENT event; PSRB_IO_CONTROL psrbIoctl; LONG srbIoctlLength; PVOID srbIoctlBuffer; LONG srbIoctlBufferLength; NTSTATUS status; PIO_STACK_LOCATION irpStack; SCSI_REQUEST_BLOCK srb; LARGE_INTEGER startingOffset; IO_STATUS_BLOCK ioStatusBlock; ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); psrbIoctl = NULL; irp = NULL; // // build an SRB for the miniport // srbIoctlBufferLength = (InputBufferLength>OutputBufferLength)?InputBufferLength:OutputBufferLength; srbIoctlLength = sizeof(SRB_IO_CONTROL) + srbIoctlBufferLength; psrbIoctl = (PSRB_IO_CONTROL)ExAllocatePoolWithTag(NonPagedPool , srbIoctlLength, NDAS_DLU_PTAG_SRB_IOCTL); if(psrbIoctl == NULL) { KDPrint(1, ("STATUS_INSUFFICIENT_RESOURCES\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } RtlZeroMemory(psrbIoctl, srbIoctlLength); psrbIoctl->HeaderLength = sizeof(SRB_IO_CONTROL); RtlCopyMemory(psrbIoctl->Signature, NDASSCSI_IOCTL_SIGNATURE, 8); psrbIoctl->Timeout = 10; psrbIoctl->ControlCode = IoctlCode; psrbIoctl->Length = srbIoctlBufferLength; srbIoctlBuffer = (PUCHAR)psrbIoctl + sizeof(SRB_IO_CONTROL); RtlCopyMemory(srbIoctlBuffer, InputBuffer, InputBufferLength); // // Initialize the notification event. // KeInitializeEvent(&event, NotificationEvent, FALSE); startingOffset.QuadPart = 1; // // Build IRP for this request. // Note we do this synchronously for two reasons. If it was done // asynchronously then the completion code would have to make a special // check to deallocate the buffer. Second if a completion routine were // used then an additional IRP stack location would be needed. // irp = IoBuildSynchronousFsdRequest( IRP_MJ_SCSI, DeviceObject, psrbIoctl, srbIoctlLength, &startingOffset, &event, &ioStatusBlock); irpStack = IoGetNextIrpStackLocation(irp); if (irp == NULL) { KDPrint(1,("STATUS_INSUFFICIENT_RESOURCES\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } // // Set major and minor codes. // irpStack->MajorFunction = IRP_MJ_SCSI; irpStack->MinorFunction = 1; // // Fill in SRB fields. // irpStack->Parameters.Others.Argument1 = &srb; // // Zero out the srb. // RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); srb.PathId = 0; srb.TargetId = 0; srb.Lun = 0; srb.Function = SRB_FUNCTION_IO_CONTROL; srb.Length = sizeof(SCSI_REQUEST_BLOCK); srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE; srb.QueueAction = SRB_SIMPLE_TAG_REQUEST; srb.QueueTag = SP_UNTAGGED; srb.OriginalRequest = irp; // // Set timeout to requested value. // srb.TimeOutValue = psrbIoctl->Timeout; // // Set the data buffer. // srb.DataBuffer = psrbIoctl; srb.DataTransferLength = srbIoctlLength; // // Flush the data buffer for output. This will insure that the data is // written back to memory. Since the data-in flag is the the port driver // will flush the data again for input which will ensure the data is not // in the cache. // /* KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE); */ status = IoCallDriver( DeviceObject, irp ); // // Wait for request to complete. // if (status == STATUS_PENDING) { (VOID)KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL ); status = ioStatusBlock.Status; } // // get the result // if(status == STATUS_SUCCESS) { if(OutputBuffer && OutputBufferLength) RtlCopyMemory(OutputBuffer, srbIoctlBuffer, OutputBufferLength); KDPrint(1,("Ioctl(%08lx) succeeded!\n", IoctlCode)); } cleanup: if(psrbIoctl) ExFreePool(psrbIoctl); return status; }
NTSTATUS LsuConfigureIdeDisk( IN PLANSCSI_SESSION LSS, IN UCHAR UdmaRestrict, OUT PULONG PduFlags, OUT PBOOLEAN Dma, OUT PULONG BlockBytes ){ NTSTATUS status; struct hd_driveid info; ULONG pduFlags; BOOLEAN setDmaMode; ULONG blockBytes; LANSCSI_PDUDESC pduDesc; UCHAR pduResponse; // // Get identify // status = LsuGetIdentify(LSS, &info); if(!NT_SUCCESS(status)) { KDPrint(1, ("LsuGetIdentify(1) failed. NTSTATUS: %08lx.\n", status)); return status; } // // IO mode: DMA/PIO Mode. // KDPrintM(DBG_OTHER_INFO, ("Major 0x%x, Minor 0x%x, Capa 0x%x\n", info.major_rev_num, info.minor_rev_num, info.capability)); KDPrintM(DBG_OTHER_INFO, ("DMA 0x%x, U-DMA 0x%x\n", info.dma_mword, info.dma_ultra)); // // determine IO mode ( UltraDMA, DMA, and PIO ) according to hardware versions and disk capacity. // setDmaMode = FALSE; pduFlags = 0; blockBytes = 512; do { UCHAR DmaFeature; UCHAR DmaMode; DmaFeature = 0; DmaMode = 0; // // Ultra DMA if NDAS chip is 2.0 or higher. // /* We don't support UDMA for 2.0 rev 0 due to the bug. The bug : Written data using UDMA will be corrupted */ if ( (info.dma_ultra & 0x00ff) && ( (LANSCSIIDE_VERSION_2_0 < LSS->HWVersion) || ((LANSCSIIDE_VERSION_2_0 == LSS->HWVersion) && (0 != LSS->HWRevision)) )) { // Find Fastest Mode. if(info.dma_ultra & 0x0001) DmaMode = 0; if(info.dma_ultra & 0x0002) DmaMode = 1; if(info.dma_ultra & 0x0004) DmaMode = 2; // if Cable80, try higher Ultra Dma Mode. #ifdef __DETECT_CABLE80__ if(info.hw_config & 0x2000) { #endif if(info.dma_ultra & 0x0008) DmaMode = 3; if(info.dma_ultra & 0x0010) DmaMode = 4; if(info.dma_ultra & 0x0020) DmaMode = 5; if(info.dma_ultra & 0x0040) DmaMode = 6; if(info.dma_ultra & 0x0080) DmaMode = 7; // // If the ndas device is version 2.0 revision 100Mbps, // Restrict UDMA to mode 2. // if (LSS->HWVersion == LANSCSIIDE_VERSION_2_0 && LSS->HWRevision == LANSCSIIDE_VER20_REV_100M) { if(DmaMode > 2) DmaMode = 2; } // // Restrict UDMA mode when requested. // if(UdmaRestrict != 0xff) { if(DmaMode > UdmaRestrict) { DmaMode = UdmaRestrict; KDPrintM(DBG_LURN_INFO, ("UDMA restriction applied. UDMA=%d\n", (ULONG)DmaMode)); } } #ifdef __DETECT_CABLE80__ } #endif KDPrintM(DBG_OTHER_INFO, ("Ultra DMA %d detected.\n", (int)DmaMode)); DmaFeature = DmaMode | 0x40; // Ultra DMA mode. pduFlags |= PDUDESC_FLAG_DMA|PDUDESC_FLAG_UDMA; // Set Ultra DMA mode if needed if(!(info.dma_ultra & (0x0100 << DmaMode))) { setDmaMode = TRUE; } // // detect DMA // Lower 8 bits of dma_mword represent supported dma modes. // } else if(info.dma_mword & 0x00ff) { if(info.dma_mword & 0x0001) DmaMode = 0; if(info.dma_mword & 0x0002) DmaMode = 1; if(info.dma_mword & 0x0004) DmaMode = 2; KDPrintM(DBG_OTHER_INFO, ("DMA mode %d detected.\n", (int)DmaMode)); DmaFeature = DmaMode | 0x20; pduFlags |= PDUDESC_FLAG_DMA; // Set DMA mode if needed if(!(info.dma_mword & (0x0100 << DmaMode))) { setDmaMode = TRUE; } } // Set DMA mode if needed. if(setDmaMode) { LSS_INITIALIZE_PDUDESC(LSS, &pduDesc, IDE_COMMAND, WIN_SETFEATURES, 0, 0, 0, 0, NULL, NULL); pduDesc.Feature = SETFEATURES_XFER; pduDesc.BlockCount = DmaFeature; status = LspRequest(LSS, &pduDesc, &pduResponse); if(!NT_SUCCESS(status)) { KDPrintM(DBG_OTHER_ERROR, ("Set Feature Failed...\n")); return status; } if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_OTHER_ERROR, ("SETFEATURES: PduResponse=%x\n", (ULONG)pduResponse)); return STATUS_UNSUCCESSFUL; } // identify. status = LsuGetIdentify(LSS, &info); if(!NT_SUCCESS(status)) { KDPrint(1, ("LsuGetIdentify(2) failed. NTSTATUS: %08lx.\n", status)); return status; } KDPrintM(DBG_OTHER_INFO, ("After Set Feature DMA 0x%x, U-DMA 0x%x\n", info.dma_mword, info.dma_ultra)); } if(pduFlags & PDUDESC_FLAG_DMA) { break; } // // PIO. // KDPrintM(DBG_OTHER_ERROR, ("NetDisk does not support DMA mode. Turn to PIO mode.\n")); pduFlags |= PDUDESC_FLAG_PIO; } while(0); // // Bytes of sector // blockBytes = AtaGetBytesPerBlock(&info); // // LBA support // if(!(info.capability & 0x02)) { pduFlags &= ~PDUDESC_FLAG_LBA; ASSERT(FALSE); } else { pduFlags |= PDUDESC_FLAG_LBA; } // // LBA48 support // if(info.command_set_2 & 0x0400 || info.cfs_enable_2 & 0x0400) { // Support LBA48bit pduFlags |= PDUDESC_FLAG_LBA48; // // If LBA48 is on, LBA is also on. // pduFlags |= PDUDESC_FLAG_LBA; } KDPrint(1, ("LBA support: LBA %d, LBA48 %d\n", (pduFlags & PDUDESC_FLAG_LBA) != 0, (pduFlags & PDUDESC_FLAG_LBA48) != 0 )); // // Set return values // if(PduFlags) { *PduFlags = pduFlags; } if(Dma) { if(pduFlags & (PDUDESC_FLAG_DMA|PDUDESC_FLAG_UDMA)) { *Dma = TRUE; } else { *Dma = FALSE; } } if(BlockBytes) { *BlockBytes = blockBytes; } return status; }
NTSTATUS NdasDluSendIoctlSrbAsynch( IN PDEVICE_OBJECT DeviceObject, IN ULONG IoctlCode, IN PVOID InputBuffer, IN LONG InputBufferLength, OUT PVOID OutputBuffer, IN LONG OutputBufferLength ){ PIRP irp; PMINISENDSRB_CONTEXT context = NULL; PSRB_IO_CONTROL psrbIoctl; PSCSI_REQUEST_BLOCK srb; LONG srbIoctlLength; PVOID srbIoctlBuffer; LONG srbIoctlBufferLength; NTSTATUS status; PIO_STACK_LOCATION irpStack; LARGE_INTEGER startingOffset; IO_STATUS_BLOCK ioStatusBlock; ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); psrbIoctl = NULL; irp = NULL; // // build an SRB for the miniport // srbIoctlBufferLength = (InputBufferLength>OutputBufferLength)?InputBufferLength:OutputBufferLength; srbIoctlLength = sizeof(SRB_IO_CONTROL) + srbIoctlBufferLength; context = (PMINISENDSRB_CONTEXT)ExAllocatePoolWithTag(NonPagedPool, FIELD_OFFSET(MINISENDSRB_CONTEXT, SrbIoctl) + srbIoctlLength, NDAS_DLU_PTAG_SRB_CMPDATA); if(context == NULL) { KDPrint(1, ("STATUS_INSUFFICIENT_RESOURCES\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } context->UserBuffer = OutputBuffer; context->UserBufferLen = OutputBufferLength; srb = &context->Srb; psrbIoctl = &context->SrbIoctl; RtlZeroMemory(psrbIoctl, srbIoctlLength); psrbIoctl->HeaderLength = sizeof(SRB_IO_CONTROL); RtlCopyMemory(psrbIoctl->Signature, NDASSCSI_IOCTL_SIGNATURE, 8); psrbIoctl->Timeout = 10; psrbIoctl->ControlCode = IoctlCode; psrbIoctl->Length = srbIoctlBufferLength; srbIoctlBuffer = (PUCHAR)psrbIoctl + sizeof(SRB_IO_CONTROL); RtlCopyMemory(srbIoctlBuffer, InputBuffer, InputBufferLength); startingOffset.QuadPart = 1; // // Build IRP for this request. // Note we do this synchronously for two reasons. If it was done // asynchronously then the completion code would have to make a special // check to deallocate the buffer. Second if a completion routine were // used then an additional IRP stack location would be needed. // irp = IoBuildAsynchronousFsdRequest( IRP_MJ_SCSI, DeviceObject, psrbIoctl, srbIoctlLength, &startingOffset, &ioStatusBlock); context->Irp = irp; IoSetCompletionRoutine(irp, NdasDluSendSrbIoCompletion, context, TRUE, TRUE, TRUE); irpStack = IoGetNextIrpStackLocation(irp); if (irp == NULL) { KDPrint(1,("STATUS_INSUFFICIENT_RESOURCES\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } // // Set major and minor codes. // irpStack->MajorFunction = IRP_MJ_SCSI; irpStack->MinorFunction = 1; // // Fill in SRB fields. // irpStack->Parameters.Others.Argument1 = srb; // // Zero out the srb. // RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); srb->PathId = 0; srb->TargetId = 0; srb->Lun = 0; srb->Function = SRB_FUNCTION_IO_CONTROL; srb->Length = sizeof(SCSI_REQUEST_BLOCK); srb->SrbFlags = SRB_FLAGS_DATA_OUT | SRB_FLAGS_NO_QUEUE_FREEZE; srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; srb->QueueTag = SP_UNTAGGED; srb->OriginalRequest = irp; // // Set timeout to requested value. // srb->TimeOutValue = psrbIoctl->Timeout; // // Set the data buffer. // srb->DataBuffer = psrbIoctl; srb->DataTransferLength = srbIoctlLength; // // Flush the data buffer for output. This will insure that the data is // written back to memory. Since the data-in flag is the the port driver // will flush the data again for input which will ensure the data is not // in the cache. // /* KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE); */ status = IoCallDriver( DeviceObject, irp ); return status; cleanup: if(context) ExFreePool(context); return status; }
////////////////////////////////////////////////////////////////////////// // // Event log // static VOID _WriteLogErrorEntry( IN PDEVICE_OBJECT DeviceObject, IN PLSU_ERROR_LOG_ENTRY LogEntry ){ PIO_ERROR_LOG_PACKET errorLogEntry; WCHAR strBuff[16]; NTSTATUS status; ULONG stringOffset; ULONG_PTR stringLen; ULONG idx_dump; // // Parameter to unicode string // ASSERT(LogEntry->DumpDataEntry <= LSU_MAX_ERRLOG_DATA_ENTRIES); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); status = RtlStringCchPrintfW(strBuff, 16, L"%u", LogEntry->Parameter2); if(!NT_SUCCESS(status)) { KDPrint(1, ("RtlStringCchVPrintfW() failed.\n")); return; } status = RtlStringCchLengthW(strBuff, 16, &stringLen); if(!NT_SUCCESS(status)) { KDPrint(1, ("RtlStringCchLengthW() failed.\n")); return; } // // Translate unicode length into byte length including NULL termination. // stringLen = ( stringLen + 1 ) * sizeof(WCHAR); stringOffset = FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + LogEntry->DumpDataEntry * sizeof(ULONG); errorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry( DeviceObject, (sizeof(IO_ERROR_LOG_PACKET) + (LogEntry->DumpDataEntry * sizeof(ULONG)) + (UCHAR)stringLen)); if(errorLogEntry == NULL) { KDPrint(1, ("Could not allocate error log entry.\n")); ASSERT(FALSE); return ; } errorLogEntry->ErrorCode = LogEntry->ErrorCode; errorLogEntry->MajorFunctionCode = LogEntry->MajorFunctionCode; errorLogEntry->IoControlCode = LogEntry->IoctlCode; errorLogEntry->EventCategory; errorLogEntry->SequenceNumber = LogEntry->SequenceNumber; errorLogEntry->RetryCount = (UCHAR) LogEntry->ErrorLogRetryCount; errorLogEntry->UniqueErrorValue = LogEntry->UniqueId; errorLogEntry->FinalStatus = STATUS_SUCCESS; errorLogEntry->DumpDataSize = LogEntry->DumpDataEntry * sizeof(ULONG); for(idx_dump=0; idx_dump < LogEntry->DumpDataEntry; idx_dump++) { errorLogEntry->DumpData[idx_dump] = LogEntry->DumpData[idx_dump]; } errorLogEntry->NumberOfStrings = 1; errorLogEntry->StringOffset = (USHORT)stringOffset; RtlCopyMemory((PUCHAR)errorLogEntry + stringOffset, strBuff, stringLen); IoWriteErrorLogEntry(errorLogEntry); return; }
UCHAR NdasDluSrbIoctlGetDVDSTatus( PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension, PNDAS_DLU_EXTENSION DluLuExtension, ULONG OutputBufferLength, PUCHAR OutputBuffer, PNTSTATUS NtStatus ) { UCHAR status; PCCB Ccb; NTSTATUS ntStatus; PNDASBUS_DVD_STATUS DvdStatusInfo = (PNDASBUS_DVD_STATUS)OutputBuffer; BYTE LurBuffer[sizeof(LURN_DVD_STATUS)]; PLURN_DVD_STATUS pDvdStatusHeader; UNREFERENCED_PARAMETER(LogicalUnitExtension); KDPrint(1,("\n")); if(OutputBufferLength < sizeof(NDASBUS_DVD_STATUS)) { KDPrint(1,("Too small output buffer\n")); *NtStatus = STATUS_BUFFER_TOO_SMALL; status = SRB_STATUS_INVALID_REQUEST; return status; } // // Query to the LUR // ntStatus = LsCcbAllocate(&Ccb); if(!NT_SUCCESS(ntStatus)) { KDPrint(1,("LsCcbAllocate() failed.\n")); *NtStatus = STATUS_INSUFFICIENT_RESOURCES; status = SRB_STATUS_INVALID_REQUEST; return status; } Ccb->OperationCode = CCB_OPCODE_DVD_STATUS; LsCcbSetFlag(Ccb, CCB_FLAG_SYNCHRONOUS|CCB_FLAG_ALLOCATED); Ccb->DataBuffer = LurBuffer; Ccb->DataBufferLength = sizeof(LURN_DVD_STATUS); pDvdStatusHeader = (PLURN_DVD_STATUS)LurBuffer; pDvdStatusHeader->Length = sizeof(LURN_DVD_STATUS); ntStatus = LurRequest( DluLuExtension->LUR, Ccb ); if(!NT_SUCCESS(ntStatus)) { LsCcbFree(Ccb); KDPrint(1,("LurnRequest() failed.\n")); *NtStatus = STATUS_INSUFFICIENT_RESOURCES; status = SRB_STATUS_INVALID_REQUEST; return status; } // // Set return values. // KDPrint(1,("Last Access Time :%I64d\n",pDvdStatusHeader->Last_Access_Time.QuadPart)); KDPrint(1,("Result %d\n",pDvdStatusHeader->Status)); DvdStatusInfo->Status = pDvdStatusHeader->Status; *NtStatus = STATUS_SUCCESS; return SRB_STATUS_SUCCESS; }
// // General ioctl to NDASBUS // NTSTATUS IoctlToLanscsiBus( IN ULONG IoControlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, OUT PULONG BufferNeeded ) { NTSTATUS ntStatus; PWSTR symbolicLinkList; UNICODE_STRING objectName; PFILE_OBJECT fileObject; PDEVICE_OBJECT deviceObject; PIRP irp; KEVENT event; IO_STATUS_BLOCK ioStatus; KDPrint(3,("IoControlCode = %x\n", IoControlCode)); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); ntStatus = IoGetDeviceInterfaces( &GUID_NDAS_BUS_ENUMERATOR_INTERFACE_CLASS, NULL, 0, &symbolicLinkList ); if(!NT_SUCCESS(ntStatus)) { KDPrint(2,("IoGetDeviceInterfaces ntStatus = 0x%x\n", ntStatus)); return ntStatus; } ASSERT(symbolicLinkList != NULL); KDPrint(2,("symbolicLinkList = %ws\n", symbolicLinkList)); RtlInitUnicodeString(&objectName, symbolicLinkList); ntStatus = IoGetDeviceObjectPointer( &objectName, FILE_ALL_ACCESS, &fileObject, &deviceObject ); if(!NT_SUCCESS(ntStatus)) { KDPrint(2,("ntStatus = 0x%x\n", ntStatus)); ExFreePool(symbolicLinkList); return ntStatus; } KeInitializeEvent(&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest( IoControlCode, deviceObject, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, FALSE, &event, &ioStatus ); if (irp == NULL) { KDPrint(2,("irp NULL\n")); ExFreePool(symbolicLinkList); ObDereferenceObject(fileObject); return ntStatus; } KDPrint(3,("Before Done...ioStatus.Status = 0x%08x Information = %d\n", ioStatus.Status, ioStatus.Information)); ntStatus = IoCallDriver(deviceObject, irp); if (ntStatus == STATUS_PENDING) { KDPrint(2,("IoCallDriver STATUS_PENDING\n")); KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); ntStatus = ioStatus.Status; } else if(NT_SUCCESS(ntStatus)) { ntStatus = ioStatus.Status; } if(BufferNeeded) *BufferNeeded = (ULONG)ioStatus.Information; ExFreePool(symbolicLinkList); ObDereferenceObject(fileObject); KDPrint(2,("Done...ioStatus.Status = 0x%08x Information = %d\n", ioStatus.Status, ioStatus.Information)); return ntStatus; }
NTSTATUS NdasDluDiskClassControl( IN PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension, IN PNDAS_DLU_EXTENSION NdasDluLuExtension, IN PSCSI_REQUEST_BLOCK Srb ){ // // The request is an I/O control request. The SRB DataBuffer points // to an SRB_IO_CONTROL header followed by the data area. The value // in DataBuffer can be used by the driver, regardless of the value // of MapBuffers field. If the HBA miniport driver supports this // request, it should execute the request and notify the OS-specific // port driver when it has completed it, using the normal mechanism // of NdasPortNotification with RequestComplete and NextLuRequest. // Only the Function, SrbFlags, TimeOutValue, DataBuffer, // DataTransferLength and SrbExtension are valid. // NTSTATUS status; PSRB_IO_CONTROL srbIoControl; PUCHAR srbIoctlBuffer; LONG srbIoctlBufferLength; status = STATUS_SUCCESS; KDPrint(3,("Entered.\n")); // // Get the Ioctl buffer. If this is a send message request, it gets // fixed up to be an I2O message later. // srbIoControl = (PSRB_IO_CONTROL) Srb->DataBuffer; srbIoctlBuffer = ((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL); srbIoctlBufferLength = srbIoControl->Length; #define IOCTL_SCSI_MINIPORT_READ_SMART_LOG ((FILE_DEVICE_SCSI << 16) + 0x050b) #define IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG ((FILE_DEVICE_SCSI << 16) + 0x050c) switch (srbIoControl->ControlCode) { // // support for Self-Monitoring Analysis and Reporting Technology (SMART) // case IOCTL_SCSI_MINIPORT_IDENTIFY: case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS: case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS: case IOCTL_SCSI_MINIPORT_ENABLE_SMART: case IOCTL_SCSI_MINIPORT_DISABLE_SMART: case IOCTL_SCSI_MINIPORT_RETURN_STATUS: case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE: case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES: case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS: case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE: case IOCTL_SCSI_MINIPORT_READ_SMART_LOG: case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG: status = NdasDluSrbIoctlSendCCBWithComp( LogicalUnitExtension, NdasDluLuExtension, Srb, CCB_OPCODE_SMART, srbIoctlBuffer, srbIoctlBufferLength); break; case IOCTL_SCSI_MINIPORT_SMART_VERSION: { PGETVERSIONINPARAMS getVersion; getVersion = (PGETVERSIONINPARAMS)srbIoctlBuffer; // // SMART 1.03 // getVersion->bVersion = 1; getVersion->bRevision = 1; getVersion->bReserved = 0; // // TODO: Add CAP_ATAPI_ID_CMD // getVersion->fCapabilities = CAP_ATA_ID_CMD | CAP_SMART_CMD; // // Regardless of unit number, we exposes the logical unit // as a pseudo ATA primary master // getVersion->bIDEDeviceMap = 1; Srb->SrbStatus = SRB_STATUS_SUCCESS; Srb->DataTransferLength = sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS); } break; // // Cluster Support // case IOCTL_SCSI_MINIPORT_NOT_QUORUM_CAPABLE: case IOCTL_SCSI_MINIPORT_NOT_CLUSTER_CAPABLE: default: Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; Srb->DataTransferLength = 0; break; } return status; }
// // query scsiport PDO // ULONG GetScsiAdapterPdoEnumInfo( IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension, IN ULONG SystemIoBusNumber, OUT PLONG AddDevInfoLength, OUT PVOID *AddDevInfo, OUT PULONG AddDevInfoFlags ) { NTSTATUS status; NDASBUS_QUERY_INFORMATION BusQuery; PNDASBUS_INFORMATION BusInfo; LONG BufferNeeded; KDPrint(2,("SystemIoBusNumber:%d\n", SystemIoBusNumber)); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); BusQuery.Size = sizeof(NDASBUS_QUERY_INFORMATION); BusQuery.InfoClass = INFORMATION_PDOENUM; BusQuery.SlotNo = SystemIoBusNumber; // // Get a buffer length needed. // status = IoctlToLanscsiBus( IOCTL_NDASBUS_QUERY_INFORMATION, &BusQuery, sizeof(NDASBUS_QUERY_INFORMATION), NULL, 0, &BufferNeeded ); if(status != STATUS_BUFFER_TOO_SMALL || BufferNeeded <= 0) { KDPrint(2,("IoctlToLanscsiBus() Failed.\n")); return SP_RETURN_NOT_FOUND; } // // // BusInfo= (PNDASBUS_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, BufferNeeded, NDSC_PTAG_IOCTL); if(BusInfo == NULL) return SP_RETURN_ERROR; status = IoctlToLanscsiBus( IOCTL_NDASBUS_QUERY_INFORMATION, &BusQuery, sizeof(NDASBUS_QUERY_INFORMATION), BusInfo, BufferNeeded, &BufferNeeded ); if(!NT_SUCCESS(status)) { ExFreePoolWithTag(BusInfo, NDSC_PTAG_IOCTL); return SP_RETURN_NOT_FOUND; } HwDeviceExtension->AdapterMaxDataTransferLength = BusInfo->PdoEnumInfo.MaxRequestLength; if(HwDeviceExtension->AdapterMaxDataTransferLength == 0) { HwDeviceExtension->AdapterMaxDataTransferLength = NDAS_MAX_TRANSFER_LENGTH; } HwDeviceExtension->EnumFlags = BusInfo->PdoEnumInfo.Flags; *AddDevInfoFlags = BusInfo->PdoEnumInfo.Flags; KDPrint(2,("MaxRequestLength:%d\n", BusInfo->PdoEnumInfo.MaxRequestLength)); if(BusInfo->PdoEnumInfo.Flags & PDOENUM_FLAG_LURDESC) { ULONG LurDescLen; PLURELATION_DESC lurDesc; PLURELATION_DESC lurDescOrig; lurDescOrig = (PLURELATION_DESC)BusInfo->PdoEnumInfo.AddDevInfo; LurDescLen = lurDescOrig->Length; // // Verify sanity // if(lurDescOrig->Type != LUR_DESC_STRUCT_TYPE) { ExFreePoolWithTag(BusInfo,NDSC_PTAG_IOCTL); KDPrint(2,("LurDescOrig has invalid type: %04x\n", lurDescOrig->Type)); return SP_RETURN_NOT_FOUND; } if(lurDescOrig->CntEcrKeyLength > NDAS_CONTENTENCRYPT_KEY_LENGTH) { ExFreePoolWithTag(BusInfo,NDSC_PTAG_IOCTL); KDPrint(2,("LurDescOrig has invalid key length: %d\n", lurDescOrig->CntEcrKeyLength)); return SP_RETURN_NOT_FOUND; } // // Allocate pool for the LUREALTION descriptor // copy LUREALTION descriptor // lurDesc = (PLURELATION_DESC)ExAllocatePoolWithTag(NonPagedPool, LurDescLen, NDSC_PTAG_ENUMINFO); if(lurDesc == NULL) { ExFreePoolWithTag(BusInfo,NDSC_PTAG_IOCTL); return SP_RETURN_NOT_FOUND; } RtlCopyMemory(lurDesc, &BusInfo->PdoEnumInfo.AddDevInfo, LurDescLen); *AddDevInfo = lurDesc; *AddDevInfoLength = LurDescLen; } else { ASSERT(FALSE); return SP_RETURN_NOT_FOUND; } ExFreePoolWithTag(BusInfo,NDSC_PTAG_IOCTL); return SP_RETURN_FOUND; }
NTSTATUS NdasDluSrbControl( IN PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PSRB_IO_CONTROL srbIoControl; PUCHAR srbIoctlBuffer; LONG srbIoctlBufferLength; ULONG controlCode; NTSTATUS status; UCHAR srbStatus; PNDAS_DLU_EXTENSION ndasDluExtension = NdasDluGetExtension(LogicalUnitExtension); // // Start off being paranoid. // if (Srb->DataBuffer == NULL) { KDPrint(1,("DataBuffer is NULL\n")); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; return STATUS_INVALID_PARAMETER; } status = STATUS_MORE_PROCESSING_REQUIRED; srbStatus = SRB_STATUS_SUCCESS; // // Extract the io_control // srbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer; // // Based on the signature, determine if this is Disk class ioctl or our own's those. // if (strncmp(srbIoControl->Signature, NDASSCSI_IOCTL_SIGNATURE, 8) == 0) { // // NDAS MINIPORT own's. // Continue to the parsing and execution in this function. // } else if(strncmp(srbIoControl->Signature, "SCSIDISK", 8) == 0) { #if 1 // // Disk class request // Complete the SRB in the disk class ioctl function. // return NdasDluDiskClassControl(LogicalUnitExtension, ndasDluExtension, Srb); #else KDPrint(1,("Disk class control disabled.\n")); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; return STATUS_INVALID_PARAMETER; #endif } else { KDPrint(1,("Signature mismatch %8s, %8s\n", srbIoControl->Signature, NDASSCSI_IOCTL_SIGNATURE)); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; return STATUS_INVALID_PARAMETER; } // // Get the control code. // controlCode = srbIoControl->ControlCode; // // Get the Ioctl buffer. If this is a send message request, it gets // fixed up to be an I2O message later. // srbIoctlBuffer = ((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL); srbIoctlBufferLength = srbIoControl->Length; // // Based on the control code, figure out what to do. // switch (controlCode) { case NDASSCSI_IOCTL_GET_DVD_STATUS: { srbStatus = NdasDluSrbIoctlGetDVDSTatus( LogicalUnitExtension, ndasDluExtension, srbIoctlBufferLength, srbIoctlBuffer, &srbIoControl->ReturnCode ); if(srbStatus == SRB_STATUS_SUCCESS) { KDPrint(4,("NDASSCSI_IOCTL_QUERYINFO_EX: Successful.\n")); status = STATUS_SUCCESS; } else { status = STATUS_UNSUCCESSFUL; } } break; case NDASSCSI_IOCTL_GET_SLOT_NO: KDPrint(2,("Get Slot No. Slot number is %d\n", ndasDluExtension->LogicalUnitAddress)); if(srbIoctlBufferLength < sizeof(ULONG)) { srbIoControl->ReturnCode = SRB_STATUS_DATA_OVERRUN; srbStatus = SRB_STATUS_DATA_OVERRUN; status = STATUS_UNSUCCESSFUL; break; } *(PULONG)srbIoctlBuffer = ndasDluExtension->LogicalUnitAddress; srbIoControl->ReturnCode = SRB_STATUS_SUCCESS; srbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; case NDASSCSI_IOCTL_QUERYINFO_EX: { PNDASSCSI_QUERY_INFO_DATA QueryInfo; PUCHAR tmpBuffer; KDPrint(5, ("Query information EX.\n")); QueryInfo = (PNDASSCSI_QUERY_INFO_DATA)srbIoctlBuffer; tmpBuffer = ExAllocatePoolWithTag(NonPagedPool, srbIoctlBufferLength, NDAS_DLU_PTAG_IOCTL); if(tmpBuffer == NULL) { ASSERT(FALSE); KDPrint(1,("NDASSCSI_IOCTL_QUERYINFO_EX: SRB_STATUS_DATA_OVERRUN. BufferLength:%d\n", srbIoctlBufferLength)); srbStatus = SRB_STATUS_DATA_OVERRUN; break; } status = NdasDluSrbIoctlQueryInfo( LogicalUnitExtension, ndasDluExtension, Srb, QueryInfo, srbIoctlBufferLength, tmpBuffer, &srbIoControl->ReturnCode, &srbStatus ); // // tmpBuffer only lives up to the end of current scope. // // When NdasDluSrbIoctlQueryInfo returns STATUS_PENDING, // we cannot touch srbIoctlBuffer at all because srbIoctlBuffer // is being touch by the completion routine. // // Other cases, we have to copy from the temporarily output buffer // (tmpBuffer) to the final output buffer (srbIoctlBuffer) // if (STATUS_PENDING != status) { RtlCopyMemory(srbIoctlBuffer, tmpBuffer, srbIoctlBufferLength); } ExFreePoolWithTag(tmpBuffer, NDAS_DLU_PTAG_IOCTL); break; } case NDASSCSI_IOCTL_UPGRADETOWRITE: { PLURN_UPDATE LurnUpdate; PCCB Ccb; // // Set a CCB // status = LsCcbAllocate(&Ccb); if(!NT_SUCCESS(status)) { srbStatus = SRB_STATUS_INVALID_REQUEST; KDPrint(1,("NDASSCSI_IOCTL_UPGRADETOWRITE: LsCcbAllocate() failed.\n")); break; } LurnUpdate = (PLURN_UPDATE)ExAllocatePoolWithTag(NonPagedPool, sizeof(LURN_UPDATE), NDAS_DLU_PTAG_IOCTL); if(!LurnUpdate) { srbStatus = SRB_STATUS_INVALID_REQUEST; KDPrint(1,("NDASSCSI_IOCTL_UPGRADETOWRITE: ExAllocatePoolWithTag() failed.\n")); status = STATUS_INSUFFICIENT_RESOURCES; break; } LSCCB_INITIALIZE(Ccb); Ccb->OperationCode = CCB_OPCODE_UPDATE; Ccb->DataBuffer = LurnUpdate; Ccb->DataBufferLength = sizeof(LURN_UPDATE); LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED); // Ioctl Srb will complete asynchronously. Ccb->Srb = Srb; InterlockedIncrement(&ndasDluExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, LogicalUnitExtension); LurnUpdate->UpdateClass = LURN_UPDATECLASS_WRITEACCESS_USERID; status = LurRequest( ndasDluExtension->LUR, Ccb ); if(!NT_SUCCESS(status)) { KDPrint(1,("NDASSCSI_IOCTL_UPGRADETOWRITE: LurnRequest() failed.\n")); NdasDluLogError( LogicalUnitExtension, Srb, Srb->PathId, Srb->TargetId, Srb->Lun, NDASSCSI_IO_UPGRADEIOCTL_FAIL, EVTLOG_UNIQUEID(EVTLOG_MODULE_IOCTL, EVTLOG_FAIL_UPGRADEIOCTL, 0) ); LsuDecrementTdiClientInProgress(); LsCcbFree(Ccb); ExFreePoolWithTag(LurnUpdate, NDSC_PTAG_IOCTL); status = STATUS_SUCCESS; srbStatus = SRB_STATUS_INVALID_REQUEST; } else { status = STATUS_PENDING; } break; } case NDASSCSI_IOCTL_NOOP: { PCCB Ccb; // // Query to the LUR // status = LsCcbAllocate(&Ccb); if(!NT_SUCCESS(status)) { srbStatus = SRB_STATUS_ERROR; status = STATUS_SUCCESS; KDPrint(1,("LsCcbAllocate() failed.\n")); break; } LSCCB_INITIALIZE(Ccb); Ccb->OperationCode = CCB_OPCODE_NOOP; LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED); Ccb->Srb = Srb; LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, LogicalUnitExtension); InterlockedIncrement(&ndasDluExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); status = LurRequest( ndasDluExtension->LUR, Ccb ); if(!NT_SUCCESS(status)) { LsuDecrementTdiClientInProgress(); LsCcbFree(Ccb); srbStatus = SRB_STATUS_ERROR; status = STATUS_SUCCESS; KDPrint(1,("LurRequest() failed.\n")); break; } srbStatus = SRB_STATUS_SUCCESS; status = STATUS_PENDING; break; } case NDASSCSI_IOCTL_ADD_USERBACL: { PNDAS_BLOCK_ACE bace = (PNDAS_BLOCK_ACE)srbIoctlBuffer; // input PBLOCKACE_ID blockAceId = (PBLOCKACE_ID)srbIoctlBuffer; // output UCHAR lsuAccessMode; PLSU_BLOCK_ACE lsuBace; UINT64 blockStartAddr; UINT64 blockEndAddr; if(srbIoctlBufferLength < sizeof(NDAS_BLOCK_ACE)) { srbStatus = SRB_STATUS_DATA_OVERRUN; status = STATUS_UNSUCCESSFUL; break; } if(ndasDluExtension->LUR == NULL) { srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } lsuAccessMode = 0; if(bace->AccessMode & NBACE_ACCESS_READ) { lsuAccessMode |= LSUBACE_ACCESS_READ; } if(bace->AccessMode & NBACE_ACCESS_WRITE) { lsuAccessMode |= LSUBACE_ACCESS_WRITE; } if (bace->IsByteAddress) { blockStartAddr = bace->StartingOffset / ndasDluExtension->LUR->BlockBytes; blockEndAddr = (bace->StartingOffset + bace->Length) / ndasDluExtension->LUR->BlockBytes - 1; } else { blockStartAddr = bace->BlockStartAddr; blockEndAddr = bace->BlockEndAddr; } lsuBace = LsuCreateBlockAce( lsuAccessMode, blockStartAddr, blockEndAddr ); if(lsuBace == NULL) { srbStatus = SRB_STATUS_DATA_OVERRUN; status = STATUS_UNSUCCESSFUL; break; } // Set returned BACE ID. *blockAceId = lsuBace->BlockAceId; LsuInsertAce(&ndasDluExtension->LUR->UserBacl, lsuBace); srbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; } case NDASSCSI_IOCTL_REMOVE_USERBACL: { PNDSCIOCTL_REMOVE_USERBACL ioctlRemoveUserAcl = (PNDSCIOCTL_REMOVE_USERBACL)srbIoctlBuffer; BLOCKACE_ID blockAceId; PLSU_BLOCK_ACE lsuBacl; if(srbIoctlBufferLength < sizeof(NDSCIOCTL_REMOVE_USERBACL)) { srbStatus = SRB_STATUS_DATA_OVERRUN; status = STATUS_UNSUCCESSFUL; break; } blockAceId = ioctlRemoveUserAcl->NdasBlockAceId; // input if(ndasDluExtension->LUR == NULL) { srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } if(blockAceId == 0) { KDPrint(1,("REMOVE_USERBACL: Zero block ACE ID.\n")); srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } lsuBacl = LsuRemoveAceById(&ndasDluExtension->LUR->UserBacl, blockAceId); if(lsuBacl == NULL) { KDPrint(1,("REMOVE_USERBACL: Invalid block ACE ID.\n")); srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } LsuFreeBlockAce(lsuBacl); srbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; } case NDASSCSI_IOCTL_DEVICE_LOCK: { if(srbIoctlBufferLength < sizeof(NDSCIOCTL_DEVICELOCK)) { srbStatus = SRB_STATUS_DATA_OVERRUN; status = STATUS_UNSUCCESSFUL; break; } if(ndasDluExtension->LUR == NULL) { srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } status = NdasDluIoctlDeviceLock( LogicalUnitExtension, ndasDluExtension, (PNDSCIOCTL_DEVICELOCK)srbIoctlBuffer, Srb); srbStatus = Srb->SrbStatus; break; } default: KDPrint(2,("Control Code (%x)\n", controlCode)); srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_MORE_PROCESSING_REQUIRED; } Srb->SrbStatus = srbStatus; return status; }
VOID UpdatePdoInfoInLSBus( PMINIPORT_DEVICE_EXTENSION HwDeviceExtension, UINT32 AdapterStatus ) { PNDASBUS_SETPDOINFO busSet; NDAS_FEATURES supportedFeatures, enabledFeatures; ASSERT(HwDeviceExtension); // // Query to the LUR // if(HwDeviceExtension->LURs[0]) { KDPrint(4,("going to default LuExtention 0.\n")); supportedFeatures = HwDeviceExtension->LURs[0]->SupportedNdasFeatures; enabledFeatures = HwDeviceExtension->LURs[0]->EnabledNdasFeatures; } else { KDPrint(2,("No LUR available..\n")); supportedFeatures = enabledFeatures = 0; return; } KDPrint(2,("Set AdapterStatus=%x Supp=%x Enab=%x\n", AdapterStatus, supportedFeatures, enabledFeatures)); // // Send to LSBus // busSet = (PNDASBUS_SETPDOINFO)ExAllocatePoolWithTag(NonPagedPool, sizeof(NDASBUS_SETPDOINFO), NDSC_PTAG_IOCTL); if(busSet == NULL) { return; } busSet->Size = sizeof(NDASBUS_SETPDOINFO); busSet->SlotNo = HwDeviceExtension->SlotNumber; busSet->AdapterStatus = AdapterStatus; busSet->SupportedFeatures = supportedFeatures; busSet->EnabledFeatures = enabledFeatures; if(KeGetCurrentIrql() == PASSIVE_LEVEL) { IoctlToLanscsiBus( IOCTL_NDASBUS_SETPDOINFO, busSet, sizeof(NDASBUS_SETPDOINFO), NULL, 0, NULL); ExFreePoolWithTag(busSet, NDSC_PTAG_IOCTL); } else { // // IoctlToLanscsiBus_Worker() will free memory of BusSet. // IoctlToLanscsiBusByWorker( HwDeviceExtension->ScsiportFdoObject, IOCTL_NDASBUS_SETPDOINFO, busSet, sizeof(NDASBUS_SETPDOINFO) ); } }