PVIOSERIAL_PORT VIOSerialFindPortById( IN WDFDEVICE Device, IN ULONG id ) { NTSTATUS status = STATUS_SUCCESS; WDFCHILDLIST list; WDF_CHILD_LIST_ITERATOR iterator; PRAWPDO_VIOSERIAL_PORT rawPdo = NULL; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP,"%s port = %d\n", __FUNCTION__, id); list = WdfFdoGetDefaultChildList(Device); WDF_CHILD_LIST_ITERATOR_INIT(&iterator, WdfRetrievePresentChildren ); WdfChildListBeginIteration(list, &iterator); for (;;) { WDF_CHILD_RETRIEVE_INFO childInfo; VIOSERIAL_PORT port; WDFDEVICE hChild; WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT( &port.Header, sizeof(port) ); WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &port.Header); status = WdfChildListRetrieveNextDevice( list, &iterator, &hChild, &childInfo ); if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES) { break; } ASSERT(childInfo.Status == WdfChildListRetrieveDeviceSuccess); rawPdo = RawPdoSerialPortGetData(hChild); if(rawPdo && rawPdo->port->PortId == id) { WdfChildListEndIteration(list, &iterator); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"%s id = %d port = 0x%p\n", __FUNCTION__, id, rawPdo->port); return rawPdo->port; } } WdfChildListEndIteration(list, &iterator); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP, "<-- %s\n", __FUNCTION__); return NULL; }
NTSTATUS Bus_EjectDevice( WDFDEVICE Device, ULONG SerialNo ) /*++ Routine Description: The user application has told us to eject the device from the bus. In a real situation the driver gets notified by an interrupt when the user presses the Eject button on the device. Arguments: Returns: STATUS_SUCCESS upon successful removal from the list STATUS_INVALID_PARAMETER if the ejection was unsuccessful --*/ { WDFDEVICE hChild; NTSTATUS status = STATUS_INVALID_PARAMETER; WDFCHILDLIST list; PAGED_CODE (); list = WdfFdoGetDefaultChildList(Device); // // A zero serial number means eject all children // if (0 == SerialNo) { WDF_CHILD_LIST_ITERATOR iterator; WDF_CHILD_LIST_ITERATOR_INIT( &iterator, WdfRetrievePresentChildren ); WdfChildListBeginIteration(list, &iterator); for ( ; ; ) { WDF_CHILD_RETRIEVE_INFO childInfo; PDO_IDENTIFICATION_DESCRIPTION description; BOOLEAN ret; // // Init the structures. // WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description)); WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &description.Header); WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT( &description.Header, sizeof(description) ); // // Get the device identification description // status = WdfChildListRetrieveNextDevice(list, &iterator, &hChild, &childInfo); if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES) { break; } ASSERT(childInfo.Status == WdfChildListRetrieveDeviceSuccess); // // Use that description to request an eject. // ret = WdfChildListRequestChildEject(list, &description.Header); if(!ret) { WDFVERIFY(ret); } } WdfChildListEndIteration(list, &iterator); if (status == STATUS_NO_MORE_ENTRIES) { status = STATUS_SUCCESS; } } else { PDO_IDENTIFICATION_DESCRIPTION description; WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT( &description.Header, sizeof(description) ); description.SerialNo = SerialNo; if (WdfChildListRequestChildEject(list, &description.Header)) { status = STATUS_SUCCESS; } } return status; }
VOID VIOSerialRenewAllPorts( IN WDFDEVICE Device ) { NTSTATUS status = STATUS_SUCCESS; WDFCHILDLIST list; WDF_CHILD_LIST_ITERATOR iterator; PPORTS_DEVICE pContext = GetPortsDevice(Device); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"--> %s\n", __FUNCTION__); if(pContext->isHostMultiport) { VIOSerialFillQueue(pContext->c_ivq, pContext->CVqLock); } list = WdfFdoGetDefaultChildList(Device); WDF_CHILD_LIST_ITERATOR_INIT(&iterator, WdfRetrievePresentChildren ); WdfChildListBeginIteration(list, &iterator); for (;;) { WDF_CHILD_RETRIEVE_INFO childInfo; VIOSERIAL_PORT vport; WDFDEVICE hChild; WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT( &vport.Header, sizeof(vport) ); WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &vport.Header); status = WdfChildListRetrieveNextDevice( list, &iterator, &hChild, &childInfo ); if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES) { break; } ASSERT(childInfo.Status == WdfChildListRetrieveDeviceSuccess); VIOSerialEnableInterruptQueue(GetInQueue(&vport)); WdfIoQueueStart(vport.ReadQueue); WdfIoQueueStart(vport.WriteQueue); WdfIoQueueStart(vport.IoctlQueue); if(vport.GuestConnected) { VIOSerialSendCtrlMsg(vport.BusDevice, vport.PortId, VIRTIO_CONSOLE_PORT_OPEN, 1); } } WdfChildListEndIteration(list, &iterator); WdfChildListUpdateAllChildDescriptionsAsPresent(list); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"<-- %s\n", __FUNCTION__); return; }
NTSTATUS VIOSerialEvtDeviceD0ExitPreInterruptsDisabled( IN WDFDEVICE WdfDevice, IN WDF_POWER_DEVICE_STATE TargetState ) { NTSTATUS status = STATUS_SUCCESS; WDFCHILDLIST portList; WDF_CHILD_LIST_ITERATOR portIterator; UNREFERENCED_PARAMETER(TargetState); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "--> %s\n", __FUNCTION__); PAGED_CODE(); portList = WdfFdoGetDefaultChildList(WdfDevice); WDF_CHILD_LIST_ITERATOR_INIT(&portIterator, WdfRetrievePresentChildren); WdfChildListBeginIteration(portList, &portIterator); for (;;) { WDF_CHILD_RETRIEVE_INFO childInfo; WDFDEVICE hChild; VIOSERIAL_PORT port; PRAWPDO_VIOSERIAL_PORT pdoData; WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT( &port.Header, sizeof(port)); WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &port.Header); status = WdfChildListRetrieveNextDevice(portList, &portIterator, &hChild, &childInfo); if (!NT_SUCCESS(status) || (status == STATUS_NO_MORE_ENTRIES)) { break; } ASSERT(childInfo.Status == WdfChildListRetrieveDeviceSuccess); pdoData = RawPdoSerialPortGetData(hChild); if (pdoData->port->GuestConnected && !pdoData->port->Removed) { VIOSerialSendCtrlMsg(pdoData->port->BusDevice, pdoData->port->PortId, VIRTIO_CONSOLE_PORT_OPEN, 0); pdoData->port->GuestConnected = FALSE; } pdoData->port->Removed = TRUE; } WdfChildListEndIteration(portList, &portIterator); if (status == STATUS_NO_MORE_ENTRIES) { status = STATUS_SUCCESS; } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "<-- %s: 0x%x\n", __FUNCTION__, status); return status; }