void initVulkan() {
     createInstance();
     setupDebugCallback();
     createSurface();
     pickPhysicalDevice();
     createLogicalDevice();
     createSwapChain();
 }
 void initVulkan() {
     createInstance();
     setupDebugCallback();
     createSurface();
     pickPhysicalDevice();
     createLogicalDevice();
     createSwapChain();
     createImageViews();
     createRenderPass();
     createGraphicsPipeline();
 }
void com_ximeta_driver_NDASDiskArrayController::processSettingCommand(com_ximeta_driver_NDASCommand *command)
{
	
	PPNPCommand	pnpCommand = command->pnpCommand();
	int result;
	
	// Discovery.
	result = fProvider->discovery();
	/*
	if ( kNDASStatusFailure != fProvider->status() ) {
		result = fProvider->discovery();
	} else {
		return;
	}
	*/

	// Check Data connection 
	for (int count = 0; count < MAX_NR_OF_TARGETS_PER_DEVICE; count++) {
		fProvider->checkDataConnection(count);		
	}

	if ( kNDASStatusOffline == result ) {
		for (int count = 0; count < MAX_NR_OF_TARGETS_PER_DEVICE; count++) {
						
			if ( kNDASUnitStatusMountRO == fProvider->targetStatus(count)
				 || kNDASUnitStatusMountRW == fProvider->targetStatus(count) ) {
				
				result = kNDASStatusOnline;
				
				goto out;
			}
		}
	}
	
	switch(fProvider->status()) {
		case kNDASStatusOffline:
		{
			// Get Unit disk info.
			if( kNDASStatusOnline == result ) {
				result = fProvider->getUnitDiskInfo();
			}
			
			DbgIOLog(DEBUG_MASK_NDAS_INFO, ("processSettingCommand: The Status of this NDAS changed to %d", fProvider->getState()));
			
		}
			break;
		case kNDASStatusOnline:
		{
			// Check every Targets.
			for(int count = 0; count < MAX_NR_OF_TARGETS_PER_DEVICE; count++) {
				
				bool	bNeedMount = false;
				bool	bNeedUnmount = false;
				bool	bNeedCreateDevice = false;
				bool	bNeedDeleteDevice = false;
	
				// Check BSD Name.
				if(fTargetDevices[count] != NULL) {
					fProvider->setTargetBSDName(count, fTargetDevices[count]->bsdName());
				}
								
				if ( fProvider->targetNeedRefresh(count) ) {
					result = fProvider->getUnitDiskInfo();
					
					fProvider->setTargetNeedRefresh(count, false);	
				}
				
				switch(fProvider->targetStatus(count)) {
					case kNDASUnitStatusNotPresent:
						break;
					case kNDASUnitStatusUnmount:
					{
//						UInt32	status;
						
						// Need Mount?
						switch(fProvider->targetConfiguration(count)) {
							case kNDASUnitConfigurationMountRW:
							{
								bNeedMount = true;
								
								if(fTargetDevices[count] == NULL) {
									bNeedCreateDevice = true;
								}
							}
								break;
							case kNDASUnitConfigurationMountRO:
							{
								bNeedMount = true;
								if(fTargetDevices[count] == NULL) {
									bNeedCreateDevice = true;
								}
							}
								break;
							default:
								break;
						}
					}
						break;
					case kNDASUnitStatusMountRO:
					{
//						UInt32	status;
						
						switch(fProvider->targetConfiguration(count)) {
							case kNDASUnitConfigurationMountRW:
							case kNDASUnitConfigurationUnmount:
							{
								// Need Unmount.
								bNeedUnmount = true;
								bNeedDeleteDevice = true;
							}
								break;
							case kNDASUnitConfigurationMountRO:
							{
								// Interface Change.
								if(pnpCommand->fInterfaceChanged) {
								
									DbgIOLog(DEBUG_MASK_NDAS_INFO, ("processSettingCommand: Interface Changed.\n"));
								
									bNeedUnmount = true;
									//fProvider->unmount(count);
								} else {
								
									// Check Connection.
									if(!fProvider->targetConnected(count)) {
										
										DbgIOLog(DEBUG_MASK_NDAS_WARING, ("processSettingCommand: Connection Disconnected!!!\n"));
										
										// Need Reconnect.									
										bNeedMount = true;
									}
								}
							}
								break;
							default:
								break;
						}
					}
						break;
					case kNDASUnitStatusMountRW:
					{
//						UInt32	status;
						
						// Need Unmount?
						switch(fProvider->targetConfiguration(count)) {
							case kNDASUnitConfigurationMountRO:
							case kNDASUnitConfigurationUnmount:
							{
								bNeedUnmount = true;
								bNeedDeleteDevice = true;
							}
								break;
							case kNDASUnitConfigurationMountRW:
							{
								// Interface Change.
								if(pnpCommand->fInterfaceChanged) {
									
									DbgIOLog(DEBUG_MASK_NDAS_WARING, ("processSettingCommand: Interface Changed.\n"));
									
									bNeedUnmount = true;
									//fProvider->unmount(count);
								} else {
								
									// Check Connection.
									if(!fProvider->targetConnected(count)) {
									
										DbgIOLog(DEBUG_MASK_NDAS_WARING, ("processSettingCommand: Connection Disconnected!!!\n"));
										
										// Need Reconnect.
										bNeedMount = true;
									}
								}
							}
								break;
							default:
								break;
						}
						
					}
					default:
						break;
				}

				//
				// Mount, Unmount...
				// 
				if(bNeedMount) {
					UInt32 status, prevStatus;
					
					prevStatus = fProvider->targetStatus(count);
					status = fProvider->mount(count, pnpCommand);
					
					if((status == kNDASUnitStatusMountRW
						|| status == kNDASUnitStatusMountRO))
					{
						//
						// Create Logical Device.
						//
						if(bNeedCreateDevice)
						{
							// Create Logical Device.
							if(createLogicalDevice(count) != kIOReturnSuccess) {
								fProvider->unmount(count);
							}
						}
						
						//
						// Process pending command caused by disconnection.
						//
						com_ximeta_driver_NDASCommand* command = fProvider->targetPendingCommand(count);
						if(NULL != command) {

							DbgIOLog(DEBUG_MASK_NDAS_ERROR, ("processSettingCommand: Processing Pending Command\n"));
							
							fProvider->setTargetPendingCommand(count, NULL);
							
							if(fTargetDevices[count] != NULL) {
								
								enqueueCommand(command);
								/*
								PSCSICommand	pScsiCommand;
								
								pScsiCommand = command->scsiCommand();
								
								if(kIOReturnSuccess != pScsiCommand->CmdData.results) {
									pScsiCommand->CmdData.results = kIOReturnBusy;
									pScsiCommand->CmdData.taskStatus = kSCSITaskStatus_ProtocolTimeoutOccurred;
								}
								
								fTargetDevices[count]->completeCommand(command);
								 */
							} else {
								DbgIOLog(DEBUG_MASK_NDAS_ERROR, ("processSettingCommand: fTargetDevice is NULL!!!\n"));
							}
						}
					} else {
						if(kNDASUnitStatusMountRW == prevStatus) {
							bNeedUnmount = true;
							bNeedDeleteDevice = true;
						}
					}
				}
				
				if(bNeedUnmount) {
					
					if(bNeedDeleteDevice) {
						if(deleteLogicalDevice(count) == kIOReturnSuccess
						   && bNeedUnmount) {
							fProvider->unmount(count);
						} 
					} else {
						fProvider->unmount(count);
					}
				}
			}
		}
			break;
		case kNDASStatusNoPermission:
		case kNDASStatusFailure:
		{
			if( kNDASStatusOnline == result ) {
				result = fProvider->getUnitDiskInfo();
				
				for(int count = 0; count < MAX_NR_OF_TARGETS_PER_DEVICE; count++) {
					fProvider->setTargetNeedRefresh(count, false);
				}
			}
		}
			break;
		default:
			DbgIOLog(DEBUG_MASK_NDAS_ERROR, ("processSettingCommand: Bad Status %d", fProvider->status()));
			break;
	}

out:
		
	// Change Status.
	fProvider->setStatus(result);
	
	fProvider->completePnPMessage(command);
		
	return;
}