Leaked source code of windows server 2003
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.

2288 lines
70 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 1996 Microsoft Corporation
  4. *
  5. * Module: irndis.c
  6. *
  7. * Author: mbert 8-96
  8. *
  9. * This modules provides the MAC interface of IrLAP (formerly IrMAC
  10. * of Pegasus). It is now an Ndis protocol interface for communicating
  11. * with Miniport Ir framers.
  12. *
  13. * |---------|
  14. * | |
  15. * | IrLAP |
  16. * | |
  17. * |---------|
  18. * /|\ |
  19. * | |
  20. * IrlapUp(IrlapContext, | | IrmacDown(LinkContext,
  21. * IrdaMsg) | | IrdaMsg)
  22. * | |
  23. * | \|/
  24. * |----------|
  25. * | |
  26. * | IrNDIS |
  27. * | |
  28. * |----------|
  29. * /|\ |
  30. * | | Ndis Interface for transports
  31. * | |
  32. * | \|/
  33. * |---------------------------|
  34. * | Ndis Wrapper |
  35. * |---------------------------|
  36. * |------------|
  37. * | |
  38. * | Miniport |
  39. * | Framer |
  40. * | |
  41. * |------------|
  42. *
  43. *
  44. *
  45. *
  46. */
  47. #include <irda.h>
  48. #include <ntddndis.h>
  49. #include <ndis.h>
  50. #include <irioctl.h>
  51. #include <irlap.h>
  52. #include <irlapp.h>
  53. #include <irlmp.h>
  54. #include <irmem.h>
  55. #include <decdirda.h>
  56. #undef offsetof
  57. #include "irndis.tmh"
  58. #define WORK_BUF_SIZE 256
  59. #define NICK_NAME_LEN 18
  60. #define DISABLE_CODE_PAGING 1
  61. #define DISABLE_DATA_PAGING 2
  62. #ifdef ALLOC_DATA_PRAGMA
  63. #pragma data_seg("PAGE")
  64. #endif
  65. NDIS_HANDLE NdisIrdaHandle; // Handle to identify Irda to Ndis
  66. // when opening adapters
  67. UINT DisconnectTime; // WARNING: This variable is used
  68. // to lock down all pageable data
  69. // (see MmLockPageDataSection below)
  70. UINT HintCharSet;
  71. UINT Slots;
  72. UCHAR NickName[NICK_NAME_LEN + 1];
  73. UINT NickNameLen;
  74. UINT MaxWindow;
  75. UINT NoCopyCnt;
  76. UINT CopyCnt;
  77. extern VOID (*CloseRasIrdaAddresses)();
  78. #ifdef ALLOC_DATA_PRAGMA
  79. #pragma data_seg()
  80. #endif
  81. typedef struct _IRDA_REQUEST {
  82. NDIS_REQUEST NdisRequest;
  83. NDIS_STATUS Status;
  84. NDIS_EVENT Event;
  85. } IRDA_REQUEST, *PIRDA_REQUEST;
  86. VOID
  87. OidToLapQos(
  88. const UINT ParmTable[],
  89. UINT ValArray[],
  90. UINT Cnt,
  91. PUINT pBitField,
  92. BOOLEAN MaxVal);
  93. NDIS_STATUS
  94. IrdaQueryOid(
  95. IN PIRDA_LINK_CB pIrdaLinkCb,
  96. IN NDIS_OID Oid,
  97. OUT PUINT pQBuf,
  98. IN OUT PUINT pQBufLen);
  99. NDIS_STATUS
  100. IrdaSetOid(
  101. IN PIRDA_LINK_CB pIrdaLinkCb,
  102. IN NDIS_OID Oid,
  103. IN UINT Val);
  104. VOID IrdaSendComplete(
  105. IN NDIS_HANDLE Context,
  106. IN PNDIS_PACKET NdisPacket,
  107. IN NDIS_STATUS Status
  108. );
  109. VOID InitializeLocalQos(
  110. IN OUT IRDA_QOS_PARMS *pQos,
  111. IN PNDIS_STRING ConfigPath);
  112. VOID IrdaBindAdapter(
  113. OUT PNDIS_STATUS pStatus,
  114. IN NDIS_HANDLE BindContext,
  115. IN PNDIS_STRING AdapterName,
  116. IN PVOID SystemSpecific1,
  117. IN PVOID SystemSpecific2);
  118. VOID
  119. MacControlRequest(
  120. PIRDA_LINK_CB pIrdaLinkCb,
  121. PIRDA_MSG pMsg);
  122. VOID
  123. ConfirmDataRequest(
  124. PIRDA_LINK_CB pIrdaLinkCb,
  125. PIRDA_MSG pMsg);
  126. VOID
  127. MediaSenseExp(PVOID Context);
  128. #ifdef ALLOC_PRAGMA
  129. #pragma alloc_text(INIT, IrdaInitialize)
  130. #pragma alloc_text(PAGEIRDA, OidToLapQos) // WARNING: This function is used
  131. // to lock all paged code down
  132. // (see MmLockPagableCodeSection
  133. // below)
  134. #pragma alloc_text(PAGEIRDA, IrdaQueryOid)
  135. #pragma alloc_text(PAGEIRDA, IrdaSetOid)
  136. #pragma alloc_text(PAGEIRDA, MacControlRequest)
  137. #pragma alloc_text(PAGEIRDA, MediaSenseExp)
  138. #pragma alloc_text(PAGEIRDA, InitializeLocalQos)
  139. #endif
  140. _inline
  141. VOID
  142. DBG_FRAME(
  143. PIRDA_LINK_CB pIrdaLinkCb,
  144. BOOLEAN Transmit,
  145. UCHAR *pFrame,
  146. UINT HdrLen,
  147. UINT DataLen)
  148. {
  149. LARGE_INTEGER li;
  150. int CurrTime, Diff, Inc;
  151. Inc = KeQueryTimeIncrement();
  152. KeQueryTickCount(&li);
  153. CurrTime = (int) li.LowPart * Inc;
  154. Diff = CurrTime - pIrdaLinkCb->LastTime;
  155. pIrdaLinkCb->LastTime = CurrTime;
  156. if ((WPP_LEVEL_ENABLED(DBG_TXFRAME) && Transmit)
  157. ||
  158. (WPP_LEVEL_ENABLED(DBG_RXFRAME) && !Transmit)) {
  159. UCHAR StrBuf[256];
  160. int FrameType;
  161. DecodeIRDA(&FrameType,
  162. pFrame,
  163. HdrLen,
  164. StrBuf,
  165. sizeof(StrBuf),
  166. 0,
  167. TRUE,
  168. 1);
  169. if (Transmit) {
  170. DEBUGMSG(DBG_TXFRAME, ("%03d %s %s len:%d\n", Diff/10000,
  171. "Tx:",
  172. (char*)StrBuf,
  173. DataLen));
  174. } else {
  175. DEBUGMSG(DBG_RXFRAME, ("%03d %s %s len:%d\n", Diff/10000,
  176. "Rx:",
  177. (char*)StrBuf,
  178. DataLen));
  179. }
  180. }
  181. }
  182. /***************************************************************************
  183. *
  184. * Translate the result of an OID query to IrLAP QOS definition
  185. *
  186. */
  187. VOID
  188. OidToLapQos(
  189. const UINT ParmTable[],
  190. UINT ValArray[],
  191. UINT Cnt,
  192. PUINT pBitField,
  193. BOOLEAN MaxVal)
  194. {
  195. UINT i, j;
  196. PAGED_CODE();
  197. *pBitField = 0;
  198. for (i = 0; i < Cnt; i++)
  199. {
  200. for (j = 0; j <= PV_TABLE_MAX_BIT; j++)
  201. {
  202. if (ValArray[i] == ParmTable[j])
  203. {
  204. *pBitField |= 1<<j;
  205. if (MaxVal)
  206. return;
  207. }
  208. else if (MaxVal)
  209. {
  210. *pBitField |= 1<<j;
  211. }
  212. }
  213. }
  214. }
  215. /***************************************************************************
  216. *
  217. * Perform a synchronous request for an OID
  218. *
  219. */
  220. NDIS_STATUS
  221. IrdaQueryOid(
  222. IN PIRDA_LINK_CB pIrdaLinkCb,
  223. IN NDIS_OID Oid,
  224. OUT PUINT pQBuf,
  225. IN OUT PUINT pQBufLen)
  226. {
  227. IRDA_REQUEST Request;
  228. NDIS_STATUS Status;
  229. PAGED_CODE();
  230. NdisInitializeEvent(&Request.Event);
  231. NdisResetEvent(&Request.Event);
  232. Request.NdisRequest.RequestType = NdisRequestQueryInformation;
  233. Request.NdisRequest.DATA.QUERY_INFORMATION.Oid = Oid;
  234. Request.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = pQBuf;
  235. Request.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = *pQBufLen * sizeof(UINT);
  236. NdisRequest(&Status, pIrdaLinkCb->NdisBindingHandle, &Request.NdisRequest);
  237. if (Status == NDIS_STATUS_PENDING) {
  238. NdisWaitEvent(&Request.Event, 0);
  239. Status = Request.Status;
  240. }
  241. *pQBufLen = Request.NdisRequest.DATA.QUERY_INFORMATION.BytesWritten / sizeof(UINT);
  242. return Status;
  243. }
  244. /***************************************************************************
  245. *
  246. * Perform a synchronous request to sent an OID
  247. *
  248. */
  249. NDIS_STATUS
  250. IrdaSetOid(
  251. IN PIRDA_LINK_CB pIrdaLinkCb,
  252. IN NDIS_OID Oid,
  253. IN UINT Val)
  254. {
  255. IRDA_REQUEST Request;
  256. NDIS_STATUS Status;
  257. PAGED_CODE();
  258. NdisInitializeEvent(&Request.Event);
  259. NdisResetEvent(&Request.Event);
  260. Request.NdisRequest.RequestType = NdisRequestSetInformation;
  261. Request.NdisRequest.DATA.SET_INFORMATION.Oid = Oid;
  262. Request.NdisRequest.DATA.SET_INFORMATION.InformationBuffer = &Val;
  263. Request.NdisRequest.DATA.SET_INFORMATION.InformationBufferLength = sizeof(UINT);
  264. NdisRequest(&Status, pIrdaLinkCb->NdisBindingHandle, &Request.NdisRequest);
  265. if (Status == NDIS_STATUS_PENDING) {
  266. NdisWaitEvent(&Request.Event, 0);
  267. Status = Request.Status;
  268. }
  269. return Status;
  270. }
  271. /***************************************************************************
  272. *
  273. * Allocate an Irda message for IrLap to use for control frames.
  274. * This modules owns these so IrLAP doesn't have to deal with the
  275. * Ndis send complete.
  276. *
  277. */
  278. IRDA_MSG *
  279. AllocTxMsg(PIRDA_LINK_CB pIrdaLinkCb)
  280. {
  281. IRDA_MSG *pMsg;
  282. pMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList(
  283. &pIrdaLinkCb->TxMsgFreeList, &pIrdaLinkCb->SpinLock);
  284. if (pMsg == NULL)
  285. {
  286. if (pIrdaLinkCb->TxMsgFreeListLen > 10)
  287. {
  288. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: too many tx msgs\n")));
  289. return NULL;
  290. }
  291. NdisAllocateMemoryWithTag(&pMsg,
  292. sizeof(IRDA_MSG) + IRDA_MSG_DATA_SIZE,
  293. MT_IRNDIS_TX_IMSG);
  294. if (pMsg == NULL)
  295. {
  296. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: Aloc tx msg failed\n")));
  297. return NULL;
  298. }
  299. pIrdaLinkCb->TxMsgFreeListLen++;
  300. }
  301. // Indicate driver owns message
  302. pMsg->IRDA_MSG_pOwner = &pIrdaLinkCb->TxMsgFreeList;
  303. // Initialize pointers
  304. pMsg->IRDA_MSG_pHdrWrite = \
  305. pMsg->IRDA_MSG_pHdrRead = pMsg->IRDA_MSG_Header + IRDA_HEADER_LEN;
  306. pMsg->IRDA_MSG_pBase = \
  307. pMsg->IRDA_MSG_pRead = \
  308. pMsg->IRDA_MSG_pWrite = (UCHAR *) pMsg + sizeof(IRDA_MSG);
  309. pMsg->IRDA_MSG_pLimit = pMsg->IRDA_MSG_pBase + IRDA_MSG_DATA_SIZE-1;
  310. return pMsg;
  311. }
  312. /***************************************************************************
  313. *
  314. *
  315. */
  316. #if DBG
  317. VOID
  318. CleanupRxMsgList(
  319. PIRDA_LINK_CB pIrdaLinkCb,
  320. BOOLEAN LinkClose)
  321. #else
  322. VOID
  323. CleanupRxMsgList(
  324. PIRDA_LINK_CB pIrdaLinkCb)
  325. #endif
  326. {
  327. PIRDA_MSG pMsg, pMsgNext;
  328. NdisAcquireSpinLock(&pIrdaLinkCb->SpinLock);
  329. for (pMsg = (PIRDA_MSG) pIrdaLinkCb->RxMsgList.Flink;
  330. pMsg != (PIRDA_MSG) &pIrdaLinkCb->RxMsgList;
  331. pMsg = pMsgNext)
  332. {
  333. pMsgNext = (PIRDA_MSG) pMsg->Linkage.Flink;
  334. if (pMsg->Prim == MAC_DATA_IND)
  335. {
  336. RemoveEntryList(&pMsg->Linkage);
  337. pMsg->Prim = MAC_DATA_RESP;
  338. NdisReleaseSpinLock(&pIrdaLinkCb->SpinLock);
  339. IrmacDown(pIrdaLinkCb, pMsg);
  340. NdisAcquireSpinLock(&pIrdaLinkCb->SpinLock);
  341. #if DBG
  342. if (!LinkClose)
  343. {
  344. ++pIrdaLinkCb->DelayedRxFrameCnt;
  345. }
  346. #endif
  347. }
  348. else
  349. {
  350. DbgPrint("IRNDIS: MAC_DATA_CONF on RxMsgList, not completing!\n");
  351. }
  352. }
  353. NdisReleaseSpinLock(&pIrdaLinkCb->SpinLock);
  354. }
  355. /***************************************************************************
  356. *
  357. * Process MAC_CONTROL_REQs from IrLAP
  358. *
  359. */
  360. VOID
  361. MacControlRequest(
  362. PIRDA_LINK_CB pIrdaLinkCb,
  363. PIRDA_MSG pMsg)
  364. {
  365. NDIS_STATUS Status;
  366. PAGED_CODE();
  367. switch (pMsg->IRDA_MSG_Op)
  368. {
  369. case MAC_INITIALIZE_LINK:
  370. case MAC_RECONFIG_LINK:
  371. pIrdaLinkCb->ExtraBofs = pMsg->IRDA_MSG_NumBOFs;
  372. pIrdaLinkCb->MinTat = pMsg->IRDA_MSG_MinTat;
  373. Status = IrdaSetOid(pIrdaLinkCb,
  374. OID_IRDA_LINK_SPEED,
  375. (UINT) pMsg->IRDA_MSG_Baud);
  376. return;
  377. case MAC_MEDIA_SENSE:
  378. pIrdaLinkCb->MediaBusy = FALSE;
  379. IrdaSetOid(pIrdaLinkCb, OID_IRDA_MEDIA_BUSY, 0);
  380. pIrdaLinkCb->MediaSenseTimer.Timeout = pMsg->IRDA_MSG_SenseTime;
  381. IrdaTimerStart(&pIrdaLinkCb->MediaSenseTimer);
  382. return;
  383. case MAC_CLOSE_LINK:
  384. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: Closelink %p\n"), pIrdaLinkCb));
  385. IrdaTimerStop(&pIrdaLinkCb->MediaSenseTimer);
  386. NdisResetEvent(&pIrdaLinkCb->OpenCloseEvent);
  387. #ifdef IRDA_RX_SYSTEM_THREAD
  388. KeSetEvent(&pIrdaLinkCb->EvKillRxThread, 0, FALSE);
  389. #endif
  390. #if DBG
  391. CleanupRxMsgList(pIrdaLinkCb, TRUE);
  392. #else
  393. CleanupRxMsgList(pIrdaLinkCb);
  394. #endif
  395. NdisCloseAdapter(&Status, pIrdaLinkCb->NdisBindingHandle);
  396. if (Status == NDIS_STATUS_PENDING)
  397. {
  398. NdisWaitEvent(&pIrdaLinkCb->OpenCloseEvent, 0);
  399. Status = pIrdaLinkCb->OpenCloseStatus;
  400. }
  401. if (pIrdaLinkCb->UnbindContext != NULL)
  402. {
  403. NdisCompleteUnbindAdapter(pIrdaLinkCb->UnbindContext, NDIS_STATUS_SUCCESS);
  404. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: NdisCompleteUndindAdapter for link %p called\n"),
  405. pIrdaLinkCb));
  406. }
  407. REFDEL(&pIrdaLinkCb->RefCnt, 'DNIB');
  408. return;
  409. }
  410. ASSERT(0);
  411. }
  412. VOID
  413. ConfirmDataRequest(
  414. PIRDA_LINK_CB pIrdaLinkCb,
  415. PIRDA_MSG pMsg)
  416. {
  417. if (pMsg->IRDA_MSG_pOwner == &pIrdaLinkCb->TxMsgFreeList)
  418. {
  419. // If TxMsgFreeList is the owner, then this is a control
  420. // frame which isn't confirmed.
  421. NdisInterlockedInsertTailList(&pIrdaLinkCb->TxMsgFreeList,
  422. &pMsg->Linkage,
  423. &pIrdaLinkCb->SpinLock);
  424. return;
  425. }
  426. ASSERT(pMsg->IRDA_MSG_RefCnt);
  427. if (InterlockedDecrement(&pMsg->IRDA_MSG_RefCnt) == 0)
  428. {
  429. pMsg->Prim = MAC_DATA_CONF;
  430. NdisInterlockedInsertTailList(&pIrdaLinkCb->RxMsgList,
  431. &pMsg->Linkage,
  432. &pIrdaLinkCb->SpinLock);
  433. #ifdef IRDA_RX_SYSTEM_THREAD
  434. KeSetEvent(&pIrdaLinkCb->EvRxMsgReady, 0, FALSE);
  435. #else
  436. IrdaEventSchedule(&pIrdaLinkCb->EvRxMsgReady, pIrdaLinkCb);
  437. #endif
  438. }
  439. }
  440. /***************************************************************************
  441. *
  442. * Process control and data requests from IrLAP
  443. *
  444. */
  445. VOID
  446. IrmacDown(
  447. IN PVOID Context,
  448. PIRDA_MSG pMsg)
  449. {
  450. NDIS_STATUS Status;
  451. PNDIS_PACKET NdisPacket = NULL;
  452. PNDIS_BUFFER NdisBuffer = NULL;
  453. PIRDA_PROTOCOL_RESERVED pReserved;
  454. PNDIS_IRDA_PACKET_INFO IrdaPacketInfo;
  455. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) Context;
  456. DEBUGMSG(DBG_FUNCTION, (TEXT("IrmacDown()\n")));
  457. switch (pMsg->Prim)
  458. {
  459. case MAC_CONTROL_REQ:
  460. MacControlRequest(pIrdaLinkCb, pMsg);
  461. return;
  462. case MAC_DATA_RESP:
  463. // A data response from IrLAP is the mechanism used to
  464. // return ownership of received packets back to Ndis
  465. if (pMsg->DataContext)
  466. {
  467. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: return packet %p\n"), pMsg->DataContext));
  468. NdisReturnPackets(&((PNDIS_PACKET)pMsg->DataContext), 1);
  469. }
  470. NdisInterlockedInsertTailList(&pIrdaLinkCb->RxMsgFreeList,
  471. &pMsg->Linkage,
  472. &pIrdaLinkCb->SpinLock);
  473. pIrdaLinkCb->RxMsgFreeListLen++;
  474. return;
  475. case MAC_DATA_REQ:
  476. Status = NDIS_STATUS_FAILURE;
  477. // IrDA is half duplex. If there is something on the
  478. // receive list when we go to transmit then something
  479. // went very wrong (delay in the miniport somewhere).
  480. // Return these frames back to the miniport.
  481. #if DBG
  482. CleanupRxMsgList(pIrdaLinkCb, FALSE);
  483. #else
  484. CleanupRxMsgList(pIrdaLinkCb);
  485. #endif
  486. if (pIrdaLinkCb->UnbindContext || pIrdaLinkCb->LowPowerSt)
  487. {
  488. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: Dropping MAC_DATA_REQ, link closing or low power state\n")));
  489. goto Cleanup;
  490. }
  491. pReserved = (PIRDA_PROTOCOL_RESERVED) NdisInterlockedRemoveHeadList(
  492. &pIrdaLinkCb->PacketList, &pIrdaLinkCb->SpinLock);
  493. if (pReserved == NULL)
  494. {
  495. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: NdisPacket pool has been depleted\n")));
  496. goto Cleanup;
  497. }
  498. NdisPacket = CONTAINING_RECORD(pReserved, NDIS_PACKET, ProtocolReserved);
  499. ASSERT(pMsg->IRDA_MSG_pHdrWrite-pMsg->IRDA_MSG_pHdrRead);
  500. // Allocate buffer for frame header
  501. NdisAllocateBuffer(&Status, &NdisBuffer, pIrdaLinkCb->BufferPool,
  502. pMsg->IRDA_MSG_pHdrRead,
  503. (UINT) (pMsg->IRDA_MSG_pHdrWrite-pMsg->IRDA_MSG_pHdrRead));
  504. if (Status != NDIS_STATUS_SUCCESS)
  505. {
  506. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: NdisAllocateBuffer failed\n")));
  507. ASSERT(0);
  508. goto Cleanup;
  509. }
  510. NdisChainBufferAtFront(NdisPacket, NdisBuffer);
  511. // if frame contains data, alloc buffer for data
  512. if (pMsg->IRDA_MSG_pWrite - pMsg->IRDA_MSG_pRead)
  513. {
  514. NdisAllocateBuffer(&Status, &NdisBuffer, pIrdaLinkCb->BufferPool,
  515. pMsg->IRDA_MSG_pRead,
  516. (UINT) (pMsg->IRDA_MSG_pWrite-pMsg->IRDA_MSG_pRead));
  517. if (Status != NDIS_STATUS_SUCCESS)
  518. {
  519. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: NdisAllocateBuffer failed\n")));
  520. ASSERT(0);
  521. goto Cleanup;
  522. }
  523. NdisChainBufferAtBack(NdisPacket, NdisBuffer);
  524. }
  525. pReserved =
  526. (PIRDA_PROTOCOL_RESERVED)(NdisPacket->ProtocolReserved);
  527. pReserved->pMsg = pMsg;
  528. IrdaPacketInfo = (PNDIS_IRDA_PACKET_INFO) \
  529. (pReserved->MediaInfo.ClassInformation);
  530. IrdaPacketInfo->ExtraBOFs = pIrdaLinkCb->ExtraBofs;
  531. #if DBG_TIMESTAMP
  532. {
  533. LARGE_INTEGER li;
  534. KeQueryTickCount(&li);
  535. pReserved->TimeStamp[0] = (int) li.LowPart * KeQueryTimeIncrement();
  536. }
  537. #endif
  538. if (pIrdaLinkCb->WaitMinTat)
  539. {
  540. IrdaPacketInfo->MinTurnAroundTime = pIrdaLinkCb->MinTat;
  541. pIrdaLinkCb->WaitMinTat = FALSE;
  542. }
  543. else
  544. {
  545. IrdaPacketInfo->MinTurnAroundTime = 0;
  546. }
  547. NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(
  548. NdisPacket,
  549. &pReserved->MediaInfo,
  550. sizeof(MEDIA_SPECIFIC_INFORMATION) -1 +
  551. sizeof(NDIS_IRDA_PACKET_INFO));
  552. DBG_FRAME(
  553. pIrdaLinkCb,
  554. TRUE, //DBG_TXFRAME,
  555. pMsg->IRDA_MSG_pHdrRead,
  556. (UINT) (pMsg->IRDA_MSG_pHdrWrite-pMsg->IRDA_MSG_pHdrRead),
  557. (UINT) ((pMsg->IRDA_MSG_pHdrWrite-pMsg->IRDA_MSG_pHdrRead) +
  558. (pMsg->IRDA_MSG_pWrite - pMsg->IRDA_MSG_pRead)) -
  559. IRLAP_HEADER_LEN);
  560. InterlockedIncrement(&pIrdaLinkCb->SendOutCnt);
  561. #if DBG
  562. {
  563. ULONG PacketLength;
  564. NdisQueryPacket(NdisPacket,NULL,NULL,NULL,&PacketLength);
  565. ASSERT(PacketLength <= 2048);
  566. }
  567. #endif
  568. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: NdisSend(%p)\n outstaning %d"), NdisPacket,pIrdaLinkCb->SendOutCnt));
  569. NdisSendPackets(
  570. pIrdaLinkCb->NdisBindingHandle,
  571. &NdisPacket,
  572. 1
  573. );
  574. return;
  575. default:
  576. ASSERT(0);
  577. return;
  578. }
  579. return;
  580. Cleanup:
  581. ConfirmDataRequest(pIrdaLinkCb, pMsg);
  582. if (NdisPacket != NULL) {
  583. NdisUnchainBufferAtFront(NdisPacket, &NdisBuffer);
  584. while (NdisBuffer) {
  585. NdisFreeBuffer(NdisBuffer);
  586. NdisUnchainBufferAtFront(NdisPacket, &NdisBuffer);
  587. }
  588. NdisReinitializePacket(NdisPacket);
  589. NdisInterlockedInsertTailList(&pIrdaLinkCb->PacketList,
  590. &pReserved->Linkage,
  591. &pIrdaLinkCb->SpinLock);
  592. }
  593. }
  594. /***************************************************************************
  595. *
  596. * Callback for media sense timer expirations
  597. *
  598. */
  599. VOID
  600. MediaSenseExp(PVOID Context)
  601. {
  602. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) Context;
  603. IRDA_MSG IMsg;
  604. UINT MediaBusy;
  605. UINT Cnt = 1;
  606. PAGED_CODE();
  607. IMsg.Prim = MAC_CONTROL_CONF;
  608. IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
  609. IMsg.IRDA_MSG_OpStatus = MAC_MEDIA_BUSY;
  610. if (pIrdaLinkCb->MediaBusy == FALSE)
  611. {
  612. if (IrdaQueryOid(pIrdaLinkCb, OID_IRDA_MEDIA_BUSY, &MediaBusy,
  613. &Cnt) == NDIS_STATUS_SUCCESS && !MediaBusy)
  614. {
  615. IMsg.IRDA_MSG_OpStatus = MAC_MEDIA_CLEAR;
  616. }
  617. }
  618. LOCK_LINK(pIrdaLinkCb);
  619. IrlapUp(pIrdaLinkCb->IrlapContext, &IMsg);
  620. UNLOCK_LINK(pIrdaLinkCb);
  621. }
  622. /***************************************************************************
  623. *
  624. * Protocol open adapter complete handler
  625. *
  626. */
  627. VOID IrdaOpenAdapterComplete(
  628. IN NDIS_HANDLE IrdaBindingContext,
  629. IN NDIS_STATUS Status,
  630. IN NDIS_STATUS OpenErrorStatus
  631. )
  632. {
  633. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext;
  634. DEBUGMSG(DBG_NDIS,
  635. (TEXT("+IrdaOpenAdapterComplete() BindingContext %p, Status %x\n"),
  636. IrdaBindingContext, Status));
  637. pIrdaLinkCb->OpenCloseStatus = Status;
  638. NdisSetEvent(&pIrdaLinkCb->OpenCloseEvent);
  639. DEBUGMSG(DBG_NDIS, (TEXT("-IrdaOpenAdapterComplete()\n")));
  640. return;
  641. }
  642. /***************************************************************************
  643. *
  644. * Protocol close adapter complete handler
  645. *
  646. */
  647. VOID IrdaCloseAdapterComplete(
  648. IN NDIS_HANDLE IrdaBindingContext,
  649. IN NDIS_STATUS Status
  650. )
  651. {
  652. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext;
  653. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: IrdaCloseAdapterComplete()\n")));
  654. pIrdaLinkCb->OpenCloseStatus = Status;
  655. NdisSetEvent(&pIrdaLinkCb->OpenCloseEvent);
  656. return;
  657. }
  658. /***************************************************************************
  659. *
  660. * Protocol send complete handler
  661. *
  662. */
  663. VOID IrdaSendComplete(
  664. IN NDIS_HANDLE Context,
  665. IN PNDIS_PACKET NdisPacket,
  666. IN NDIS_STATUS Status
  667. )
  668. {
  669. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) Context;
  670. PIRDA_PROTOCOL_RESERVED pReserved = \
  671. (PIRDA_PROTOCOL_RESERVED) NdisPacket->ProtocolReserved;
  672. PIRDA_MSG pMsg = pReserved->pMsg;
  673. PNDIS_BUFFER NdisBuffer;
  674. #if DBG_TIMESTAMP
  675. LARGE_INTEGER li;
  676. #endif
  677. //ASSERT(Status == NDIS_STATUS_SUCCESS);
  678. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: IrdaSendComplete(%p) outstanding %d\n"), NdisPacket,pIrdaLinkCb->SendOutCnt-1));
  679. ConfirmDataRequest(pIrdaLinkCb, pMsg);
  680. #if DBG_TIMESTAMP
  681. KeQueryTickCount(&li);
  682. pReserved->TimeStamp[1] = (int) li.LowPart * KeQueryTimeIncrement();
  683. DEBUGMSG(1, (TEXT("C: %d\n"),
  684. (pReserved->TimeStamp[1] - pReserved->TimeStamp[0])/10000));
  685. #endif
  686. if (NdisPacket)
  687. {
  688. NdisUnchainBufferAtFront(NdisPacket, &NdisBuffer);
  689. while (NdisBuffer)
  690. {
  691. NdisFreeBuffer(NdisBuffer);
  692. NdisUnchainBufferAtFront(NdisPacket, &NdisBuffer);
  693. }
  694. NdisReinitializePacket(NdisPacket);
  695. NdisInterlockedInsertTailList(&pIrdaLinkCb->PacketList,
  696. &pReserved->Linkage,
  697. &pIrdaLinkCb->SpinLock);
  698. }
  699. InterlockedDecrement(&pIrdaLinkCb->SendOutCnt);
  700. ASSERT(pIrdaLinkCb->SendOutCnt >= 0);
  701. NdisAcquireSpinLock(&pIrdaLinkCb->SpinLock);
  702. if (pIrdaLinkCb->SendOutCnt == 0 &&
  703. pIrdaLinkCb->pNetPnpEvent)
  704. {
  705. PNET_PNP_EVENT pNetPnpEvent;
  706. ASSERT(pIrdaLinkCb->LowPowerSt == TRUE);
  707. pNetPnpEvent = pIrdaLinkCb->pNetPnpEvent;
  708. pIrdaLinkCb->pNetPnpEvent = NULL;
  709. NdisReleaseSpinLock(&pIrdaLinkCb->SpinLock);
  710. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: Completing set power async\n")));
  711. NdisCompletePnPEvent(
  712. NDIS_STATUS_SUCCESS,
  713. pIrdaLinkCb->NdisBindingHandle,
  714. pNetPnpEvent);
  715. }
  716. else
  717. {
  718. NdisReleaseSpinLock(&pIrdaLinkCb->SpinLock);
  719. }
  720. return;
  721. }
  722. /***************************************************************************
  723. *
  724. * Protocol transfer complete handler
  725. *
  726. */
  727. VOID IrdaTransferDataComplete(
  728. IN NDIS_HANDLE IrdaBindingContext,
  729. IN PNDIS_PACKET Packet,
  730. IN NDIS_STATUS Status,
  731. IN UINT BytesTransferred
  732. )
  733. {
  734. DEBUGMSG(DBG_NDIS, (TEXT("+IrdaTransferDataComplete()\n")));
  735. ASSERT(0);
  736. return;
  737. }
  738. /***************************************************************************
  739. *
  740. * Protocol reset complete handler
  741. *
  742. */
  743. void IrdaResetComplete(
  744. IN NDIS_HANDLE IrdaBindingContext,
  745. IN NDIS_STATUS Status
  746. )
  747. {
  748. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext;
  749. DEBUGMSG(DBG_ERROR, (TEXT("+IrdaResetComplete()\n")));
  750. NdisSetEvent(&pIrdaLinkCb->ResetEvent);
  751. return;
  752. }
  753. /***************************************************************************
  754. *
  755. * Protocol request complete handler
  756. *
  757. */
  758. void IrdaRequestComplete(
  759. IN NDIS_HANDLE IrdaBindingContext,
  760. IN PNDIS_REQUEST NdisRequest,
  761. IN NDIS_STATUS Status
  762. )
  763. {
  764. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext;
  765. PIRDA_REQUEST Request=CONTAINING_RECORD(NdisRequest,IRDA_REQUEST,NdisRequest);
  766. //DEBUGMSG(DBG_NDIS, (TEXT("+IrdaRequestComplete()\n")));
  767. Request->Status = Status;
  768. NdisSetEvent(&Request->Event);
  769. return;
  770. }
  771. /***************************************************************************
  772. *
  773. * Protocol receive handler - This asserts if I don't get all data in the
  774. * lookahead buffer.
  775. *
  776. */
  777. NDIS_STATUS IrdaReceive(
  778. IN NDIS_HANDLE IrdaBindingContext,
  779. IN NDIS_HANDLE MacReceiveContext,
  780. IN PVOID HeaderBuffer,
  781. IN UINT HeaderBufferSize,
  782. IN PVOID LookaheadBuffer,
  783. IN UINT LookaheadBufferSize,
  784. IN UINT PacketSize
  785. )
  786. {
  787. DEBUGMSG(DBG_NDIS, (TEXT("+IrdaReceive()\n")));
  788. DEBUGMSG(DBG_ERROR, (TEXT("ProtocolReceive is not supported by irda\n")));
  789. ASSERT(0);
  790. return NDIS_STATUS_NOT_ACCEPTED;
  791. }
  792. /***************************************************************************
  793. *
  794. * Protocol receive complete handler - what is this for?
  795. *
  796. */
  797. VOID IrdaReceiveComplete(
  798. IN NDIS_HANDLE IrdaBindingContext
  799. )
  800. {
  801. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: IrdaReceiveComplete()\n")));
  802. return;
  803. }
  804. /***************************************************************************
  805. *
  806. * Protocol status handler
  807. *
  808. */
  809. VOID IrdaStatus(
  810. IN NDIS_HANDLE IrdaBindingContext,
  811. IN NDIS_STATUS GeneralStatus,
  812. IN PVOID StatusBuffer,
  813. IN UINT StatusBufferSize
  814. )
  815. {
  816. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext;
  817. if (GeneralStatus == NDIS_STATUS_MEDIA_BUSY)
  818. {
  819. DEBUGMSG(DBG_NDIS, (TEXT("STATUS_MEDIA_BUSY\n")));
  820. pIrdaLinkCb->MediaBusy = TRUE;
  821. }
  822. else
  823. {
  824. DEBUGMSG(DBG_NDIS, (TEXT("Unknown Status indication\n")));
  825. }
  826. return;
  827. }
  828. /***************************************************************************
  829. *
  830. * Protocol status complete handler
  831. *
  832. */
  833. VOID IrdaStatusComplete(
  834. IN NDIS_HANDLE IrdaBindingContext
  835. )
  836. {
  837. DEBUGMSG(DBG_NDIS, (TEXT("IrdaStatusComplete()\n")));
  838. return;
  839. }
  840. /***************************************************************************
  841. *
  842. * RxThread - Hands received frames to Irlap for processing. This is
  843. * the callback of an exec worker thread running at passive level
  844. * which allows us to get a mutex in order to single thread
  845. * events through the stack.
  846. * OR
  847. * This is an actual system thread created a bind time that waits on
  848. * 2 events:
  849. * 1 - EvRxMsgReady, an inbound frame is ready on RxMsgList
  850. * 2 - EvKillRxThread
  851. *
  852. */
  853. VOID
  854. RxThread(void *Arg)
  855. {
  856. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) Arg;
  857. PIRDA_MSG pMsg;
  858. BOOLEAN Done = FALSE;
  859. #ifdef IRDA_RX_SYSTEM_THREAD
  860. NTSTATUS Status;
  861. PKEVENT EventList[2] = {&pIrdaLinkCb->EvRxMsgReady,
  862. &pIrdaLinkCb->EvKillRxThread};
  863. BOOLEAN DataIndication;
  864. KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
  865. #endif
  866. while (!Done)
  867. {
  868. pMsg = (PIRDA_MSG) NdisInterlockedRemoveHeadList(
  869. &pIrdaLinkCb->RxMsgList,
  870. &pIrdaLinkCb->SpinLock);
  871. while (pMsg)
  872. {
  873. if (pMsg->Prim == MAC_DATA_IND)
  874. {
  875. DataIndication = TRUE;
  876. pMsg->IRDA_MSG_RefCnt = 1;
  877. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: Indicate packet %p\n"), pMsg->DataContext));
  878. }
  879. else
  880. {
  881. DataIndication = FALSE;
  882. }
  883. LOCK_LINK(pIrdaLinkCb);
  884. IrlapUp(pIrdaLinkCb->IrlapContext, pMsg);
  885. UNLOCK_LINK(pIrdaLinkCb);
  886. if (DataIndication)
  887. {
  888. //
  889. // no protection needed for refcount cuz this
  890. // is the only thread that operates on it
  891. //
  892. ASSERT(pMsg->IRDA_MSG_RefCnt);
  893. pMsg->IRDA_MSG_RefCnt -= 1;
  894. if (pMsg->IRDA_MSG_RefCnt && pMsg->DataContext)
  895. {
  896. CopyCnt++;
  897. // Irlap had to hold the data because of missing
  898. // frames. Some miniports can't handle the stack
  899. // owning the frames for any length of time.
  900. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: return packet %p\n"), pMsg->DataContext));
  901. NdisReturnPackets(&((PNDIS_PACKET)pMsg->DataContext),
  902. 1);
  903. pMsg->DataContext = NULL;
  904. }
  905. else
  906. {
  907. NoCopyCnt++;
  908. }
  909. if (pMsg->IRDA_MSG_RefCnt == 0)
  910. {
  911. pMsg->Prim = MAC_DATA_RESP;
  912. IrmacDown(pIrdaLinkCb, pMsg);
  913. }
  914. }
  915. pMsg = (PIRDA_MSG) NdisInterlockedRemoveHeadList(
  916. &pIrdaLinkCb->RxMsgList, &pIrdaLinkCb->SpinLock);
  917. }
  918. #ifdef IRDA_RX_SYSTEM_THREAD
  919. Status = KeWaitForMultipleObjects(2, EventList, WaitAny,
  920. Executive, KernelMode,
  921. FALSE, NULL, NULL);
  922. if (Status != 0)
  923. {
  924. if (Status != 1)
  925. {
  926. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: KeWaitForMultObj return %X\n"), Status));
  927. }
  928. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: Terminating RxThread\n")));
  929. PsTerminateSystemThread(STATUS_SUCCESS);
  930. }
  931. #else
  932. Done = TRUE;
  933. #endif
  934. }
  935. }
  936. /***************************************************************************
  937. *
  938. * Protocol receive packet handler - Called at DPC, put the message on
  939. * RxList and have Exec worker thread process it at passive level.
  940. *
  941. */
  942. INT
  943. IrdaReceivePacket(
  944. IN NDIS_HANDLE IrdaBindingContext,
  945. IN PNDIS_PACKET Packet)
  946. {
  947. UINT BufCnt, TotalLen, BufLen;
  948. PNDIS_BUFFER pNdisBuf;
  949. PIRDA_MSG pMsg;
  950. UCHAR *pData;
  951. PIRDA_LINK_CB pIrdaLinkCb = IrdaBindingContext;
  952. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: IrdaReceivePacket(%p)\n"), Packet));
  953. if (pIrdaLinkCb->UnbindContext)
  954. {
  955. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: Ignoring received packet, link closing\n")));
  956. return 0;
  957. }
  958. NdisQueryPacket(Packet, NULL, &BufCnt, &pNdisBuf, &TotalLen);
  959. if ((TotalLen < 2) || (TotalLen > (UINT)pIrdaLinkCb->RxMsgDataSize+1)) {
  960. //
  961. // all irda frames need an (A)ddress and (C)ontrol bytes,
  962. //
  963. // They also need to be small enough to fix in buffer at the end of the rx message
  964. // if the protocol needs to hang on to the packet. The buffers are allocated based on
  965. // the max packet size. The protocol only uses the data following the AC bytes so
  966. // we out buffers are actually two bytes bigger than needed. We add on byte onto
  967. // the allowable size since win2k had a bug that would cause it to send 2049 byte
  968. // packets.
  969. //
  970. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: Frame less than two bytes or bigger than the max size %d\n"),TotalLen));
  971. return 0;
  972. }
  973. ASSERT(BufCnt == 1);
  974. NdisQueryBufferSafe(pNdisBuf, &pData, &BufLen, NormalPagePriority);
  975. if (pData == NULL)
  976. {
  977. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: NdisQueryBufferSafe failed\n")));
  978. return 0;
  979. }
  980. pIrdaLinkCb->WaitMinTat = TRUE;
  981. pMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList(
  982. &pIrdaLinkCb->RxMsgFreeList, &pIrdaLinkCb->SpinLock);
  983. if (pMsg == NULL)
  984. {
  985. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: RxMsgFreeList depleted!\n")));
  986. return 0;
  987. }
  988. pIrdaLinkCb->RxMsgFreeListLen--;
  989. pMsg->Prim = MAC_DATA_IND;
  990. pMsg->IRDA_MSG_pRead = pData;
  991. pMsg->IRDA_MSG_pWrite = pData + BufLen;
  992. pMsg->DataContext = Packet;
  993. NdisInterlockedInsertTailList(&pIrdaLinkCb->RxMsgList,
  994. &pMsg->Linkage,
  995. &pIrdaLinkCb->SpinLock);
  996. DBG_FRAME(pIrdaLinkCb,
  997. FALSE, //DBG_RXFRAME,
  998. pMsg->IRDA_MSG_pRead,
  999. (UINT) (pMsg->IRDA_MSG_pWrite - pMsg->IRDA_MSG_pRead),
  1000. (UINT) ((pMsg->IRDA_MSG_pWrite - pMsg->IRDA_MSG_pRead))
  1001. - IRLAP_HEADER_LEN);
  1002. #ifdef IRDA_RX_SYSTEM_THREAD
  1003. KeSetEvent(&pIrdaLinkCb->EvRxMsgReady, 0, FALSE);
  1004. #else
  1005. IrdaEventSchedule(&pIrdaLinkCb->EvRxMsgReady, pIrdaLinkCb);
  1006. #endif
  1007. return 1; // Ownership reference count of packet
  1008. }
  1009. /***************************************************************************
  1010. *
  1011. * Delete all control blocks for a given link
  1012. *
  1013. */
  1014. VOID
  1015. DeleteIrdaLink(PVOID Arg)
  1016. {
  1017. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) Arg;
  1018. int i;
  1019. PIRDA_MSG pMsg;
  1020. DEBUGMSG(DBG_IRMAC,("IRNDIS: Delete instance %p\n", pIrdaLinkCb));
  1021. NdisFreeBufferPool(pIrdaLinkCb->BufferPool);
  1022. pIrdaLinkCb->BufferPool=NULL;
  1023. for (i = 0; i < IRDA_NDIS_PACKET_POOL_SIZE; i++)
  1024. {
  1025. PIRDA_PROTOCOL_RESERVED pReserved;
  1026. PNDIS_PACKET NdisPacket;
  1027. pReserved = (PIRDA_PROTOCOL_RESERVED) NdisInterlockedRemoveHeadList(
  1028. &pIrdaLinkCb->PacketList, &pIrdaLinkCb->SpinLock);
  1029. if (pReserved == NULL)
  1030. {
  1031. DEBUGMSG(DBG_ERROR, (TEXT("Not all NdisPackets were on list when deleting\n")));
  1032. ASSERT(0);
  1033. break;
  1034. }
  1035. NdisPacket = CONTAINING_RECORD(pReserved, NDIS_PACKET, ProtocolReserved);
  1036. NdisFreePacket(NdisPacket);
  1037. }
  1038. NdisFreePacketPool(pIrdaLinkCb->PacketPool);
  1039. pIrdaLinkCb->PacketPool=NULL;
  1040. pMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList(
  1041. &pIrdaLinkCb->TxMsgFreeList, &pIrdaLinkCb->SpinLock);
  1042. while (pMsg != NULL)
  1043. {
  1044. NdisFreeMemory(pMsg, sizeof(IRDA_MSG) + IRDA_MSG_DATA_SIZE, 0);
  1045. pMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList(
  1046. &pIrdaLinkCb->TxMsgFreeList, &pIrdaLinkCb->SpinLock);
  1047. }
  1048. pMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList(
  1049. &pIrdaLinkCb->RxMsgFreeList, &pIrdaLinkCb->SpinLock);
  1050. while (pMsg != NULL)
  1051. {
  1052. NdisFreeMemory(pMsg, sizeof(IRDA_MSG), 0);
  1053. pMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList(
  1054. &pIrdaLinkCb->RxMsgFreeList, &pIrdaLinkCb->SpinLock);
  1055. }
  1056. IrlapDeleteInstance(pIrdaLinkCb->IrlapContext);
  1057. pIrdaLinkCb->IrlapContext=NULL;
  1058. IrlmpDeleteInstance(pIrdaLinkCb->IrlmpContext);
  1059. pIrdaLinkCb->IrlmpContext=NULL;
  1060. NdisFreeSpinLock(&pIrdaLinkCb->SpinLock);
  1061. NdisFreeMemory(pIrdaLinkCb, sizeof(IRDA_LINK_CB), 0);
  1062. }
  1063. /***************************************************************************
  1064. *
  1065. * Initialize local Qos with info from adapters register and globals
  1066. * initialized at driver entry time (from protocol's registery)
  1067. *
  1068. */
  1069. VOID InitializeLocalQos(
  1070. IN OUT IRDA_QOS_PARMS *pQos,
  1071. IN PNDIS_STRING ConfigPath)
  1072. {
  1073. NDIS_HANDLE ConfigHandle;
  1074. NDIS_STRING DataSizeStr = NDIS_STRING_CONST("DATASIZE");
  1075. NDIS_STRING WindowSizeStr = NDIS_STRING_CONST("WINDOWSIZE");
  1076. NDIS_STRING MaxTatStr = NDIS_STRING_CONST("MAXTURNTIME");
  1077. NDIS_STRING BofsStr = NDIS_STRING_CONST("BOFS");
  1078. PNDIS_CONFIGURATION_PARAMETER ParmVal;
  1079. NDIS_STATUS Status;
  1080. PAGED_CODE();
  1081. pQos->bfDisconnectTime = DisconnectTime;
  1082. pQos->bfDataSize = IRLAP_DEFAULT_DATASIZE;
  1083. pQos->bfWindowSize = IRLAP_DEFAULT_WINDOWSIZE;
  1084. pQos->bfMaxTurnTime = IRLAP_DEFAULT_MAXTAT;
  1085. pQos->bfBofs = BOFS_0;
  1086. NdisOpenProtocolConfiguration(&Status,
  1087. &ConfigHandle,
  1088. ConfigPath);
  1089. if (Status == NDIS_STATUS_SUCCESS)
  1090. {
  1091. NdisReadConfiguration(&Status,
  1092. &ParmVal,
  1093. ConfigHandle,
  1094. &DataSizeStr,
  1095. NdisParameterInteger);
  1096. if (Status == NDIS_STATUS_SUCCESS)
  1097. pQos->bfDataSize = ParmVal->ParameterData.IntegerData;
  1098. NdisReadConfiguration(&Status,
  1099. &ParmVal,
  1100. ConfigHandle,
  1101. &WindowSizeStr,
  1102. NdisParameterInteger);
  1103. if (Status == NDIS_STATUS_SUCCESS)
  1104. pQos->bfWindowSize = ParmVal->ParameterData.IntegerData;
  1105. NdisReadConfiguration(&Status,
  1106. &ParmVal,
  1107. ConfigHandle,
  1108. &MaxTatStr,
  1109. NdisParameterInteger);
  1110. if (Status == NDIS_STATUS_SUCCESS)
  1111. pQos->bfMaxTurnTime = ParmVal->ParameterData.IntegerData;
  1112. NdisReadConfiguration(&Status,
  1113. &ParmVal,
  1114. ConfigHandle,
  1115. &BofsStr,
  1116. NdisParameterInteger);
  1117. if (Status == NDIS_STATUS_SUCCESS)
  1118. pQos->bfBofs = ParmVal->ParameterData.IntegerData;
  1119. NdisCloseConfiguration(ConfigHandle);
  1120. }
  1121. DEBUGMSG(DBG_NDIS, (TEXT("DataSize %x, WindowSize %x, MaxTat %x, Bofs=%x\n"),
  1122. pQos->bfDataSize, pQos->bfWindowSize,
  1123. pQos->bfMaxTurnTime,pQos->bfBofs));
  1124. }
  1125. /***************************************************************************
  1126. *
  1127. * Protocol bind adapter handler
  1128. *
  1129. */
  1130. VOID IrdaBindAdapter(
  1131. OUT PNDIS_STATUS pStatus,
  1132. IN NDIS_HANDLE BindContext,
  1133. IN PNDIS_STRING AdapterName,
  1134. IN PVOID SystemSpecific1,
  1135. IN PVOID SystemSpecific2
  1136. )
  1137. {
  1138. NDIS_STATUS OpenErrorStatus;
  1139. NDIS_MEDIUM MediumArray[] = {NdisMediumIrda};
  1140. UINT SelectedMediumIndex;
  1141. PIRDA_LINK_CB pIrdaLinkCb;
  1142. UINT UintArray[16];
  1143. UINT UintArrayCnt;
  1144. IRDA_MSG *pMsg;
  1145. int i, WinSize;
  1146. IRDA_QOS_PARMS LocalQos;
  1147. UCHAR DscvInfoBuf[64];
  1148. int DscvInfoLen;
  1149. ULONG Val, Mask;
  1150. NDIS_STATUS CloseStatus;
  1151. ULONG BytesToCopy;
  1152. #ifdef IRDA_RX_SYSTEM_THREAD
  1153. HANDLE hSysThread;
  1154. #endif
  1155. DEBUGMSG(DBG_IRMAC, (TEXT("IRNDIS: IrdaBindAdapter() \"%ws\"\n"), AdapterName->Buffer));
  1156. NdisAllocateMemoryWithTag((PVOID *)&pIrdaLinkCb,
  1157. sizeof(IRDA_LINK_CB),
  1158. MT_IRNDIS_LINKCB);
  1159. if (!pIrdaLinkCb)
  1160. {
  1161. *pStatus = STATUS_INSUFFICIENT_RESOURCES;
  1162. goto exit10;
  1163. }
  1164. NdisZeroMemory(pIrdaLinkCb, sizeof(IRDA_LINK_CB));
  1165. ReferenceInit(&pIrdaLinkCb->RefCnt, pIrdaLinkCb, DeleteIrdaLink);
  1166. REFADD(&pIrdaLinkCb->RefCnt, 'DNIB');
  1167. pIrdaLinkCb->UnbindContext = NULL;
  1168. pIrdaLinkCb->WaitMinTat = FALSE;
  1169. pIrdaLinkCb->PnpContext = SystemSpecific2;
  1170. NdisInitializeEvent(&pIrdaLinkCb->OpenCloseEvent);
  1171. NdisResetEvent(&pIrdaLinkCb->OpenCloseEvent);
  1172. NdisInitializeEvent(&pIrdaLinkCb->ResetEvent);
  1173. NdisResetEvent(&pIrdaLinkCb->ResetEvent);
  1174. NdisAllocateSpinLock(&pIrdaLinkCb->SpinLock);
  1175. INIT_LINK_LOCK(pIrdaLinkCb);
  1176. NdisInitializeListHead(&pIrdaLinkCb->TxMsgFreeList);
  1177. NdisInitializeListHead(&pIrdaLinkCb->RxMsgFreeList);
  1178. NdisInitializeListHead(&pIrdaLinkCb->RxMsgList);
  1179. #ifdef IRDA_RX_SYSTEM_THREAD
  1180. KeInitializeEvent(&pIrdaLinkCb->EvRxMsgReady, SynchronizationEvent, FALSE);
  1181. KeInitializeEvent(&pIrdaLinkCb->EvKillRxThread, SynchronizationEvent, FALSE);
  1182. #else
  1183. IrdaEventInitialize(&pIrdaLinkCb->EvRxMsgReady, RxThread);
  1184. #endif
  1185. #if DBG
  1186. pIrdaLinkCb->MediaSenseTimer.pName = "MediaSense";
  1187. #endif
  1188. IrdaTimerInitialize(&pIrdaLinkCb->MediaSenseTimer,
  1189. MediaSenseExp,
  1190. 0,
  1191. pIrdaLinkCb,
  1192. pIrdaLinkCb);
  1193. NdisAllocateBufferPool(pStatus,
  1194. &pIrdaLinkCb->BufferPool,
  1195. IRDA_NDIS_BUFFER_POOL_SIZE);
  1196. if (*pStatus != NDIS_STATUS_SUCCESS)
  1197. {
  1198. DEBUGMSG(DBG_ERROR, (TEXT("NdisAllocateBufferPool failed\n")));
  1199. goto error10;
  1200. }
  1201. NdisAllocatePacketPool(pStatus,
  1202. &pIrdaLinkCb->PacketPool,
  1203. IRDA_NDIS_PACKET_POOL_SIZE,
  1204. sizeof(IRDA_PROTOCOL_RESERVED)-1 + \
  1205. sizeof(NDIS_IRDA_PACKET_INFO));
  1206. if (*pStatus != NDIS_STATUS_SUCCESS)
  1207. {
  1208. DEBUGMSG(DBG_ERROR, (TEXT("NdisAllocatePacketPool failed\n")));
  1209. goto error20;
  1210. }
  1211. NdisInitializeListHead(&pIrdaLinkCb->PacketList);
  1212. for (i = 0; i < IRDA_NDIS_PACKET_POOL_SIZE; i++)
  1213. {
  1214. PIRDA_PROTOCOL_RESERVED pReserved;
  1215. PNDIS_PACKET NdisPacket;
  1216. NdisAllocatePacket(pStatus, &NdisPacket, pIrdaLinkCb->PacketPool);
  1217. if (*pStatus != NDIS_STATUS_SUCCESS)
  1218. {
  1219. ASSERT(0);
  1220. goto error30;
  1221. }
  1222. pReserved =
  1223. (PIRDA_PROTOCOL_RESERVED)(NdisPacket->ProtocolReserved);
  1224. NdisInterlockedInsertTailList(&pIrdaLinkCb->PacketList,
  1225. &pReserved->Linkage,
  1226. &pIrdaLinkCb->SpinLock);
  1227. }
  1228. // Allocate a list of Irda messages w/ data for internally
  1229. // generated LAP messages
  1230. pIrdaLinkCb->TxMsgFreeListLen = 0;
  1231. for (i = 0; i < IRDA_MSG_LIST_LEN; i++)
  1232. {
  1233. NdisAllocateMemoryWithTag(&pMsg, sizeof(IRDA_MSG) + IRDA_MSG_DATA_SIZE,
  1234. MT_IRNDIS_TX_IMSG);
  1235. if (pMsg == NULL)
  1236. {
  1237. *pStatus = STATUS_INSUFFICIENT_RESOURCES;
  1238. goto error40;
  1239. }
  1240. NdisInterlockedInsertTailList(&pIrdaLinkCb->TxMsgFreeList,
  1241. &pMsg->Linkage,
  1242. &pIrdaLinkCb->SpinLock);
  1243. pIrdaLinkCb->TxMsgFreeListLen++;
  1244. }
  1245. // Build the discovery info
  1246. Val = HintCharSet;
  1247. DscvInfoLen = 0;
  1248. for (i = 0, Mask = 0xFF000000; i < 4; i++, Mask >>= 8)
  1249. {
  1250. if (Mask & Val || DscvInfoLen > 0)
  1251. {
  1252. DscvInfoBuf[DscvInfoLen++] = (UCHAR)
  1253. ((Mask & Val) >> (8 * (3-i)));
  1254. }
  1255. }
  1256. BytesToCopy= sizeof(DscvInfoBuf)-DscvInfoLen < NickNameLen ?
  1257. sizeof(DscvInfoBuf)-DscvInfoLen : NickNameLen;
  1258. RtlCopyMemory(DscvInfoBuf+DscvInfoLen, NickName, BytesToCopy);
  1259. DscvInfoLen += BytesToCopy;
  1260. NdisOpenAdapter(
  1261. pStatus,
  1262. &OpenErrorStatus,
  1263. &pIrdaLinkCb->NdisBindingHandle,
  1264. &SelectedMediumIndex,
  1265. MediumArray,
  1266. 1,
  1267. NdisIrdaHandle,
  1268. pIrdaLinkCb,
  1269. AdapterName,
  1270. 0,
  1271. NULL);
  1272. DEBUGMSG(DBG_NDIS, (TEXT("NdisOpenAdapter(%p), status %x\n"),
  1273. pIrdaLinkCb->NdisBindingHandle, *pStatus));
  1274. if (*pStatus == NDIS_STATUS_PENDING)
  1275. {
  1276. NdisWaitEvent(&pIrdaLinkCb->OpenCloseEvent, 0);
  1277. *pStatus = pIrdaLinkCb->OpenCloseStatus;
  1278. }
  1279. if (*pStatus != NDIS_STATUS_SUCCESS)
  1280. {
  1281. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: Failed %X\n"), *pStatus));
  1282. goto error40;
  1283. }
  1284. InitializeLocalQos(&LocalQos, (PNDIS_STRING) SystemSpecific1);
  1285. //
  1286. // Query adapters capabilities and store in LocalQos
  1287. //
  1288. //
  1289. // query the adpater for the spuuported speeds
  1290. //
  1291. UintArrayCnt = sizeof(UintArray)/sizeof(UINT);
  1292. *pStatus = IrdaQueryOid(pIrdaLinkCb,
  1293. OID_IRDA_SUPPORTED_SPEEDS,
  1294. UintArray, &UintArrayCnt);
  1295. if (*pStatus != NDIS_STATUS_SUCCESS)
  1296. {
  1297. DEBUGMSG(DBG_ERROR,
  1298. (TEXT("Query IRDA_SUPPORTED_SPEEDS failed %x\n"),
  1299. *pStatus));
  1300. goto error50;
  1301. }
  1302. OidToLapQos(vBaudTable,
  1303. UintArray,
  1304. UintArrayCnt,
  1305. &LocalQos.bfBaud,
  1306. FALSE);
  1307. //
  1308. // query the adapter for min turn araound time
  1309. //
  1310. UintArrayCnt = sizeof(UintArray)/sizeof(UINT);
  1311. *pStatus = IrdaQueryOid(pIrdaLinkCb,
  1312. OID_IRDA_TURNAROUND_TIME,
  1313. UintArray, &UintArrayCnt);
  1314. if (*pStatus != NDIS_STATUS_SUCCESS)
  1315. {
  1316. DEBUGMSG(DBG_ERROR,
  1317. (TEXT("Query IRDA_IRDA_TURNARROUND_TIME failed %x\n"),
  1318. *pStatus));
  1319. goto error50;
  1320. }
  1321. OidToLapQos(vMinTATTable,
  1322. UintArray,
  1323. UintArrayCnt,
  1324. &LocalQos.bfMinTurnTime,
  1325. FALSE);
  1326. //
  1327. // query the adapter for max receive window size
  1328. //
  1329. UintArrayCnt = sizeof(UintArray)/sizeof(UINT);
  1330. *pStatus = IrdaQueryOid(pIrdaLinkCb,
  1331. OID_IRDA_MAX_RECEIVE_WINDOW_SIZE,
  1332. UintArray, &UintArrayCnt);
  1333. if (*pStatus != NDIS_STATUS_SUCCESS)
  1334. {
  1335. // Not fatal
  1336. DEBUGMSG(DBG_WARN,
  1337. (TEXT("Query IRDA_MAX_RECEIVE_WINDOW_SIZE failed %x\n"),
  1338. *pStatus));
  1339. }
  1340. else
  1341. {
  1342. OidToLapQos(vWinSizeTable,
  1343. UintArray,
  1344. UintArrayCnt,
  1345. &LocalQos.bfWindowSize,
  1346. TRUE);
  1347. }
  1348. //
  1349. // query the adapter for extra bofs
  1350. //
  1351. UintArrayCnt = sizeof(UintArray)/sizeof(UINT);
  1352. *pStatus = IrdaQueryOid(pIrdaLinkCb,
  1353. OID_IRDA_EXTRA_RCV_BOFS,
  1354. UintArray, &UintArrayCnt);
  1355. if (*pStatus != NDIS_STATUS_SUCCESS)
  1356. {
  1357. // Not fatal
  1358. DEBUGMSG(DBG_WARN,
  1359. (TEXT("Query OID_IRDA_EXTRA_RCV_BOFS failed %x\n"),
  1360. *pStatus));
  1361. }
  1362. else
  1363. {
  1364. OidToLapQos(vBOFSTable,
  1365. UintArray,
  1366. UintArrayCnt,
  1367. &LocalQos.bfBofs,
  1368. FALSE
  1369. );
  1370. }
  1371. if (MaxWindow)
  1372. {
  1373. LocalQos.bfWindowSize &= MaxWindow;
  1374. }
  1375. // Get the window size and data size to determine the number
  1376. // and size of Irda messages to allocate for receiving frames
  1377. WinSize = IrlapGetQosParmVal(vWinSizeTable,
  1378. LocalQos.bfWindowSize,
  1379. NULL);
  1380. pIrdaLinkCb->RxMsgDataSize = IrlapGetQosParmVal(vDataSizeTable,
  1381. LocalQos.bfDataSize,
  1382. NULL) + IRLAP_HEADER_LEN;
  1383. pIrdaLinkCb->RxMsgFreeListLen = 0;
  1384. for (i = 0; i < WinSize + 1; i++)
  1385. {
  1386. // Allocate room for data in case we get indicated data
  1387. // that must be copied (IrdaReceive vs. IrdaReceivePacket)
  1388. // LATER NOTE: We don't support IrdaReceive now to save locked mem
  1389. NdisAllocateMemoryWithTag(&pMsg, sizeof(IRDA_MSG) +
  1390. pIrdaLinkCb->RxMsgDataSize,
  1391. MT_IRNDIS_RX_IMSG);
  1392. if (pMsg == NULL)
  1393. {
  1394. *pStatus = STATUS_INSUFFICIENT_RESOURCES;
  1395. goto error50;
  1396. }
  1397. NdisInterlockedInsertTailList(&pIrdaLinkCb->RxMsgFreeList,
  1398. &pMsg->Linkage,
  1399. &pIrdaLinkCb->SpinLock);
  1400. pIrdaLinkCb->RxMsgFreeListLen++;
  1401. }
  1402. // Create an instance of IrLAP
  1403. IrlapOpenLink(pStatus,
  1404. pIrdaLinkCb,
  1405. &LocalQos,
  1406. DscvInfoBuf,
  1407. DscvInfoLen,
  1408. Slots,
  1409. NickName,
  1410. NickNameLen,
  1411. (UCHAR)(HintCharSet & 0xFF));
  1412. if (*pStatus != STATUS_SUCCESS)
  1413. {
  1414. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: IrlapOpenLink failed %X\n"), *pStatus));
  1415. goto error50;
  1416. }
  1417. #ifdef IRDA_RX_SYSTEM_THREAD
  1418. *pStatus = (NDIS_STATUS) PsCreateSystemThread(
  1419. &pIrdaLinkCb->hRxThread,
  1420. (ACCESS_MASK) 0L,
  1421. NULL,
  1422. NULL,
  1423. NULL,
  1424. RxThread,
  1425. pIrdaLinkCb);
  1426. if (*pStatus != STATUS_SUCCESS)
  1427. {
  1428. DEBUGMSG(DBG_ERROR, (TEXT("IRNDIS: failed create system thread\n")));
  1429. goto error60;
  1430. }
  1431. #endif
  1432. goto exit10;
  1433. error60:
  1434. LOCK_LINK(pIrdaLinkCb);
  1435. IrlmpCloseLink(pIrdaLinkCb);
  1436. UNLOCK_LINK(pIrdaLinkCb);
  1437. goto exit10;
  1438. error50:
  1439. NdisCloseAdapter(&CloseStatus, pIrdaLinkCb->NdisBindingHandle);
  1440. if (CloseStatus == NDIS_STATUS_PENDING)
  1441. {
  1442. NdisWaitEvent(&pIrdaLinkCb->OpenCloseEvent, 0);
  1443. DEBUGMSG(DBG_NDIS, ("IRNDIS: Close wait complete\n"));
  1444. }
  1445. error40:
  1446. pMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList(
  1447. &pIrdaLinkCb->TxMsgFreeList, &pIrdaLinkCb->SpinLock);
  1448. while (pMsg != NULL)
  1449. {
  1450. NdisFreeMemory(pMsg, sizeof(IRDA_MSG) + IRDA_MSG_DATA_SIZE, 0);
  1451. pMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList(
  1452. &pIrdaLinkCb->TxMsgFreeList, &pIrdaLinkCb->SpinLock);
  1453. }
  1454. pMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList(
  1455. &pIrdaLinkCb->RxMsgFreeList, &pIrdaLinkCb->SpinLock);
  1456. while (pMsg != NULL)
  1457. {
  1458. NdisFreeMemory(pMsg, sizeof(IRDA_MSG), 0);
  1459. pMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList(
  1460. &pIrdaLinkCb->RxMsgFreeList, &pIrdaLinkCb->SpinLock);
  1461. }
  1462. error30:
  1463. for (i = 0; i < IRDA_NDIS_PACKET_POOL_SIZE; i++)
  1464. {
  1465. PIRDA_PROTOCOL_RESERVED pReserved;
  1466. PNDIS_PACKET NdisPacket;
  1467. pReserved = (PIRDA_PROTOCOL_RESERVED) NdisInterlockedRemoveHeadList(
  1468. &pIrdaLinkCb->PacketList, &pIrdaLinkCb->SpinLock);
  1469. if (pReserved == NULL)
  1470. {
  1471. DEBUGMSG(DBG_ERROR, (TEXT("Not all NdisPackets were on list when deleting\n")));
  1472. ASSERT(0);
  1473. break;;
  1474. }
  1475. NdisPacket = CONTAINING_RECORD(pReserved, NDIS_PACKET, ProtocolReserved);
  1476. NdisFreePacket(NdisPacket);
  1477. }
  1478. NdisFreePacketPool(pIrdaLinkCb->PacketPool);
  1479. error20:
  1480. NdisFreeBufferPool(pIrdaLinkCb->BufferPool);
  1481. error10:
  1482. NdisFreeMemory(pIrdaLinkCb, sizeof(IRDA_LINK_CB), 0);
  1483. exit10:
  1484. DEBUGMSG(DBG_NDIS, (TEXT("IRNDIS: -IrdaBindAdapter() status %x\n"),
  1485. *pStatus));
  1486. return;
  1487. }
  1488. /***************************************************************************
  1489. *
  1490. * Protocol unbind adapter handler
  1491. *
  1492. */
  1493. VOID IrdaUnbindAdapter(
  1494. OUT PNDIS_STATUS pStatus,
  1495. IN NDIS_HANDLE IrdaBindingContext,
  1496. IN NDIS_HANDLE UnbindContext
  1497. )
  1498. {
  1499. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext;
  1500. DEBUGMSG(DBG_IRMAC, (TEXT("+IrdaUnbindAdapter()\n")));
  1501. pIrdaLinkCb->UnbindContext = UnbindContext;
  1502. #ifdef IRDA_RX_SYSTEM_THREAD
  1503. KeSetEvent(&pIrdaLinkCb->EvKillRxThread, 0, FALSE);
  1504. #endif
  1505. LOCK_LINK(pIrdaLinkCb);
  1506. IrlmpCloseLink(pIrdaLinkCb);
  1507. UNLOCK_LINK(pIrdaLinkCb);
  1508. *pStatus = NDIS_STATUS_PENDING;
  1509. DEBUGMSG(DBG_IRMAC, (TEXT("-IrdaUnbindAdapter() Status %x\n"),
  1510. *pStatus));
  1511. return;
  1512. }
  1513. NDIS_STATUS
  1514. IrdaPnpEvent(
  1515. IN NDIS_HANDLE IrdaBindingContext,
  1516. IN PNET_PNP_EVENT pNetPnpEvent
  1517. )
  1518. {
  1519. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext;
  1520. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1521. DEBUGMSG(DBG_IRMAC, (TEXT("IRNDIS: PnpEvent:%p, NetEvent:%d Buffer:%p(%d)\n"),
  1522. pNetPnpEvent,
  1523. pNetPnpEvent->NetEvent,
  1524. pNetPnpEvent->Buffer,
  1525. pNetPnpEvent->BufferLength));
  1526. switch (pNetPnpEvent->NetEvent)
  1527. {
  1528. case NetEventQueryPower:
  1529. break;
  1530. case NetEventSetPower:
  1531. {
  1532. PNET_DEVICE_POWER_STATE pPowerState = pNetPnpEvent->Buffer;
  1533. ASSERT(pPowerState);
  1534. if (*pPowerState == NetDeviceStateD0)
  1535. {
  1536. DEBUGMSG(DBG_IRMAC, (TEXT("IRNDIS: NetEventSetPower, full power state\n")));
  1537. pIrdaLinkCb->LowPowerSt = FALSE;
  1538. }
  1539. else
  1540. {
  1541. NDIS_STATUS ResetStatus;
  1542. DEBUGMSG(DBG_IRMAC, (TEXT("IRNDIS: NetEventSetPower, low power state\n")));
  1543. pIrdaLinkCb->LowPowerSt = TRUE;
  1544. if (pIrdaLinkCb->SendOutCnt > 0) {
  1545. NdisResetEvent(&pIrdaLinkCb->ResetEvent);
  1546. NdisReset(
  1547. &ResetStatus,
  1548. pIrdaLinkCb->NdisBindingHandle
  1549. );
  1550. if (ResetStatus == NDIS_STATUS_PENDING) {
  1551. NdisWaitEvent(&pIrdaLinkCb->ResetEvent,0);
  1552. }
  1553. }
  1554. NdisAcquireSpinLock(&pIrdaLinkCb->SpinLock);
  1555. if (pIrdaLinkCb->SendOutCnt)
  1556. {
  1557. pIrdaLinkCb->pNetPnpEvent = pNetPnpEvent;
  1558. Status = NDIS_STATUS_PENDING;
  1559. }
  1560. NdisReleaseSpinLock(&pIrdaLinkCb->SpinLock);
  1561. }
  1562. }
  1563. }
  1564. return Status;
  1565. }
  1566. /***************************************************************************
  1567. *
  1568. * IrdaInitialize - register Irda with Ndis, get Irlap parms from registry
  1569. *
  1570. */
  1571. NTSTATUS IrdaInitialize(
  1572. PNDIS_STRING ProtocolName,
  1573. PUNICODE_STRING RegistryPath,
  1574. PUINT pLazyDscvInterval)
  1575. {
  1576. NDIS_STATUS Status;
  1577. NDIS_PROTOCOL_CHARACTERISTICS pc;
  1578. OBJECT_ATTRIBUTES ObjectAttribs;
  1579. HANDLE KeyHandle;
  1580. UNICODE_STRING ValStr;
  1581. PKEY_VALUE_FULL_INFORMATION FullInfo;
  1582. ULONG Result;
  1583. UCHAR Buf[WORK_BUF_SIZE];
  1584. WCHAR StrBuf[WORK_BUF_SIZE];
  1585. UNICODE_STRING Path;
  1586. ULONG i, Multiplier;
  1587. ULONG PagingFlags = 0;
  1588. DEBUGMSG(DBG_NDIS,(TEXT("+IrdaInitialize()\n")));
  1589. // Get protocol configuration from registry
  1590. Path.Buffer = StrBuf;
  1591. Path.MaximumLength = WORK_BUF_SIZE;
  1592. Path.Length = 0;
  1593. RtlAppendUnicodeStringToString(&Path, RegistryPath);
  1594. RtlAppendUnicodeToString(&Path, L"\\Parameters");
  1595. InitializeObjectAttributes(&ObjectAttribs,
  1596. &Path,
  1597. OBJ_CASE_INSENSITIVE,
  1598. NULL,
  1599. NULL);
  1600. Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttribs);
  1601. Slots = IRLAP_DEFAULT_SLOTS;
  1602. HintCharSet = IRLAP_DEFAULT_HINTCHARSET;
  1603. DisconnectTime = IRLAP_DEFAULT_DISCONNECTTIME;
  1604. *pLazyDscvInterval = 0;
  1605. if (Status == STATUS_SUCCESS)
  1606. {
  1607. RtlInitUnicodeString(&ValStr, L"PagingFlags");
  1608. FullInfo = (PKEY_VALUE_FULL_INFORMATION) Buf;
  1609. Status = ZwQueryValueKey(KeyHandle,
  1610. &ValStr,
  1611. KeyValueFullInformation,
  1612. FullInfo,
  1613. WORK_BUF_SIZE,
  1614. &Result);
  1615. if (Status == STATUS_SUCCESS && FullInfo->Type == REG_DWORD)
  1616. {
  1617. PagingFlags = *((ULONG UNALIGNED *) ((PCHAR)FullInfo +
  1618. FullInfo->DataOffset));
  1619. DEBUGMSG(DBG_IRMAC, (TEXT("IRDA: Registry PagingFlags %X\n"), PagingFlags));
  1620. }
  1621. RtlInitUnicodeString(&ValStr, L"DiscoveryRate");
  1622. FullInfo = (PKEY_VALUE_FULL_INFORMATION) Buf;
  1623. Status = ZwQueryValueKey(KeyHandle,
  1624. &ValStr,
  1625. KeyValueFullInformation,
  1626. FullInfo,
  1627. WORK_BUF_SIZE,
  1628. &Result);
  1629. if (Status == STATUS_SUCCESS && FullInfo->Type == REG_DWORD)
  1630. {
  1631. *pLazyDscvInterval = *((ULONG UNALIGNED *) ((PCHAR)FullInfo +
  1632. FullInfo->DataOffset));
  1633. DEBUGMSG(DBG_IRMAC, (TEXT("IRDA: Registry LasyDscvInterval %d\n"), *pLazyDscvInterval));
  1634. }
  1635. RtlInitUnicodeString(&ValStr, L"Slots");
  1636. FullInfo = (PKEY_VALUE_FULL_INFORMATION) Buf;
  1637. Status = ZwQueryValueKey(KeyHandle,
  1638. &ValStr,
  1639. KeyValueFullInformation,
  1640. FullInfo,
  1641. WORK_BUF_SIZE,
  1642. &Result);
  1643. if (Status == STATUS_SUCCESS && FullInfo->Type == REG_DWORD)
  1644. {
  1645. Slots = *((ULONG UNALIGNED *) ((PCHAR)FullInfo +
  1646. FullInfo->DataOffset));
  1647. DEBUGMSG(DBG_IRMAC, (TEXT("IRDA: Registry slots %d\n"), Slots));
  1648. }
  1649. RtlInitUnicodeString(&ValStr, L"HINTCHARSET");
  1650. FullInfo = (PKEY_VALUE_FULL_INFORMATION) Buf;
  1651. Status = ZwQueryValueKey(KeyHandle,
  1652. &ValStr,
  1653. KeyValueFullInformation,
  1654. FullInfo,
  1655. WORK_BUF_SIZE,
  1656. &Result);
  1657. if (Status == STATUS_SUCCESS && FullInfo->Type == REG_DWORD)
  1658. {
  1659. HintCharSet = *((ULONG UNALIGNED *) ((PCHAR)FullInfo +
  1660. FullInfo->DataOffset));
  1661. DEBUGMSG(DBG_IRMAC, (TEXT("IRDA: Registry HintCharSet %X\n"), HintCharSet));
  1662. }
  1663. RtlInitUnicodeString(&ValStr, L"DISCONNECTTIME");
  1664. FullInfo = (PKEY_VALUE_FULL_INFORMATION) Buf;
  1665. Status = ZwQueryValueKey(KeyHandle,
  1666. &ValStr,
  1667. KeyValueFullInformation,
  1668. FullInfo,
  1669. WORK_BUF_SIZE,
  1670. &Result);
  1671. if (Status == STATUS_SUCCESS && FullInfo->Type == REG_DWORD)
  1672. {
  1673. DisconnectTime = *((ULONG UNALIGNED *) ((PCHAR)FullInfo +
  1674. FullInfo->DataOffset));
  1675. DEBUGMSG(DBG_IRMAC, (TEXT("IRDA: Registry DisconnectTime %X\n"), DisconnectTime));
  1676. }
  1677. RtlInitUnicodeString(&ValStr, L"WindowSize");
  1678. FullInfo = (PKEY_VALUE_FULL_INFORMATION) Buf;
  1679. Status = ZwQueryValueKey(KeyHandle,
  1680. &ValStr,
  1681. KeyValueFullInformation,
  1682. FullInfo,
  1683. WORK_BUF_SIZE,
  1684. &Result);
  1685. if (Status == STATUS_SUCCESS && FullInfo->Type == REG_DWORD)
  1686. {
  1687. MaxWindow = *((ULONG UNALIGNED *) ((PCHAR)FullInfo +
  1688. FullInfo->DataOffset));
  1689. DEBUGMSG(DBG_IRMAC, (TEXT("IRDA: Registry MaxWindow %X\n"), MaxWindow));
  1690. }
  1691. ZwClose(KeyHandle);
  1692. }
  1693. else
  1694. DEBUGMSG(DBG_IRMAC, (TEXT("Failed to open key %x\n"), Status));
  1695. DEBUGMSG(DBG_NDIS, (TEXT("Slots %x, HintCharSet %x, Disconnect %x\n"),
  1696. Slots, HintCharSet, DisconnectTime));
  1697. //
  1698. // adjust the Slots value to make sure it is valid. Can only be 1, 6, 8, 16
  1699. //
  1700. if (Slots > 8) {
  1701. Slots = 16;
  1702. } else {
  1703. if (Slots > 6) {
  1704. Slots = 8;
  1705. } else {
  1706. if (Slots > 1) {
  1707. Slots = 6;
  1708. } else {
  1709. Slots = 1;
  1710. }
  1711. }
  1712. }
  1713. //
  1714. // Use the ComputerName as the discovery nickname
  1715. //
  1716. RtlZeroMemory(&NickName,sizeof(NickName));
  1717. NickNameLen = 0;
  1718. RtlInitUnicodeString(
  1719. &Path,
  1720. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ComputerName");
  1721. InitializeObjectAttributes(&ObjectAttribs,
  1722. &Path,
  1723. OBJ_CASE_INSENSITIVE,
  1724. NULL,
  1725. NULL);
  1726. Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttribs);
  1727. if (Status == STATUS_SUCCESS)
  1728. {
  1729. RtlInitUnicodeString(&ValStr, L"ComputerName");
  1730. FullInfo = (PKEY_VALUE_FULL_INFORMATION) Buf;
  1731. Status = ZwQueryValueKey(KeyHandle,
  1732. &ValStr,
  1733. KeyValueFullInformation,
  1734. FullInfo,
  1735. WORK_BUF_SIZE,
  1736. &Result);
  1737. NickNameLen = 0;
  1738. HintCharSet &= ~0xff;
  1739. //
  1740. // check to see if any of the machine name characters are non ansi, if so
  1741. // use unicode. Otherwise, send as ansi so more characters can be displayed.
  1742. //
  1743. for (i=0; i< FullInfo->DataLength/sizeof(WCHAR); i++) {
  1744. PWCHAR SourceString=(PWCHAR)((PUCHAR)FullInfo + FullInfo->DataOffset);
  1745. if (SourceString[i] > 127) {
  1746. HintCharSet |= UNICODE_CHAR_SET;
  1747. break;
  1748. }
  1749. }
  1750. if ((HintCharSet & 0XFF) == UNICODE_CHAR_SET) {
  1751. PWCHAR SourceString=(PWCHAR)((PUCHAR)FullInfo + FullInfo->DataOffset);
  1752. PWCHAR DestString=(PWCHAR)NickName;
  1753. for (i=0; i< FullInfo->DataLength/sizeof(WCHAR) && i < NICK_NAME_LEN/sizeof(WCHAR) ; i++) {
  1754. DestString[i]=SourceString[i];
  1755. NickNameLen+=sizeof(WCHAR);
  1756. }
  1757. } else {
  1758. UNICODE_STRING SourceString;
  1759. ANSI_STRING DestString;
  1760. SourceString.Length=(USHORT)FullInfo->DataLength;
  1761. SourceString.MaximumLength=SourceString.Length;
  1762. SourceString.Buffer=(PWCHAR)((PUCHAR)FullInfo + FullInfo->DataOffset);
  1763. DestString.MaximumLength=NICK_NAME_LEN;
  1764. DestString.Buffer=NickName;
  1765. RtlUnicodeStringToAnsiString(&DestString, &SourceString, FALSE);
  1766. NickNameLen=DestString.Length;
  1767. }
  1768. ZwClose(KeyHandle);
  1769. }
  1770. // Disable paging of code and data if indicated in registery
  1771. if (PagingFlags & DISABLE_CODE_PAGING)
  1772. {
  1773. // Any function in the section PAGEIRDA that is locked down
  1774. // will cause the entire section to be locked into memory
  1775. MmLockPagableCodeSection(OidToLapQos);
  1776. DEBUGMSG(DBG_WARN, (TEXT("IRNDIS: Code paging is disabled\n")));
  1777. }
  1778. if (PagingFlags & DISABLE_DATA_PAGING)
  1779. {
  1780. MmLockPagableDataSection(&DisconnectTime);
  1781. DEBUGMSG(DBG_WARN, (TEXT("IRNDIS: Data paging is disabled\n")));
  1782. }
  1783. // Register protocol with Ndis
  1784. NdisZeroMemory((PVOID)&pc, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  1785. pc.MajorNdisVersion = 0x04;
  1786. pc.MinorNdisVersion = 0x00;
  1787. pc.OpenAdapterCompleteHandler = IrdaOpenAdapterComplete;
  1788. pc.CloseAdapterCompleteHandler = IrdaCloseAdapterComplete;
  1789. pc.SendCompleteHandler = IrdaSendComplete;
  1790. pc.TransferDataCompleteHandler = IrdaTransferDataComplete;
  1791. pc.ResetCompleteHandler = IrdaResetComplete;
  1792. pc.RequestCompleteHandler = IrdaRequestComplete;
  1793. pc.ReceiveHandler = IrdaReceive;
  1794. pc.ReceiveCompleteHandler = IrdaReceiveComplete;
  1795. pc.StatusHandler = IrdaStatus;
  1796. pc.StatusCompleteHandler = IrdaStatusComplete;
  1797. pc.BindAdapterHandler = IrdaBindAdapter;
  1798. pc.UnbindAdapterHandler = IrdaUnbindAdapter;
  1799. pc.UnloadHandler = NULL;
  1800. pc.Name = *ProtocolName;
  1801. pc.ReceivePacketHandler = IrdaReceivePacket;
  1802. #if defined(_PNP_POWER_)
  1803. pc.PnPEventHandler = IrdaPnpEvent;
  1804. #endif
  1805. NdisRegisterProtocol(&Status,
  1806. &NdisIrdaHandle,
  1807. (PNDIS_PROTOCOL_CHARACTERISTICS)&pc,
  1808. sizeof(NDIS40_PROTOCOL_CHARACTERISTICS));
  1809. IrlmpInitialize();
  1810. DEBUGMSG(DBG_NDIS, (TEXT("-IrdaInitialize(), rc %x\n"), Status));
  1811. return Status;
  1812. }