mirror of https://github.com/tongzx/nt5src
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.
1461 lines
42 KiB
1461 lines
42 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rasirda.c
|
|
|
|
Abstract:
|
|
|
|
Miniport peice of the irda NDIS 5 miniport (WAN driver)
|
|
|
|
Author:
|
|
|
|
mbert 9-97
|
|
|
|
--*/
|
|
|
|
#include "rasirdap.h"
|
|
|
|
// Globals
|
|
#if DBG
|
|
|
|
#include <irioctl.h>
|
|
|
|
int DbgSettings =
|
|
DBG_INIT |
|
|
DBG_CONFIG |
|
|
DBG_CONNECT |
|
|
// DBG_SEND |
|
|
// DBG_RECV |
|
|
DBG_LIB_OBJ |
|
|
DBG_LIB_CONNECT |
|
|
DBG_ERROR |
|
|
1;
|
|
|
|
int DbgOutput =
|
|
DBG_OUTPUT_BUFFER |
|
|
// DBG_OUTPUT_DEBUGGER |
|
|
0;
|
|
|
|
PDRIVER_OBJECT pRasIrDriverObject;
|
|
PDEVICE_OBJECT pRasIrDeviceObject;
|
|
|
|
NTSTATUS
|
|
DbgDispatch(
|
|
PDEVICE_OBJECT pDeviceObject,
|
|
PIRP pIrp);
|
|
#endif
|
|
|
|
NDIS_SPIN_LOCK RasIrSpinLock;
|
|
LIST_ENTRY RasIrAdapterList;
|
|
|
|
const USHORT FcsTable[256] = {
|
|
0x0000,0x1189,0x2312,0x329B,0x4624,0x57AD,0x6536,0x74BF,
|
|
0x8C48,0x9DC1,0xAF5A,0xBED3,0xCA6C,0xDBE5,0xE97E,0xF8F7,
|
|
0x1081,0x0108,0x3393,0x221A,0x56A5,0x472C,0x75B7,0x643E,
|
|
0x9CC9,0x8D40,0xBFDB,0xAE52,0xDAED,0xCB64,0xF9FF,0xE876,
|
|
0x2102,0x308B,0x0210,0x1399,0x6726,0x76AF,0x4434,0x55BD,
|
|
0xAD4A,0xBCC3,0x8E58,0x9FD1,0xEB6E,0xFAE7,0xC87C,0xD9F5,
|
|
0x3183,0x200A,0x1291,0x0318,0x77A7,0x662E,0x54B5,0x453C,
|
|
0xBDCB,0xAC42,0x9ED9,0x8F50,0xFBEF,0xEA66,0xD8FD,0xC974,
|
|
0x4204,0x538D,0x6116,0x709F,0x0420,0x15A9,0x2732,0x36BB,
|
|
0xCE4C,0xDFC5,0xED5E,0xFCD7,0x8868,0x99E1,0xAB7A,0xBAF3,
|
|
0x5285,0x430C,0x7197,0x601E,0x14A1,0x0528,0x37B3,0x263A,
|
|
0xDECD,0xCF44,0xFDDF,0xEC56,0x98E9,0x8960,0xBBFB,0xAA72,
|
|
0x6306,0x728F,0x4014,0x519D,0x2522,0x34AB,0x0630,0x17B9,
|
|
0xEF4E,0xFEC7,0xCC5C,0xDDD5,0xA96A,0xB8E3,0x8A78,0x9BF1,
|
|
0x7387,0x620E,0x5095,0x411C,0x35A3,0x242A,0x16B1,0x0738,
|
|
0xFFCF,0xEE46,0xDCDD,0xCD54,0xB9EB,0xA862,0x9AF9,0x8B70,
|
|
0x8408,0x9581,0xA71A,0xB693,0xC22C,0xD3A5,0xE13E,0xF0B7,
|
|
0x0840,0x19C9,0x2B52,0x3ADB,0x4E64,0x5FED,0x6D76,0x7CFF,
|
|
0x9489,0x8500,0xB79B,0xA612,0xD2AD,0xC324,0xF1BF,0xE036,
|
|
0x18C1,0x0948,0x3BD3,0x2A5A,0x5EE5,0x4F6C,0x7DF7,0x6C7E,
|
|
0xA50A,0xB483,0x8618,0x9791,0xE32E,0xF2A7,0xC03C,0xD1B5,
|
|
0x2942,0x38CB,0x0A50,0x1BD9,0x6F66,0x7EEF,0x4C74,0x5DFD,
|
|
0xB58B,0xA402,0x9699,0x8710,0xF3AF,0xE226,0xD0BD,0xC134,
|
|
0x39C3,0x284A,0x1AD1,0x0B58,0x7FE7,0x6E6E,0x5CF5,0x4D7C,
|
|
0xC60C,0xD785,0xE51E,0xF497,0x8028,0x91A1,0xA33A,0xB2B3,
|
|
0x4A44,0x5BCD,0x6956,0x78DF,0x0C60,0x1DE9,0x2F72,0x3EFB,
|
|
0xD68D,0xC704,0xF59F,0xE416,0x90A9,0x8120,0xB3BB,0xA232,
|
|
0x5AC5,0x4B4C,0x79D7,0x685E,0x1CE1,0x0D68,0x3FF3,0x2E7A,
|
|
0xE70E,0xF687,0xC41C,0xD595,0xA12A,0xB0A3,0x8238,0x93B1,
|
|
0x6B46,0x7ACF,0x4854,0x59DD,0x2D62,0x3CEB,0x0E70,0x1FF9,
|
|
0xF78F,0xE606,0xD49D,0xC514,0xB1AB,0xA022,0x92B9,0x8330,
|
|
0x7BC7,0x6A4E,0x58D5,0x495C,0x3DE3,0x2C6A,0x1EF1,0x0F78
|
|
};
|
|
|
|
NDIS_STATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath);
|
|
|
|
NDIS_STATUS
|
|
QueryInformation(
|
|
IN PRASIR_ADAPTER pAdapter,
|
|
IN PRASIR_VC pVc,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG BytesWritten,
|
|
OUT PULONG BytesNeeded);
|
|
|
|
NDIS_STATUS
|
|
SetInformation(
|
|
IN PRASIR_ADAPTER pAdapter,
|
|
IN PRASIR_VC pVc,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG BytesRead,
|
|
OUT PULONG BytesNeeded);
|
|
|
|
|
|
#pragma NDIS_INIT_FUNCTION(DriverEntry)
|
|
|
|
NDIS_STATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath )
|
|
{
|
|
NDIS_STATUS Status;
|
|
NDIS_MINIPORT_CHARACTERISTICS MiniportChr;
|
|
NDIS_HANDLE NdisWrapperHandle;
|
|
#if DBG
|
|
UNICODE_STRING DeviceName;
|
|
int i;
|
|
#endif
|
|
|
|
DEBUGMSG(DBG_INIT, ("RASIR: DriverEntry\n"));
|
|
|
|
IrdaClientInitialize();
|
|
|
|
NdisAllocateSpinLock(&RasIrSpinLock);
|
|
|
|
InitializeListHead(&RasIrAdapterList);
|
|
|
|
NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject,
|
|
RegistryPath, NULL );
|
|
NdisZeroMemory( &MiniportChr, sizeof(MiniportChr) );
|
|
|
|
MiniportChr.MajorNdisVersion = NDIS_MajorVersion;
|
|
MiniportChr.MinorNdisVersion = NDIS_MinorVersion;
|
|
MiniportChr.Reserved = NDIS_USE_WAN_WRAPPER;
|
|
MiniportChr.HaltHandler = RasIrHalt;
|
|
MiniportChr.InitializeHandler = RasIrInitialize;
|
|
MiniportChr.ResetHandler = RasIrReset;
|
|
MiniportChr.ReturnPacketHandler = RasIrReturnPacket;
|
|
MiniportChr.CoActivateVcHandler = RasIrCoActivateVc;
|
|
MiniportChr.CoDeactivateVcHandler = RasIrCoDeactivateVc;
|
|
MiniportChr.CoSendPacketsHandler = RasIrCoSendPackets;
|
|
MiniportChr.CoRequestHandler = RasIrCoRequest;
|
|
|
|
// no CheckForHangHandler
|
|
// no DisableInterruptHandler
|
|
// no EnableInterruptHandler
|
|
// no HandleInterruptHandler
|
|
// no ISRHandler
|
|
// no QueryInformationHandler (see CoRequestHandler)
|
|
// no SendHandler (see CoSendPacketsHandler)
|
|
// no WanSendHandler (see CoSendPacketsHandler)
|
|
// no SetInformationHandler (see CoRequestHandler)
|
|
// no TransferDataHandler
|
|
// no WanTransferDataHandler
|
|
// no SendPacketsHandler (see CoSendPacketsHandler)
|
|
// no AllocateCompleteHandler
|
|
|
|
|
|
Status = NdisMRegisterMiniport(NdisWrapperHandle, &MiniportChr, sizeof(MiniportChr));
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: ->NdisMRegisterMiniport failed %x\n", Status));
|
|
NdisTerminateWrapper(NdisWrapperHandle, NULL);
|
|
}
|
|
|
|
#if 0
|
|
|
|
DbgMsgInit();
|
|
|
|
RtlInitUnicodeString(&DeviceName, L"\\Device\\RASIR");
|
|
|
|
Status = IoCreateDevice(
|
|
DriverObject, // DriverObject
|
|
0, // DeviceExtensionSize
|
|
&DeviceName, // DeviceName
|
|
FILE_DEVICE_NETWORK, // DeviceType
|
|
0, // DeviceCharacteristics
|
|
FALSE, // Exclusive?
|
|
&pRasIrDeviceObject); // DeviceObject pointer returned
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
DbgPrint("Failed to create device\n");
|
|
|
|
else
|
|
{
|
|
DriverObject->DriverUnload = NULL;
|
|
DriverObject->FastIoDispatch = NULL;
|
|
|
|
for (i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
|
{
|
|
DriverObject->MajorFunction[i] = DbgDispatch;
|
|
}
|
|
|
|
pRasIrDeviceObject->Flags |= DO_DIRECT_IO;
|
|
|
|
}
|
|
#endif
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
FreeAdapter(PRASIR_ADAPTER pAdapter)
|
|
{
|
|
|
|
ASSERT(IsListEmpty(&pAdapter->VcList));
|
|
|
|
#if DBG
|
|
pAdapter->Sig = 0xBAD;
|
|
#endif
|
|
|
|
NdisDeleteNPagedLookasideList(&pAdapter->WorkItemsLList);
|
|
NdisDeleteNPagedLookasideList(&pAdapter->AsyncBufLList);
|
|
|
|
NdisFreeMemory(pAdapter, sizeof(PRASIR_ADAPTER), 0);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrInitialize(
|
|
OUT PNDIS_STATUS OpenErrorStatus,
|
|
OUT PUINT SelectedMediumIndex,
|
|
IN PNDIS_MEDIUM MediumArray,
|
|
IN UINT MediumArraySize,
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN NDIS_HANDLE WrapperConfigurationContext)
|
|
{
|
|
UINT i;
|
|
PRASIR_ADAPTER pAdapter;
|
|
NDIS_CALL_MANAGER_CHARACTERISTICS CallMgrChr;
|
|
CO_ADDRESS_FAMILY Family;
|
|
NDIS_STATUS Status;
|
|
NDIS_HANDLE hConfig;
|
|
PNDIS_CONFIGURATION_PARAMETER Value;
|
|
NDIS_STRING TapiLineNameString = NDIS_STRING_CONST("TapiLineName");
|
|
NDIS_STRING ModemPortString = NDIS_STRING_CONST("ModemPort");
|
|
ULONG ModemPort;
|
|
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: Miniport initialize\n"));
|
|
|
|
for (i = 0; i < MediumArraySize; ++i)
|
|
{
|
|
if (MediumArray[i] == NdisMediumCoWan)
|
|
break;
|
|
}
|
|
|
|
if (i == MediumArraySize)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: No matching media\n"));
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
*SelectedMediumIndex = i;
|
|
|
|
NdisAllocateMemoryWithTag((PVOID *)&pAdapter, sizeof(RASIR_ADAPTER),
|
|
MT_RASIR_ADAPTER);
|
|
|
|
if (pAdapter == NULL)
|
|
return NDIS_STATUS_RESOURCES;
|
|
|
|
NdisZeroMemory(pAdapter, sizeof(RASIR_ADAPTER));
|
|
|
|
InitializeListHead(&pAdapter->VcList);
|
|
|
|
InitializeListHead(&pAdapter->EndpList);
|
|
|
|
NdisInitializeNPagedLookasideList(
|
|
&pAdapter->WorkItemsLList,
|
|
NULL, NULL, 0,
|
|
sizeof(NDIS_WORK_ITEM),
|
|
MT_RASIR_WORKITEM, // RasIr work item
|
|
10);
|
|
|
|
NdisInitializeNPagedLookasideList(
|
|
&pAdapter->AsyncBufLList,
|
|
NULL, NULL, 0,
|
|
sizeof(ASYNC_BUFFER),
|
|
MT_RASIR_ASYNCBUF, // RasIr work item
|
|
0);
|
|
|
|
NdisAllocateSpinLock(&pAdapter->SpinLock);
|
|
|
|
NdisOpenConfiguration(&Status, &hConfig, WrapperConfigurationContext);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
pAdapter->TapiLineNameBuf[0] = 0;
|
|
pAdapter->TapiLineName.Buffer = pAdapter->TapiLineNameBuf;
|
|
pAdapter->TapiLineName.Length = 0;
|
|
pAdapter->TapiLineName.MaximumLength = sizeof(pAdapter->TapiLineNameBuf);
|
|
|
|
NdisReadConfiguration(&Status,
|
|
&Value,
|
|
hConfig,
|
|
&TapiLineNameString,
|
|
NdisParameterString);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
RtlCopyUnicodeString(&pAdapter->TapiLineName, &Value->ParameterData.StringData);
|
|
*(PWCHAR)(pAdapter->TapiLineName.Buffer + (pAdapter->TapiLineName.MaximumLength)/sizeof(WCHAR)) = UNICODE_NULL;
|
|
}
|
|
|
|
NdisReadConfiguration(&Status,
|
|
&Value,
|
|
hConfig,
|
|
&ModemPortString,
|
|
NdisParameterInteger);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
pAdapter->ModemPort = (BOOLEAN) Value->ParameterData.IntegerData;
|
|
}
|
|
|
|
NdisCloseConfiguration(hConfig);
|
|
}
|
|
|
|
DEBUGMSG(DBG_CONFIG, ("RASIR: ModemPort = %d\n", pAdapter->ModemPort));
|
|
|
|
pAdapter->MiniportAdapterHandle = MiniportAdapterHandle;
|
|
|
|
pAdapter->Info.MaxFrameSize = IRDA_MAX_DATA_SIZE;
|
|
pAdapter->Info.MaxSendWindow = 4;
|
|
pAdapter->Info.FramingBits = PPP_FRAMING |
|
|
PPP_COMPRESS_ADDRESS_CONTROL |
|
|
PPP_COMPRESS_PROTOCOL_FIELD;
|
|
pAdapter->Info.DesiredACCM = 0;
|
|
|
|
#if DBG
|
|
pAdapter->Sig = (ULONG)ADAPTER_SIG;
|
|
#endif
|
|
|
|
// Inform NDIS of the attributes of our adapter. Set the
|
|
// 'MiniportAdapterContext' returned to us by NDIS when it calls our
|
|
// handlers to the address of our adapter control block. Turn off
|
|
// hardware oriented timeouts.
|
|
//
|
|
|
|
NdisMSetAttributesEx(
|
|
MiniportAdapterHandle,
|
|
(NDIS_HANDLE)pAdapter,
|
|
(UINT)-1,
|
|
NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT
|
|
| NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT,
|
|
NdisInterfaceInternal);
|
|
|
|
|
|
NdisZeroMemory(&Family, sizeof(Family));
|
|
Family.MajorVersion = NDIS_MajorVersion;
|
|
Family.MinorVersion = NDIS_MinorVersion;
|
|
Family.AddressFamily = CO_ADDRESS_FAMILY_TAPI_PROXY;
|
|
|
|
NdisZeroMemory(&CallMgrChr, sizeof(CallMgrChr));
|
|
CallMgrChr.MajorVersion = NDIS_MajorVersion;
|
|
CallMgrChr.MinorVersion = NDIS_MinorVersion;
|
|
CallMgrChr.CmCreateVcHandler = RasIrCmCreateVc;
|
|
CallMgrChr.CmDeleteVcHandler = RasIrCmDeleteVc;
|
|
CallMgrChr.CmOpenAfHandler = RasIrCmOpenAf;
|
|
CallMgrChr.CmCloseAfHandler = RasIrCmCloseAf;
|
|
CallMgrChr.CmRegisterSapHandler = RasIrCmRegisterSap;
|
|
CallMgrChr.CmDeregisterSapHandler = RasIrCmDeregisterSap;
|
|
CallMgrChr.CmMakeCallHandler = RasIrCmMakeCall;
|
|
CallMgrChr.CmCloseCallHandler = RasIrCmCloseCall;
|
|
CallMgrChr.CmIncomingCallCompleteHandler= RasIrCmIncomingCallComplete;
|
|
CallMgrChr.CmActivateVcCompleteHandler = RasIrCmActivateVcComplete;
|
|
CallMgrChr.CmDeactivateVcCompleteHandler= RasIrCmDeactivateVcComplete;
|
|
CallMgrChr.CmModifyCallQoSHandler = RasIrCmModifyCallQoS;
|
|
CallMgrChr.CmRequestHandler = RasIrCmRequest;
|
|
// no CmAddPartyHandler
|
|
// no CmDropPartyHandler
|
|
|
|
Status = NdisMCmRegisterAddressFamily(
|
|
MiniportAdapterHandle, &Family, &CallMgrChr,
|
|
sizeof(CallMgrChr));
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
FreeAdapter(pAdapter);
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: NdisMCmRegisterFamily failed %X\n",
|
|
Status));
|
|
}
|
|
else
|
|
{
|
|
NdisInterlockedInsertTailList(&RasIrAdapterList,
|
|
&pAdapter->Linkage,
|
|
&RasIrSpinLock);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
RasIrHalt(
|
|
IN NDIS_HANDLE MiniportAdapterContext)
|
|
{
|
|
PRASIR_ADAPTER pAdapter = MiniportAdapterContext;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
NdisAcquireSpinLock(&RasIrSpinLock);
|
|
|
|
RemoveEntryList(&pAdapter->Linkage);
|
|
|
|
NdisReleaseSpinLock(&RasIrSpinLock);
|
|
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: Halt!\n"));
|
|
|
|
FreeAdapter(pAdapter);
|
|
|
|
return;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrReset(
|
|
OUT PBOOLEAN AddressingReset,
|
|
IN NDIS_HANDLE MiniportAdapterContext)
|
|
{
|
|
return NDIS_STATUS_NOT_RESETTABLE;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrCoActivateVc(
|
|
IN NDIS_HANDLE MiniportVcContext,
|
|
IN OUT PCO_CALL_PARAMETERS CallParameters)
|
|
{
|
|
#if DBG
|
|
DbgBreakPoint();
|
|
#endif
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
RasIrCoDeactivateVc(
|
|
IN NDIS_HANDLE MiniportVcContext)
|
|
{
|
|
#if DBG
|
|
DbgBreakPoint();
|
|
#endif
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
UINT
|
|
AddAsyncFraming(
|
|
IN PUCHAR pOutBuf,
|
|
IN PNDIS_BUFFER pNdisBuf,
|
|
IN ULONG Accm)
|
|
{
|
|
PUCHAR pData;
|
|
int DataLen;
|
|
USHORT Fcs = 0xFFFF;
|
|
PUCHAR pBuf = pOutBuf;
|
|
PUCHAR pEndBuf = pOutBuf + ASYNC_BUF_SIZE;
|
|
|
|
NdisQueryBufferSafe(pNdisBuf, &pData, &DataLen, NormalPagePriority);
|
|
|
|
if (pData == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ASSERT(DataLen);
|
|
|
|
*pBuf++ = AF_FLAG_CHAR;
|
|
|
|
while (DataLen != 0)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < DataLen; i++)
|
|
{
|
|
Fcs = CALC_FCS(Fcs, pData[i]);
|
|
STUFF_BYTE(pBuf, pData[i], Accm);
|
|
}
|
|
|
|
NdisGetNextBuffer(pNdisBuf, &pNdisBuf);
|
|
|
|
if (pNdisBuf)
|
|
{
|
|
NdisQueryBufferSafe(pNdisBuf, &pData, &DataLen, NormalPagePriority);
|
|
|
|
if (pData == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (pBuf > pEndBuf)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Fcs = ~(Fcs);
|
|
|
|
STUFF_BYTE(pBuf, ((CHAR) (Fcs & 0xFF)), Accm);
|
|
STUFF_BYTE(pBuf, ((CHAR) (Fcs >> 8)), Accm);
|
|
|
|
*pBuf++ = AF_FLAG_CHAR;
|
|
|
|
return (UINT)((UINT_PTR)pBuf - (UINT_PTR) pOutBuf);
|
|
}
|
|
|
|
VOID
|
|
RasIrCoSendPackets(
|
|
IN NDIS_HANDLE MiniportVcContext,
|
|
IN PPNDIS_PACKET PacketArray,
|
|
IN UINT NumberOfPackets )
|
|
{
|
|
PRASIR_VC pVc = MiniportVcContext;
|
|
UINT i;
|
|
PNDIS_BUFFER pNdisBuf;
|
|
UINT PacketLen;
|
|
NTSTATUS Status = NDIS_STATUS_SUCCESS;
|
|
BOOLEAN VcDown = FALSE;
|
|
PASYNC_BUFFER pAsyncBuf;
|
|
PMDL pSendNdisBuf;
|
|
|
|
GOODVC(pVc);
|
|
|
|
for (i = 0; i < NumberOfPackets; i++)
|
|
{
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
NdisQueryPacket(PacketArray[i], NULL, NULL, &pNdisBuf, &PacketLen);
|
|
|
|
ASSERT(PacketLen <= IRDA_MAX_DATA_SIZE);
|
|
|
|
*((PVOID *) &PacketArray[i]->MiniportReserved[0]) = NULL;
|
|
|
|
NdisAcquireSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
REFADD(&pVc->RefCnt, 'DNES');
|
|
|
|
pVc->OutstandingSends += 1;
|
|
|
|
if (!(pVc->Flags & VCF_IRDA_OPEN))
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: Not sending on Vc %X, Irda is closed\n", pVc));
|
|
Status = NDIS_STATUS_CLOSED;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
if (!pVc->AsyncFraming)
|
|
{
|
|
pSendNdisBuf = pNdisBuf;
|
|
}
|
|
else
|
|
{
|
|
pAsyncBuf = NdisAllocateFromNPagedLookasideList(
|
|
&pVc->pAdapter->AsyncBufLList);
|
|
|
|
*((PVOID *) &PacketArray[i]->MiniportReserved[0]) = pAsyncBuf;
|
|
|
|
if (!pAsyncBuf)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
UINT FrameLen;
|
|
|
|
pAsyncBuf->pNdisBuf = NULL;
|
|
|
|
FrameLen = AddAsyncFraming(pAsyncBuf->Buf, pNdisBuf,
|
|
pVc->LinkInfo.SendACCM);
|
|
if (!FrameLen)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: not sending, AsyncFraming failed\n"));
|
|
IrdaSendComplete(pVc, PacketArray[i], Status);
|
|
continue;
|
|
}
|
|
|
|
NdisAllocateBuffer(&Status, &pAsyncBuf->pNdisBuf,
|
|
pVc->TxBufferPool, pAsyncBuf->Buf, FrameLen);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
pSendNdisBuf = pAsyncBuf->pNdisBuf;
|
|
}
|
|
else
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: NdisAllocateBuffer failed %X\n", Status));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
IrdaSend(pVc->IrdaConnContext, pSendNdisBuf, PacketArray[i]);
|
|
}
|
|
else
|
|
{
|
|
IrdaSendComplete(pVc, PacketArray[i], Status);
|
|
continue;
|
|
}
|
|
|
|
DEBUGMSG(DBG_SEND, ("RASIR: IrdaSend %X len %d pending\n",
|
|
PacketArray[i], PacketLen));
|
|
}
|
|
}
|
|
|
|
VOID
|
|
RasIrReceiveComplete(
|
|
PRASIR_VC pVc,
|
|
PVOID pRxBuf)
|
|
{
|
|
if (pVc->AsyncFraming)
|
|
{
|
|
// Async frames where already completed in
|
|
// ProcessAsyncRxPacket() so just return the
|
|
// buffer owned by rasir to the BufList
|
|
|
|
NdisFreeToNPagedLookasideList(
|
|
&pVc->pAdapter->AsyncBufLList,
|
|
pRxBuf);
|
|
}
|
|
else
|
|
{
|
|
IrdaReceiveComplete(pVc->IrdaConnContext,
|
|
(PIRDA_RECVBUF) pRxBuf);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
RasIrReturnPacket(
|
|
IN NDIS_HANDLE MiniportAdapterContext,
|
|
IN PNDIS_PACKET pNdisPacket)
|
|
{
|
|
PVOID pRxBuf;
|
|
PRASIR_VC pVc;
|
|
PNDIS_BUFFER pNdisBuf;
|
|
|
|
pVc = *((PRASIR_VC *) &pNdisPacket->MiniportReserved[0]);
|
|
pRxBuf = *((PVOID *) &pNdisPacket->MiniportReserved[sizeof(PUCHAR)]);
|
|
|
|
|
|
GOODVC(pVc);
|
|
|
|
DEBUGMSG(DBG_RECV, ("RASIR: ReturnPacket %X\n", pRxBuf));
|
|
|
|
RasIrReceiveComplete(pVc, pRxBuf);
|
|
|
|
NdisUnchainBufferAtFront(pNdisPacket, &pNdisBuf);
|
|
|
|
NdisFreeBuffer(pNdisBuf);
|
|
|
|
NdisFreePacket(pNdisPacket);
|
|
|
|
REFDEL(&pVc->RefCnt, 'VCER');
|
|
|
|
return;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrCoRequest(
|
|
IN NDIS_HANDLE MiniportAdapterContext,
|
|
IN NDIS_HANDLE MiniportVcContext,
|
|
IN OUT PNDIS_REQUEST NdisRequest)
|
|
{
|
|
NDIS_STATUS Status;
|
|
PRASIR_ADAPTER pAdapter = MiniportAdapterContext;
|
|
PRASIR_VC pVc = MiniportVcContext;
|
|
|
|
DEBUGMSG(DBG_CONFIG, ("RASIR: RasIrCoRequest() type %X\n",
|
|
NdisRequest->RequestType));
|
|
|
|
switch (NdisRequest->RequestType)
|
|
{
|
|
case NdisRequestQueryInformation:
|
|
{
|
|
Status = QueryInformation(
|
|
pAdapter,
|
|
pVc,
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid,
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
|
|
&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded );
|
|
break;
|
|
}
|
|
|
|
case NdisRequestSetInformation:
|
|
{
|
|
Status = SetInformation(
|
|
pAdapter,
|
|
pVc,
|
|
NdisRequest->DATA.SET_INFORMATION.Oid,
|
|
NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
|
|
NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
|
|
&NdisRequest->DATA.SET_INFORMATION.BytesRead,
|
|
&NdisRequest->DATA.SET_INFORMATION.BytesNeeded );
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
QueryInformation(
|
|
IN PRASIR_ADAPTER pAdapter,
|
|
IN PRASIR_VC pVc,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG BytesWritten,
|
|
OUT PULONG BytesNeeded)
|
|
{
|
|
NDIS_STATUS status;
|
|
ULONG ulInfo;
|
|
VOID* pInfo;
|
|
ULONG ulInfoLen;
|
|
|
|
status = NDIS_STATUS_SUCCESS;
|
|
|
|
// The cases in this switch statement find or create a buffer containing
|
|
// the requested information and point 'pInfo' at it, noting it's length
|
|
// in 'ulInfoLen'. Since many of the OIDs return a ULONG, a 'ulInfo'
|
|
// buffer is set up as the default.
|
|
//
|
|
ulInfo = 0;
|
|
pInfo = &ulInfo;
|
|
ulInfoLen = sizeof(ulInfo);
|
|
|
|
DEBUGMSG(DBG_CONFIG, ("RASIR: QueryInformation oid:%X\n", Oid));
|
|
|
|
switch (Oid)
|
|
{
|
|
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
|
{
|
|
DEBUGMSG(DBG_CONFIG, (" OID_GET_MAXIMUM_LOOKAHEAD = %d\n",
|
|
IRDA_MAX_DATA_SIZE));
|
|
ulInfo = IRDA_MAX_DATA_SIZE;
|
|
break;
|
|
}
|
|
|
|
case OID_GEN_MAC_OPTIONS:
|
|
{
|
|
// Report a bitmask defining optional properties of the driver.
|
|
//
|
|
// NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA promises that our receive
|
|
// buffer is not on a device-specific card.
|
|
//
|
|
// NDIS_MAC_OPTION_TRANSFERS_NOT_PEND promises we won't return
|
|
// NDIS_STATUS_PENDING from our TransferData handler which is true
|
|
// since we don't have one.
|
|
//
|
|
ulInfo = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA
|
|
| NDIS_MAC_OPTION_TRANSFERS_NOT_PEND;
|
|
DEBUGMSG(DBG_CONFIG, (" OID_GEN_MAC_OPTIONS = %d\n",ulInfo));
|
|
break;
|
|
}
|
|
|
|
case OID_WAN_MEDIUM_SUBTYPE:
|
|
{
|
|
// Report the media subtype we support. NDISWAN may use this in
|
|
// the future (doesn't now) to provide framing differences for
|
|
// different media.
|
|
//
|
|
DEBUGMSG(DBG_CONFIG, (" OID_WAN_MEDIUM_SUBTYPE\n"));
|
|
if (pAdapter->ModemPort)
|
|
{
|
|
ulInfo = NdisWanMediumSerial;
|
|
}
|
|
else
|
|
{
|
|
ulInfo = NdisWanMediumIrda;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case OID_WAN_CO_GET_INFO:
|
|
{
|
|
// Report the capabilities of the adapter.
|
|
//
|
|
DEBUGMSG(DBG_CONFIG, (" OID_WAN_CO_GET_INFO\n"));
|
|
pInfo = &pAdapter->Info;
|
|
ulInfoLen = sizeof(NDIS_WAN_CO_INFO);
|
|
break;
|
|
}
|
|
|
|
case OID_WAN_CO_GET_LINK_INFO:
|
|
{
|
|
// Report the current state of the link.
|
|
//
|
|
DEBUGMSG(DBG_CONFIG, (" OID_WAN_CO_GET_LINK_INFO\n"));
|
|
|
|
if (!pVc)
|
|
return NDIS_STATUS_INVALID_DATA;
|
|
|
|
pInfo = &pVc->LinkInfo;
|
|
|
|
ulInfoLen = sizeof(NDIS_WAN_CO_GET_LINK_INFO);
|
|
break;
|
|
}
|
|
|
|
case OID_WAN_CO_GET_COMP_INFO:
|
|
{
|
|
// Report the type of compression we provide, which is none.
|
|
//
|
|
DEBUGMSG(DBG_CONFIG, (" OID_WAN_CO_GET_COMP_INFO\n"));
|
|
status = NDIS_STATUS_NOT_SUPPORTED;
|
|
ulInfoLen = 0;
|
|
break;
|
|
}
|
|
|
|
case OID_WAN_CO_GET_STATS_INFO:
|
|
{
|
|
// Because L2TP doesn't do compression, NDISWAN will use it's own
|
|
// statistics and not query ours.
|
|
//
|
|
ASSERT( !"OID_WAN_CO_GET_STATS_INFO?" );
|
|
status = NDIS_STATUS_NOT_SUPPORTED;
|
|
ulInfoLen = 0;
|
|
break;
|
|
}
|
|
|
|
case OID_PNP_QUERY_POWER:
|
|
DEBUGMSG(DBG_CONFIG, (" OID_PNP_QUERY_POWER\n"));
|
|
status = NDIS_STATUS_NOT_SUPPORTED;
|
|
ulInfoLen = 0;
|
|
break;
|
|
|
|
case OID_PNP_CAPABILITIES:
|
|
DEBUGMSG(DBG_CONFIG, (" OID_PNP_CAP\n"));
|
|
status = NDIS_STATUS_NOT_SUPPORTED;
|
|
ulInfoLen = 0;
|
|
break;
|
|
|
|
case OID_PNP_SET_POWER:
|
|
DEBUGMSG(DBG_CONFIG, (" OID_PNP_SET_POWER\n"));
|
|
status = NDIS_STATUS_NOT_SUPPORTED;
|
|
ulInfoLen = 0;
|
|
break;
|
|
|
|
default:
|
|
{
|
|
DEBUGMSG(DBG_CONFIG, ( " Oid $%08x?\n", Oid));
|
|
status = NDIS_STATUS_INVALID_OID;
|
|
ulInfoLen = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ulInfoLen > InformationBufferLength)
|
|
{
|
|
// Caller's buffer is too small. Tell him what he needs.
|
|
//
|
|
*BytesNeeded = ulInfoLen;
|
|
status = NDIS_STATUS_INVALID_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
// Copy the found result to caller's buffer.
|
|
//
|
|
if (ulInfoLen > 0)
|
|
{
|
|
NdisMoveMemory( InformationBuffer, pInfo, ulInfoLen );
|
|
}
|
|
|
|
*BytesNeeded = *BytesWritten = ulInfoLen;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
SetInformation(
|
|
IN PRASIR_ADAPTER pAdapter,
|
|
IN PRASIR_VC pVc,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG BytesRead,
|
|
OUT PULONG BytesNeeded)
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
DEBUGMSG(DBG_CONFIG, ("RASIR: SetInformation oid:%X\n", Oid));
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
switch (Oid)
|
|
{
|
|
case OID_WAN_CO_SET_LINK_INFO:
|
|
{
|
|
// Read new link state settings.
|
|
//
|
|
DEBUGMSG(DBG_CONFIG, (" OID_WAN_CO_SET_LINK_INFO\n"));
|
|
|
|
if (InformationBufferLength < sizeof(NDIS_WAN_CO_SET_LINK_INFO))
|
|
{
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
*BytesRead = 0;
|
|
}
|
|
else
|
|
{
|
|
if (!pVc)
|
|
return NDIS_STATUS_INVALID_DATA;
|
|
|
|
ASSERT( sizeof(pVc->LinkInfo)
|
|
== sizeof(NDIS_WAN_CO_SET_LINK_INFO) );
|
|
|
|
NdisMoveMemory(&pVc->LinkInfo, InformationBuffer,
|
|
sizeof(pVc->LinkInfo) );
|
|
|
|
DEBUGMSG(DBG_CONFIG, (" MaxSend %d MaxRecv %d SendAccm %X RecvAccm %X\n",
|
|
pVc->LinkInfo.MaxSendFrameSize,
|
|
pVc->LinkInfo.MaxRecvFrameSize,
|
|
pVc->LinkInfo.SendACCM,
|
|
pVc->LinkInfo.RecvACCM));
|
|
|
|
*BytesRead = sizeof(NDIS_WAN_CO_SET_LINK_INFO);
|
|
}
|
|
*BytesNeeded = sizeof(NDIS_WAN_CO_SET_LINK_INFO);
|
|
}
|
|
break;
|
|
|
|
case OID_WAN_CO_SET_COMP_INFO:
|
|
{
|
|
// L2TP doesn't provide compression. Neither does IrDA
|
|
//
|
|
DEBUGMSG(DBG_CONFIG, (" OID_WAN_CO_SET_COMP_INFO\n"));
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
*BytesRead = *BytesNeeded = 0;
|
|
break;
|
|
}
|
|
|
|
case OID_PNP_QUERY_POWER:
|
|
DEBUGMSG(DBG_CONFIG, (" OID_PNP_QUERY_POWER\n"));
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
*BytesRead = *BytesNeeded = 0;
|
|
break;
|
|
|
|
case OID_PNP_CAPABILITIES:
|
|
DEBUGMSG(DBG_CONFIG, (" OID_PNP_CAP\n"));
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
*BytesRead = *BytesNeeded = 0;
|
|
break;
|
|
|
|
case OID_PNP_SET_POWER:
|
|
DEBUGMSG(DBG_CONFIG, (" OID_PNP_SET_POWER\n"));
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
*BytesRead = *BytesNeeded = 0;
|
|
break;
|
|
|
|
#if 0
|
|
// These OIDs are mandatory according to current doc, but since
|
|
// NDISWAN never requests them they are omitted.
|
|
//
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
case OID_GEN_PROTOCOL_OPTIONS:
|
|
case OID_WAN_PROTOCOL_TYPE:
|
|
case OID_WAN_HEADER_FORMAT:
|
|
#endif
|
|
default:
|
|
{
|
|
DEBUGMSG(DBG_CONFIG, ("Oid $%08x?\n", Oid ));
|
|
Status = NDIS_STATUS_INVALID_OID;
|
|
*BytesRead = *BytesNeeded = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
ProcessAsyncRxPacket(
|
|
PRASIR_VC pVc,
|
|
PIRDA_RECVBUF pIrdaRxBuf)
|
|
{
|
|
PASYNC_BUFFER pReturnRxBuf = NULL;
|
|
BOOLEAN EndOfFrame = FALSE;
|
|
PASYNC_BUFFER pCurrAsyncBuf;
|
|
UINT i;
|
|
CHAR Byte;
|
|
|
|
//DbgMsgBuf(pIrdaRxBuf->Buf, pIrdaRxBuf->BufLen);
|
|
|
|
for (i = 0; i < pIrdaRxBuf->BufLen; i++)
|
|
{
|
|
//
|
|
// If we are not currently reasembling a frame
|
|
// in pCurrAsyncBuf then get a new one
|
|
//
|
|
|
|
if (pVc->pCurrAsyncBuf == NULL)
|
|
{
|
|
pVc->AsyncFramingState = RX_READY;
|
|
|
|
if (!(pCurrAsyncBuf = NdisAllocateFromNPagedLookasideList(
|
|
&pVc->pAdapter->AsyncBufLList)))
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: Failed to allocate AsyncBuf\n"));
|
|
return;
|
|
}
|
|
|
|
pCurrAsyncBuf->BufLen = 0;
|
|
pVc->pCurrAsyncBuf = pCurrAsyncBuf;
|
|
}
|
|
else
|
|
{
|
|
pCurrAsyncBuf = pVc->pCurrAsyncBuf;
|
|
}
|
|
|
|
Byte = pIrdaRxBuf->Buf[i];
|
|
|
|
switch (pVc->AsyncFramingState)
|
|
{
|
|
case RX_READY:
|
|
|
|
if (Byte == AF_FLAG_CHAR)
|
|
{
|
|
pVc->AsyncFramingState = RX_RX;
|
|
}
|
|
break;
|
|
|
|
case RX_RX:
|
|
switch (Byte)
|
|
{
|
|
case AF_FLAG_CHAR:
|
|
|
|
// We have a complete frame, put it on the completed
|
|
// list
|
|
|
|
pVc->AsyncFramingState = RX_READY;
|
|
|
|
if (pCurrAsyncBuf->BufLen > 2)
|
|
{
|
|
// remove FCS, IrDA is reliable so I don't look at it
|
|
|
|
pCurrAsyncBuf->BufLen -= 2;
|
|
|
|
NdisInterlockedInsertTailList(
|
|
&pVc->CompletedAsyncBufList,
|
|
&pCurrAsyncBuf->Linkage,
|
|
&pVc->pAdapter->SpinLock);
|
|
|
|
DEBUGMSG(DBG_RECV, ("RASIR: Complete async frame %d, %d of %d\n",
|
|
pVc->pCurrAsyncBuf->BufLen, i, pIrdaRxBuf->BufLen));
|
|
|
|
pVc->pCurrAsyncBuf = NULL;
|
|
|
|
}
|
|
else
|
|
{
|
|
// frame too small, we'll just ignore it
|
|
pCurrAsyncBuf->BufLen = 0;
|
|
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: Async failure 1\n"));
|
|
}
|
|
|
|
break;
|
|
|
|
case AF_ESC_CHAR:
|
|
pVc->AsyncFramingState = RX_ESC;
|
|
break;
|
|
|
|
default:
|
|
if (pCurrAsyncBuf->BufLen >= ASYNC_BUF_SIZE)
|
|
{
|
|
pCurrAsyncBuf->BufLen = 0;
|
|
pVc->AsyncFramingState = RX_READY;
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: Async buffer overflow\n"));
|
|
|
|
}
|
|
else
|
|
{
|
|
pCurrAsyncBuf->Buf[pCurrAsyncBuf->BufLen] = Byte;
|
|
pCurrAsyncBuf->BufLen += 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case RX_ESC:
|
|
if (pCurrAsyncBuf->BufLen >= ASYNC_BUF_SIZE)
|
|
{
|
|
pCurrAsyncBuf->BufLen = 0;
|
|
pVc->AsyncFramingState = RX_READY;
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: Async failure 2\n"));
|
|
}
|
|
else
|
|
{
|
|
pCurrAsyncBuf->Buf[pCurrAsyncBuf->BufLen] = (Byte ^= AF_COMP_BIT);
|
|
pCurrAsyncBuf->BufLen += 1;
|
|
pVc->AsyncFramingState = RX_RX;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
IndicateReceive(
|
|
PRASIR_VC pVc,
|
|
PIRDA_RECVBUF pRecvBuf,
|
|
PASYNC_BUFFER pAsyncBuf,
|
|
BOOLEAN LastBuf)
|
|
{
|
|
PNDIS_PACKET pNdisPacket;
|
|
PNDIS_BUFFER pNdisBuf;
|
|
NDIS_STATUS Status;
|
|
KIRQL OldIrql;
|
|
PVOID pRecvOrAsyncBuf = NULL;
|
|
int Len;
|
|
|
|
REFADD(&pVc->RefCnt, 'VCER');
|
|
|
|
if (pVc->AsyncFraming)
|
|
{
|
|
ASSERT(pAsyncBuf && !pRecvBuf);
|
|
pRecvOrAsyncBuf = pAsyncBuf;
|
|
Len = pAsyncBuf->BufLen;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(pRecvBuf && !pAsyncBuf);
|
|
pRecvOrAsyncBuf = pRecvBuf;
|
|
Len = pRecvBuf->BufLen;
|
|
}
|
|
|
|
if (!(pVc->Flags & VCF_OPEN))
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: VC not open yet, dropping packet\n"));
|
|
goto error1;
|
|
}
|
|
NdisAllocatePacket(&Status, &pNdisPacket, pVc->RxPacketPool);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: NdisAllocatePacket failed, %X\n",
|
|
Status));
|
|
goto error1;
|
|
}
|
|
|
|
if (pVc->AsyncFraming)
|
|
{
|
|
NdisAllocateBuffer(&Status, &pNdisBuf, pVc->RxBufferPool,
|
|
pAsyncBuf->Buf, pAsyncBuf->BufLen);
|
|
}
|
|
else
|
|
{
|
|
NdisAllocateBuffer(&Status, &pNdisBuf, pVc->RxBufferPool,
|
|
pRecvBuf->Buf, pRecvBuf->BufLen);
|
|
}
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: NdisAllocateBuffer failed, %X\n",
|
|
Status));
|
|
goto error2;
|
|
}
|
|
|
|
NdisChainBufferAtFront(pNdisPacket, pNdisBuf);
|
|
|
|
*((PRASIR_VC *) &pNdisPacket->MiniportReserved[0]) = pVc;
|
|
*((PVOID *) &pNdisPacket->MiniportReserved[sizeof(PUCHAR)]) = pRecvOrAsyncBuf;
|
|
|
|
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
|
|
|
if (LastBuf)
|
|
{
|
|
NDIS_SET_PACKET_STATUS(pNdisPacket, NDIS_STATUS_RESOURCES);
|
|
|
|
DEBUGMSG(DBG_RECV, ("RASIR: Irtdi out of buffers\n"));
|
|
}
|
|
else
|
|
{
|
|
NDIS_SET_PACKET_STATUS(pNdisPacket, NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
Status = NDIS_GET_PACKET_STATUS(pNdisPacket);
|
|
|
|
DEBUGMSG(DBG_RECV, ("RASIR: ->NdisMCoIndicateReceive %d\n", Len));
|
|
|
|
NdisMCoIndicateReceivePacket(pVc->NdisVcHandle, &pNdisPacket, 1);
|
|
|
|
NdisMCoReceiveComplete(pVc->pAdapter->MiniportAdapterHandle);
|
|
|
|
KeLowerIrql(OldIrql);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS) {
|
|
//
|
|
// the packets will be returned later
|
|
//
|
|
return;
|
|
}
|
|
|
|
|
|
NdisUnchainBufferAtFront(pNdisPacket, &pNdisBuf);
|
|
|
|
NdisFreeBuffer(pNdisBuf);
|
|
|
|
error2:
|
|
|
|
NdisFreePacket(pNdisPacket);
|
|
|
|
error1:
|
|
|
|
DEBUGMSG(DBG_RECV, ("RASIR: RecvIndication completed synchronously for %X\n",
|
|
pRecvOrAsyncBuf));
|
|
|
|
RasIrReceiveComplete(pVc, pRecvOrAsyncBuf);
|
|
|
|
REFDEL(&pVc->RefCnt, 'VCER');
|
|
|
|
}
|
|
|
|
VOID
|
|
IrdaReceiveIndication(
|
|
PVOID ConnectionContext,
|
|
PIRDA_RECVBUF pRecvBuf,
|
|
BOOLEAN LastBuf)
|
|
{
|
|
PRASIR_VC pVc = ConnectionContext;
|
|
PASYNC_BUFFER pAsyncRxBuf;
|
|
|
|
|
|
DEBUGMSG(DBG_RECV, ("RASIR: IrdaReceiveIndication %X, %d bytes\n",
|
|
pRecvBuf, pRecvBuf->BufLen));
|
|
|
|
if (!pVc)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: IrdaReceiveIndication NULL vc\n"));
|
|
ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
GOODVC(pVc);
|
|
|
|
GOODADAPTER(pVc->pAdapter);
|
|
|
|
if (pVc->IrModemCall && pVc->ModemState < MS_ONLINE)
|
|
{
|
|
ProcessOfflineRxBuf(pVc, pRecvBuf);
|
|
|
|
IrdaReceiveComplete(pVc->IrdaConnContext, pRecvBuf);
|
|
|
|
return;
|
|
}
|
|
|
|
if (pVc->AsyncFraming)
|
|
{
|
|
ProcessAsyncRxPacket(pVc, pRecvBuf);
|
|
|
|
// We are done with pRecvBuf. The async framing has
|
|
// been removed and the data is now contained in a buffer
|
|
// on the CompletedAsyncBufList or if not a full frame
|
|
// then in pCurrAsyncBuf
|
|
|
|
IrdaReceiveComplete(pVc->IrdaConnContext, pRecvBuf);
|
|
|
|
while ((pAsyncRxBuf = (PASYNC_BUFFER) NdisInterlockedRemoveHeadList(
|
|
&pVc->CompletedAsyncBufList,
|
|
&pVc->pAdapter->SpinLock)) != NULL)
|
|
{
|
|
IndicateReceive(pVc, NULL, pAsyncRxBuf, LastBuf);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IndicateReceive(pVc, pRecvBuf, NULL, LastBuf);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
IrdaSendComplete(
|
|
PVOID ConnectContext,
|
|
PVOID SendContext,
|
|
NTSTATUS Status)
|
|
{
|
|
PRASIR_VC pVc = ConnectContext;
|
|
PNDIS_PACKET pNdisPacket = (PNDIS_PACKET) SendContext;
|
|
|
|
DEBUGMSG(DBG_SEND, ("RASIR: IrdaSendComplete vc:%X, Packet %X\n", pVc, SendContext));
|
|
|
|
GOODVC(pVc);
|
|
|
|
if (SendContext == RASIR_INTERNAL_SEND)
|
|
{
|
|
ASSERT(pVc->pOfflineNdisBuf);
|
|
|
|
NdisFreeBuffer(pVc->pOfflineNdisBuf);
|
|
|
|
pVc->pOfflineNdisBuf = NULL;
|
|
|
|
goto EXIT;
|
|
}
|
|
|
|
if (pVc->AsyncFraming)
|
|
{
|
|
PASYNC_BUFFER pAsyncBuf;
|
|
|
|
pAsyncBuf = *((PASYNC_BUFFER *) &pNdisPacket->MiniportReserved[0]);
|
|
|
|
if (pAsyncBuf)
|
|
{
|
|
if (pAsyncBuf->pNdisBuf)
|
|
{
|
|
NdisFreeBuffer(pAsyncBuf->pNdisBuf);
|
|
}
|
|
|
|
NdisFreeToNPagedLookasideList(&pVc->pAdapter->AsyncBufLList,
|
|
pAsyncBuf);
|
|
}
|
|
}
|
|
|
|
NdisMCoSendComplete(Status, pVc->NdisVcHandle, pNdisPacket);
|
|
|
|
NdisAcquireSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
pVc->OutstandingSends -= 1; // do interlockedDec dork
|
|
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
if ((pVc->Flags & VCF_CLOSE_PEND) && (pVc->OutstandingSends == 0))
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Outstanding send to 0, CompleteClose\n"));
|
|
CompleteClose(pVc);
|
|
}
|
|
|
|
EXIT:
|
|
|
|
REFDEL(&pVc->RefCnt, 'DNES');
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ScheduleWork(
|
|
IN PRASIR_ADAPTER pAdapter,
|
|
IN NDIS_PROC pProc,
|
|
IN PVOID pContext )
|
|
|
|
// Schedules a PASSIVE IRQL callback to routine 'pProc' which will be
|
|
// passed 'pContext'. 'PAdapter' is the adapter control block from which
|
|
// the work item is allocated.
|
|
//
|
|
// Returns NDIS_STATUS_SUCCESS or an error code.
|
|
//
|
|
{
|
|
NDIS_STATUS status;
|
|
NDIS_WORK_ITEM* pWork;
|
|
|
|
pWork = NdisAllocateFromNPagedLookasideList(&pAdapter->WorkItemsLList);
|
|
|
|
if (!pWork)
|
|
{
|
|
ASSERT( !"Alloc work?" );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
NdisInitializeWorkItem( pWork, pProc, pContext );
|
|
|
|
status = NdisScheduleWorkItem( pWork );
|
|
if (status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
ASSERT( !"SchedWork?" );
|
|
NdisFreeToNPagedLookasideList(&pAdapter->WorkItemsLList, pWork);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
#if DBG
|
|
|
|
NTSTATUS
|
|
DbgDispatch(
|
|
PDEVICE_OBJECT pDeviceObject,
|
|
PIRP pIrp)
|
|
{
|
|
PIO_STACK_LOCATION pIrpSp;
|
|
|
|
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
|
|
|
|
if (pIrpSp->MajorFunction != IRP_MJ_DEVICE_CONTROL)
|
|
{
|
|
pIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
pIrp->IoStatus.Information = 0;
|
|
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ASSERT(pIrpSp->MajorFunction != IRP_MJ_INTERNAL_DEVICE_CONTROL);
|
|
|
|
switch(pIrpSp->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
case IOCTL_IRDA_GET_DBG_MSGS:
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
if ((Status = DbgMsgIrp(pIrp, pIrpSp)) == STATUS_PENDING)
|
|
{
|
|
return STATUS_PENDING;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_IRDA_GET_DBG_SETTINGS:
|
|
{
|
|
UINT *Settings = pIrp->AssociatedIrp.SystemBuffer;
|
|
|
|
Settings[0] = DbgSettings;
|
|
Settings[1] = DbgOutput;
|
|
|
|
pIrp->IoStatus.Information = sizeof(UINT)*2;
|
|
pIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
case IOCTL_IRDA_SET_DBG_SETTINGS:
|
|
{
|
|
UINT *Settings = pIrp->AssociatedIrp.SystemBuffer;
|
|
|
|
DbgSettings = Settings[0];
|
|
DbgOutput = Settings[1];
|
|
|
|
pIrp->IoStatus.Information = 0;
|
|
pIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
pIrp->IoStatus.Information = 0;
|
|
pIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
#endif
|