/*++ Copyright (c) 1992 Microsoft Corporation Module Name: send.c Abstract: NOTE: ZZZ There is a potential priority inversion problem when allocating the packet. For nt it looks like we need to raise the irql to dpc when we start the allocation. Author: Thomas J. Dimitri 8-May-1992 Environment: Kernel Mode - Or whatever is the equivalent on OS/2 and DOS. Revision History: Ray Patch (raypa) 04/13/94 Modified for new WAN wrapper. --*/ #if DBG #define __FILE_SIG__ 'dneS' #endif #include "asyncall.h" #include "globals.h" // // Forward references. // extern NTSTATUS AsyncWriteCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PNDIS_WAN_PACKET WanPacket); //============================================================================= // Function: // // AsyncSend() // // Description: // // This function is the main entry point for transmitting data to the serial // driver. When entered, we get the MAC binding handle (a pointer to our // private data structure) and the WAN packet which we are going to send. // We don't bother queuing the frame, we simple allocate an IRP and ship // it to the serial driver and let him worry about it. // // In Parameters: // // NdisLinkContext - Pointer to the ASYNC_INFO structure. // // Packet - WAN packet containing the data to be framed and shipped. // // Out Parameters: // // None. // // Return status: // // NDIS_STATUS_SUCCESS. //============================================================================= NDIS_STATUS MpSend( IN NDIS_HANDLE MacBindingHandle, IN NDIS_HANDLE NdisLinkHandle, IN PNDIS_WAN_PACKET Packet) { PASYNC_INFO AsyncInfo; NDIS_STATUS Status; DbgTracef(1,("AS\n")); // // Get the open handle for this MAC binding. // AsyncInfo = (PASYNC_INFO) NdisLinkHandle; // // First make sure this link is still up. // if (AsyncInfo->PortState == PORT_FRAMING && (AsyncInfo->GetLinkInfo.SendFramingBits & (PPP_FRAMING | SLIP_FRAMING)) != 0) { // // Now we can send this frame. // Status = AsyncSendPacket( NdisLinkHandle, Packet); // For all Status values (PENDING, SUCCESS, and ERROR) the callback from Write will // do a sendcomplete indication so we always return PENDING. // Status = STATUS_PENDING ; } else { DbgTracef(-2,("AsyncSend: Link not found, dropping packet!\n")); Status = NDIS_STATUS_SUCCESS; } return Status; } //============================================================================= // Function: // // AsyncSendPacket() // // Description: // This function is called from AsyncSend() to send an IRP to the serial // driver. If this IRP pends, the the I/O complete routine will be called // later to complete the request. // // In Parameters: // // Packet - WAN packet containing the data to be framed and shipped. // // Out Parameters: // // None. // // Return status: // // NDIS_STATUS_SUCCESS. //============================================================================= NTSTATUS AsyncSendPacket( IN PASYNC_INFO AsyncInfo, IN PNDIS_WAN_PACKET WanPacket) { NTSTATUS Status; PIRP irp; PIO_STACK_LOCATION irpSp; PFILE_OBJECT FileObject; PDEVICE_OBJECT DeviceObject; PASYNC_ADAPTER Adapter; UCHAR irpStackSize; // // Initialize locals. // FileObject = AsyncInfo->FileObject; DeviceObject = AsyncInfo->DeviceObject; Adapter = AsyncInfo->Adapter; irpStackSize = (UCHAR) Adapter->IrpStackSize; // // Get irp from irp pool. // irp = IoAllocateIrp(DeviceObject->StackSize, (BOOLEAN)FALSE); // // The IO subsystem may be out of irps. // if (irp == NULL) { return(NDIS_STATUS_RESOURCES); } // // Tuck pointer to AsyncInfo for completion use // WanPacket->MacReserved1 = AsyncInfo; irp->Tail.Overlay.OriginalFileObject = FileObject; irp->RequestorMode = KernelMode; irp->PendingReturned = FALSE; // // Fill in the service independent parameters in the IRP. // irp->UserEvent = NULL; // // 8 byte align (also use end of packet for IOSB). // irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; irp->Overlay.AsynchronousParameters.UserApcContext = NULL; // // Get a pointer to the stack location for the first driver. This will be // used to pass the original function codes and parameters. // irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_WRITE; irpSp->FileObject = FileObject; if (FileObject->Flags & FO_WRITE_THROUGH) { irpSp->Flags = SL_WRITE_THROUGH; } // // If this write operation is to be performed without any caching, set the // appropriate flag in the IRP so no caching is performed. // if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) { irp->Flags |= (IRP_NOCACHE | IRP_WRITE_OPERATION); } else { irp->Flags |= IRP_WRITE_OPERATION; } // // Assemble a RAS, PPP, SLIP frame type. // if (AsyncInfo->GetLinkInfo.SendFramingBits & PPP_FRAMING) { AssemblePPPFrame(WanPacket); } else if (AsyncInfo->GetLinkInfo.SendFramingBits & SLIP_FRAMING) { AssembleSLIPFrame(WanPacket); } irp->AssociatedIrp.SystemBuffer = WanPacket->CurrentBuffer; DbgTracef(0, ("Writing out %.2x %.2x %.2x %.2x %.2x\n", WanPacket->CurrentBuffer[0], WanPacket->CurrentBuffer[1], WanPacket->CurrentBuffer[2], WanPacket->CurrentBuffer[3], WanPacket->CurrentBuffer[4])); // // Copy the caller's parameters to the service-specific portion of the IRP. // irpSp->Parameters.Write.Length = WanPacket->CurrentLength; irpSp->Parameters.Write.Key = 0; irpSp->Parameters.Write.ByteOffset = FileObject->CurrentByteOffset; // // Setup IRP for callback. // IoSetCompletionRoutine( irp, // irp to use AsyncWriteCompletionRoutine, // routine to call when irp is done WanPacket, // context to pass routine TRUE, // call on success TRUE, // call on error TRUE); // call on cancel // // We DO NOT insert the packet at the head of the IRP list for the thread. // because we do NOT really have an IoCompletionRoutine that does // anything with the thread or needs to be in that thread's context. // GlobalXmitWentOut++; AsyncInfo->In++; AsyncInfo->Flags |= ASYNC_FLAG_SEND_PACKET; REF_ASYNCINFO(AsyncInfo, irp); // // Now simply invoke the driver at its dispatch entry with the IRP. // Status = IoCallDriver(DeviceObject, irp); // According to TonyE, the status for the serial driver should // always be STATUS_PENDING. DigiBoard usually STATUS_SUCCESS. return Status; }