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

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