Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

396 lines
10 KiB

/*****************************************************************************
*
* 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;
}