|
|
/*****************************************************************************
* * Copyright (c) 1996-1999 Microsoft Corporation * * @doc * @module send.c | IrSIR NDIS Miniport Driver * @comm * *----------------------------------------------------------------------------- * * Author: Scott Holden (sholden) * * Date: 10/4/1996 (created) * * Contents: * *****************************************************************************/
#include "irsir.h"
//
// Declarations.
//
NDIS_STATUS SendPacket( IN PIR_DEVICE pThisDev, IN PNDIS_PACKET Packet, IN UINT Flags );
NTSTATUS SerialIoCompleteWrite( IN PDEVICE_OBJECT pSerialDevObj, IN PIRP pIrp, IN PVOID Context );
VOID SendPacketToSerial( PVOID Context, PNDIS_PACKET Packet )
{
PIR_DEVICE pThisDev=(PIR_DEVICE)Context; NDIS_STATUS status; PPACKET_RESERVED_BLOCK Reserved=(PPACKET_RESERVED_BLOCK)&Packet->MiniportReservedEx[0];
Reserved->Context=pThisDev;
status = SendPacket( pThisDev, Packet, 0 );
if (status != NDIS_STATUS_PENDING) { //
// failed for some reason
//
NdisMSendComplete( pThisDev->hNdisAdapter, Packet, (NDIS_STATUS)status ); //
// This packet is finished, start the next on in the queue
//
StartNextPacket(&pThisDev->SendPacketQueue); }
//
// the write irp completion routine will finish things up
//
return; }
/*****************************************************************************
* * Function: IrsirSend * * Synopsis: Send a packet to the serial driver or queue the packet to * be sent at a later time if a send is pending. * * Arguments: MiniportAdapterContext - pointer to current ir device object * pPacketToSend - pointer to packet to send * Flags - any flags set by protocol * * Returns: NDIS_STATUS_PENDING - This is generally what we should * return. We will call NdisMSendComplete * when the serial driver completes the * send. * * NDIS_STATUS_SUCCESS - We should never return this since * results will always be pending from * the serial driver. * * Algorithm: * * History: dd-mm-yyyy Author Comment * 10/7/1996 sholden author * * Notes: * * *****************************************************************************/
NDIS_STATUS IrsirSend( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET pPacketToSend, IN UINT Flags ) { PIR_DEVICE pThisDev; BOOLEAN fCompletionRoutine; NDIS_STATUS status;
DEBUGMSG(DBG_FUNC, ("+IrsirSend\n"));
pThisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
if (pThisDev->pSerialDevObj==NULL) {
return NDIS_STATUS_SUCCESS; }
QueuePacket( &pThisDev->SendPacketQueue, pPacketToSend );
DEBUGMSG(DBG_FUNC, ("-IrsirSend\n"));
return NDIS_STATUS_PENDING; }
/*****************************************************************************
* * Function: SendPacket * * Synopsis: * * Arguments: pThisDev - a pointer to the current ir device object * pPacketToSend - * Flags - * fCompletionRoutine - return TRUE if the completion routine will * be called * - else return FALSE * * Returns: NDIS_STATUS_PENDING - if irp is successfully sent to the serial * driver * NDIS_STATUS_INVALID_PACKET - if NdisToIrPacket fails * STATUS_Xxx - if IoCallDriver fails * * Algorithm: * * History: dd-mm-yyyy Author Comment * 10/7/1996 sholden author * * Notes: * * Since we know that we will only have one pending IRP_MJ_WRITE request at * a time, we will build an irp once in IrsirInitialize and keep it in the * ir device object, so we don't have to allocate it all the time and * allocate a new buffer all the time. * * *****************************************************************************/
NDIS_STATUS SendPacket( IN PIR_DEVICE pThisDev, IN PNDIS_PACKET pPacketToSend, IN UINT Flags ) { PIRP pSendIrp; UINT BytesToWrite; NDIS_STATUS status; BOOLEAN fConvertedPacket;
DEBUGMSG(DBG_FUNC, ("+SendPacket\n"));
//
// Initialize the mem of our buffer and io status block.
//
#if DBG
NdisZeroMemory( pThisDev->pSendIrpBuffer, MAX_IRDA_DATA_SIZE ); #endif
//
// Assume that the irp is all set with the proper parameters, all we
// need to do is convert the packet to an ir frame and copy into our buffer
// and send the irp.
//
fConvertedPacket = NdisToIrPacket( pThisDev, pPacketToSend, (PUCHAR)pThisDev->pSendIrpBuffer, MAX_IRDA_DATA_SIZE, &BytesToWrite );
if (fConvertedPacket == FALSE) { DEBUGMSG(DBG_ERR, (" NdisToIrPacket failed. Couldn't convert packet!\n")); status = NDIS_STATUS_INVALID_PACKET;
goto done; } { LARGE_INTEGER Time; KeQuerySystemTime(&Time);
LOG_ENTRY('XT', pThisDev, Time.LowPart/10000, BytesToWrite);
}
pSendIrp = SerialBuildReadWriteIrp( pThisDev->pSerialDevObj, IRP_MJ_WRITE, pThisDev->pSendIrpBuffer, BytesToWrite, NULL );
if (pSendIrp == NULL) { DEBUGMSG(DBG_ERR, (" SerialBuildReadWriteIrp failed.\n")); status = NDIS_STATUS_RESOURCES;
goto done; }
//
// Set up the completion routine for the write irp.
//
IoSetCompletionRoutine( pSendIrp, // irp to use
SerialIoCompleteWrite, // routine to call when irp is done
pPacketToSend, TRUE, // call on success
TRUE, // call on error
TRUE // call on cancel
);
//
// Call IoCallDriver to send the irp to the serial port.
//
DBGTIME("Send ");
//
// The completion routine will be called no matter what the status
// of IoCallDriver is.
//
status=NDIS_STATUS_PENDING;
IoCallDriver( pThisDev->pSerialDevObj, pSendIrp );
done: DEBUGMSG(DBG_FUNC, ("-SendPacket\n"));
return status; }
/*****************************************************************************
* * Function: SerialIoCompleteWrite * * Synopsis: * * Arguments: pSerialDevObj - pointer to the serial device object which * completed the irp * pIrp - the irp which was completed by the serial * device object * Context - the context given to IoSetCompletionRoutine * before calling IoCallDriver on the irp * The Context is a pointer to the ir device object. * * Returns: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine * (IofCompleteRequest) to stop working on the irp. * * Algorithm: * 1a) Indicate to the protocol the status of the write. * 1b) Return ownership of the packet to the protocol. * * 2) If any more packets are queue for sending, send another packet * to the serial driver. * If the attempt to send the packet to the serial driver fails, * return ownership of the packet to the protocol and * try another packet (until one succeeds). * * History: dd-mm-yyyy Author Comment * 10/8/1996 sholden author * * Notes: * * *****************************************************************************/
NTSTATUS SerialIoCompleteWrite( IN PDEVICE_OBJECT pSerialDevObj, IN PIRP pIrp, IN PVOID Context ) { PIR_DEVICE pThisDev; PNDIS_PACKET pPacketToSend; NTSTATUS status; PPACKET_RESERVED_BLOCK Reserved;
DEBUGMSG(DBG_FUNC, ("+SerialIoCompleteWrite\n"));
//
// The context given to IoSetCompletionRoutine is simply the the ir
// device object pointer.
//
pPacketToSend=(PNDIS_PACKET)Context;
Reserved=(PPACKET_RESERVED_BLOCK)&pPacketToSend->MiniportReservedEx[0];
pThisDev = (PIR_DEVICE)Reserved->Context;
status = pIrp->IoStatus.Status;
//
// Free the irp. We keep our buffer and user io status block.
//
IoFreeIrp(pIrp);
pIrp=NULL;
{ LARGE_INTEGER Time; KeQuerySystemTime(&Time);
LOG_ENTRY('CT', pThisDev, Time.LowPart/10000, status); } //
// Keep statistics.
//
if (status == STATUS_SUCCESS) {
pThisDev->packetsSent++;
} else {
pThisDev->packetsSentDropped++; }
//
// Indicate to the protocol the status of the sent packet and return
// ownership of the packet.
//
NdisMSendComplete( pThisDev->hNdisAdapter, pPacketToSend, (NDIS_STATUS)status );
//////////////////////////////////////////////////////////////
//
// We have completed a packet. Start another if there is one
// on the send queue.
//
//////////////////////////////////////////////////////////////
StartNextPacket(&pThisDev->SendPacketQueue);
DEBUGMSG(DBG_FUNC, ("-SerialIoCompleteWrite\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
|