// purge.c // // // Requires DDK Only // File created on 2/2/2005 // #include "pch.h" #ifdef CPR_WMI_TRACE #include "purge.tmh" #endif /////////////////////////////////////////////////////////////////////////////////////////////////// // PurgeQueueStartIo // StartIo routine for PurgeQueue IRP queue, processes serialized // requests // // Arguments: // IN DeviceObject // Device object for our device // // IN Irp // The PurgeQueue IRP to process // // Return Value: // None // VOID PurgeQueueStartIo( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PCPR_DEVICE_EXTENSION deviceExtension; ULONG mask; PIRP xoffIrp; BOOLEAN RFC2217_RX = FALSE; BOOLEAN RFC2217_TX = FALSE; KIRQL oldIrql; // get our device extension deviceExtension = (PCPR_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // get the purge request mask mask = *(PULONG)Irp->AssociatedIrp.SystemBuffer; CprAcquireSerialSpinLock(deviceExtension, &oldIrql); // see if we need to abort outstanding write requests if (mask & SERIAL_PURGE_TXABORT) { CprReleaseSerialSpinLock(deviceExtension, oldIrql); CprQueueCancelAll(&deviceExtension->WriteQueue); CprAcquireSerialSpinLock(deviceExtension, &oldIrql); // This is disabled for now... DAG 8/8/07 CprCancelTdiIrps(deviceExtension); // check Xoff counter IRP if (deviceExtension->XoffIrp != NULL) { // cancel Xoff io CprSerialStopXoff(deviceExtension); // cancel Xoff timer if (deviceExtension->XoffIrpRef & CPR_IRPREF_TIMER) { if (KeCancelTimer(&deviceExtension->XoffTimer)) { deviceExtension->XoffIrpRef &= ~CPR_IRPREF_TIMER; } } // remove cancel routine if (deviceExtension->XoffIrpRef & CPR_IRPREF_CANCEL) { if (IoSetCancelRoutine(deviceExtension->XoffIrp, NULL)) { deviceExtension->XoffIrpRef &= ~CPR_IRPREF_CANCEL; } } } if ((deviceExtension->XoffIrp != NULL) && (deviceExtension->XoffIrpRef == 0)) { xoffIrp = deviceExtension->XoffIrp; deviceExtension->XoffIrp = NULL; } else { xoffIrp = NULL; } if (xoffIrp != NULL) { xoffIrp->IoStatus.Status = STATUS_SERIAL_MORE_WRITES; xoffIrp->IoStatus.Information = 0; CprReleaseSerialSpinLock(deviceExtension, oldIrql); IoCompleteRequest(xoffIrp, IO_NO_INCREMENT); CprAcquireSerialSpinLock(deviceExtension, &oldIrql); } if (deviceExtension->UseRFC2217) { RFC2217_TX = TRUE; CprRfc2217_SendCPCByteCommand(deviceExtension, TNCAS_PURGE_DATA, TN_PURGE_TX_BUFFER); } } // see if we need to abort outstanding read requests if (mask & SERIAL_PURGE_RXABORT) { CprReleaseSerialSpinLock(deviceExtension, oldIrql); CprQueueCancelAll(&deviceExtension->ReadQueue); CprAcquireSerialSpinLock(deviceExtension, &oldIrql); if (deviceExtension->UseRFC2217) { RFC2217_RX = TRUE; CprRfc2217_SendCPCByteCommand(deviceExtension, TNCAS_PURGE_DATA, TN_PURGE_RX_BUFFER); } } // see if we need to clear our read queue from any characters if (mask & SERIAL_PURGE_RXCLEAR) { if (deviceExtension->ReadBuffer == deviceExtension->QueueBuffer) { deviceExtension->ReadCharLast = deviceExtension->QueueBuffer; deviceExtension->ReadCharFirst = deviceExtension->QueueBuffer; deviceExtension->ReadBufferEnd = deviceExtension->QueueBuffer + (deviceExtension->QueueSize - 1); deviceExtension->ReadCount = 0; // we changed number of bytes in receive buffer, make sure that // we generate all the required events CprCheckForReceiveBufferChangedEvent(deviceExtension); } if (deviceExtension->UseRFC2217 && (RFC2217_RX == FALSE)) { RFC2217_RX = TRUE; CprRfc2217_SendCPCByteCommand(deviceExtension, TNCAS_PURGE_DATA, TN_PURGE_RX_BUFFER); } } if (deviceExtension->UseRFC2217 && (RFC2217_TX == FALSE) && (mask & SERIAL_PURGE_TXCLEAR)) { RFC2217_TX = TRUE; CprRfc2217_SendCPCByteCommand(deviceExtension, TNCAS_PURGE_DATA, TN_PURGE_TX_BUFFER); } if (RFC2217_TX || RFC2217_RX) { CprRfc2217_SendToNet(deviceExtension, TRUE); CprReleaseSerialSpinLock(deviceExtension, oldIrql); // Flags will be false if deviceExtension->UseRFC2217 is false if (deviceExtension->PendingWriteCount > 0) { //DbgPrint(__FUNCTION__" UDP-Before, IRQL %d RX %d TX %d\n", KeGetCurrentIrql(), RFC2217_RX, RFC2217_TX); if (CprUartUdpPurgeBuffers(deviceExtension, RFC2217_RX, RFC2217_TX) == STATUS_SUCCESS) { //DbgPrint(__FUNCTION__" UDP-After, IRQL %d \n", KeGetCurrentIrql()); // CprAcquireSerialSpinLock(deviceExtension, &oldIrql); //DbgPrint(__FUNCTION__" CprRfc2217_SendCPCByteCommand-Before, IRQL %d \n", KeGetCurrentIrql()); // CprRfc2217_SendCPCByteCommand(deviceExtension, TNCAS_NOTIFY_LINESTATE, 0); //DbgPrint(__FUNCTION__" CprRfc2217_SendToNet-Before, IRQL %d \n", KeGetCurrentIrql()); // CprRfc2217_SendToNet(deviceExtension, TRUE); //DbgPrint(__FUNCTION__" CprRfc2217_SendToNet-After, IRQL %d \n", KeGetCurrentIrql()); // CprReleaseSerialSpinLock(deviceExtension, oldIrql); } //DbgPrint(__FUNCTION__" CprReleaseSerialSpinLock-After, IRQL %d \n", KeGetCurrentIrql()); } } else { CprReleaseSerialSpinLock(deviceExtension, oldIrql); } // CprReleaseSerialSpinLockFromDpcLevel(deviceExtension); //CprReleaseSerialSpinLock(deviceExtension, oldIrql); CprStartNext(&deviceExtension->PurgeQueue); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return; } VOID PurgeQueueStatusChange( IN PDEVICE_OBJECT DeviceObject, ULONG QueueIrpStatus ) { }