397 lines
10 KiB
C
397 lines
10 KiB
C
|
/*****************************************************************************
|
||
|
*
|
||
|
* 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;
|
||
|
|
||
|
}
|