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.

1451 lines
40 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 1996-1999 Microsoft Corporation
  4. *
  5. * @doc
  6. * @module irsir.c | IrSIR NDIS Miniport Driver
  7. * @comm
  8. *
  9. *-----------------------------------------------------------------------------
  10. *
  11. * Author: Scott Holden (sholden)
  12. *
  13. * Date: 10/3/1996 (created)
  14. *
  15. * Contents:
  16. *
  17. *****************************************************************************/
  18. #include "irsir.h"
  19. VOID
  20. ResetCallback(
  21. PIR_WORK_ITEM pWorkItem
  22. );
  23. NDIS_STATUS
  24. ResetIrDevice(
  25. PIR_DEVICE pThisDev
  26. );
  27. VOID
  28. StopWorkerThread(
  29. PIR_DEVICE pThisDev
  30. );
  31. NDIS_STATUS
  32. DriverEntry(
  33. PDRIVER_OBJECT DriverObject,
  34. PUNICODE_STRING RegistryPath
  35. );
  36. #pragma NDIS_INIT_FUNCTION(DriverEntry)
  37. #pragma alloc_text(PAGE,ResetCallback)
  38. #pragma alloc_text(PAGE,IrsirHalt)
  39. #pragma alloc_text(PAGE,ResetIrDevice)
  40. #pragma alloc_text(PAGE,IrsirInitialize)
  41. #pragma alloc_text(PAGE,IrsirHalt)
  42. #pragma alloc_text(PAGE,PassiveLevelThread)
  43. #pragma alloc_text(PAGE,SetIrFunctions)
  44. #pragma alloc_text(PAGE,StopWorkerThread)
  45. //
  46. // Global list of device objects and a spin lock to interleave access
  47. // to the global queue.
  48. //
  49. #ifdef DEBUG
  50. int DbgSettings =
  51. //DBG_PNP |
  52. //DBG_TIME |
  53. //DBG_DBG |
  54. //DBG_STAT |
  55. //DBG_FUNCTION |
  56. DBG_ERROR |
  57. DBG_WARN |
  58. //DBG_OUT |
  59. 0;
  60. #endif
  61. // We use these timeouts when we just have to return soon.
  62. SERIAL_TIMEOUTS SerialTimeoutsInit =
  63. {
  64. 30, // ReadIntervalTimeout
  65. 0, // ReadTotalTimeoutMultiplier
  66. 250, // ReadTotalTimeoutConstant
  67. 0, // WriteTotalTimeoutMultiplier
  68. 20*1000 // WriteTotalTimeoutConstant
  69. };
  70. // We use the timeouts while we're running, and we want to return less frequently.
  71. SERIAL_TIMEOUTS SerialTimeoutsIdle =
  72. {
  73. MAXULONG, // ReadIntervalTimeout
  74. 0, // ReadTotalTimeoutMultiplier
  75. 10, // ReadTotalTimeoutConstant
  76. 0, // WriteTotalTimeoutMultiplier
  77. 20*1000 // WriteTotalTimeoutConstant
  78. };
  79. #if IRSIR_EVENT_DRIVEN
  80. // We use the timeouts while we're running, and we want to return less frequently.
  81. SERIAL_TIMEOUTS SerialTimeoutsActive =
  82. {
  83. MAXULONG, // ReadIntervalTimeout
  84. 0, // ReadTotalTimeoutMultiplier
  85. 0, // ReadTotalTimeoutConstant
  86. 0, // WriteTotalTimeoutMultiplier
  87. 0 // WriteTotalTimeoutConstant
  88. };
  89. #endif
  90. /*****************************************************************************
  91. *
  92. * Function: DriverEntry
  93. *
  94. * Synopsis: register driver entry functions with NDIS
  95. *
  96. * Arguments: DriverObject - the driver object being initialized
  97. * RegistryPath - registry path of the driver
  98. *
  99. * Returns: value returned by NdisMRegisterMiniport
  100. *
  101. * Algorithm:
  102. *
  103. * History: dd-mm-yyyy Author Comment
  104. * 10/3/1996 sholden author
  105. *
  106. * Notes:
  107. *
  108. * This routine runs at IRQL PASSIVE_LEVEL.
  109. *
  110. *****************************************************************************/
  111. //
  112. // Mark the DriverEntry function to run once during initialization.
  113. //
  114. #ifndef MAX_PATH
  115. #define MAX_PATH 2048
  116. #endif
  117. NDIS_STATUS
  118. DriverEntry(
  119. IN PDRIVER_OBJECT pDriverObject,
  120. IN PUNICODE_STRING pRegistryPath
  121. )
  122. {
  123. NDIS_STATUS status;
  124. #if NDIS_MAJOR_VERSION < 5
  125. NDIS40_MINIPORT_CHARACTERISTICS characteristics;
  126. #else
  127. NDIS50_MINIPORT_CHARACTERISTICS characteristics;
  128. #endif
  129. NDIS_HANDLE hWrapper;
  130. #if MEM_CHECKING
  131. InitMemory();
  132. #endif
  133. DEBUGMSG(DBG_FUNC, ("+DriverEntry(irsir)\n"));
  134. NdisMInitializeWrapper(
  135. &hWrapper,
  136. pDriverObject,
  137. pRegistryPath,
  138. NULL
  139. );
  140. NdisZeroMemory(&characteristics, sizeof(characteristics));
  141. characteristics.MajorNdisVersion = (UCHAR)NDIS_MAJOR_VERSION;
  142. characteristics.MinorNdisVersion = (UCHAR)NDIS_MINOR_VERSION;
  143. characteristics.Reserved = 0;
  144. characteristics.HaltHandler = IrsirHalt;
  145. characteristics.InitializeHandler = IrsirInitialize;
  146. characteristics.QueryInformationHandler = IrsirQueryInformation;
  147. characteristics.SetInformationHandler = IrsirSetInformation;
  148. characteristics.ResetHandler = IrsirReset;
  149. //
  150. // For now we will allow NDIS to send only one packet at a time.
  151. //
  152. characteristics.SendHandler = IrsirSend;
  153. characteristics.SendPacketsHandler = NULL;
  154. //
  155. // We don't use NdisMIndicateXxxReceive function, so we will
  156. // need a ReturnPacketHandler to retrieve our packet resources.
  157. //
  158. characteristics.ReturnPacketHandler = IrsirReturnPacket;
  159. characteristics.TransferDataHandler = NULL;
  160. //
  161. // NDIS never calls the ReconfigureHandler.
  162. //
  163. characteristics.ReconfigureHandler = NULL;
  164. //
  165. // Let NDIS handle the hangs for now.
  166. //
  167. // If a CheckForHangHandler is supplied, NDIS will call it every two
  168. // seconds (by default) or at a driver specified interval.
  169. //
  170. // When not supplied, NDIS will conclude that the miniport is hung:
  171. // 1) a send packet has been pending longer than twice the
  172. // timeout period
  173. // 2) a request to IrsirQueryInformation or IrsirSetInformation
  174. // is not completed in a period equal to twice the timeout
  175. // period.
  176. // NDIS will keep track of the NdisMSendComplete calls and probably do
  177. // a better job of ensuring the miniport is not hung.
  178. //
  179. // If NDIS detects that the miniport is hung, NDIS calls
  180. // IrsirReset.
  181. //
  182. characteristics.CheckForHangHandler = NULL;
  183. //
  184. // This miniport driver does not handle interrupts.
  185. //
  186. characteristics.HandleInterruptHandler = NULL;
  187. characteristics.ISRHandler = NULL;
  188. characteristics.DisableInterruptHandler = NULL;
  189. characteristics.EnableInterruptHandler = NULL;
  190. //
  191. // This miniport does not control a busmaster DMA with
  192. // NdisMAllocateShareMemoryAsysnc, AllocateCompleteHandler won't be
  193. // called from NDIS.
  194. //
  195. characteristics.AllocateCompleteHandler = NULL;
  196. //
  197. // Need to initialize the ir device object queue and the spin lock
  198. // to interleave access to the queue at this point, since after we
  199. // return, the driver will only deal with the device level.
  200. //
  201. status = NdisMRegisterMiniport(
  202. hWrapper,
  203. (PNDIS_MINIPORT_CHARACTERISTICS)&characteristics,
  204. sizeof(characteristics)
  205. );
  206. if (status != NDIS_STATUS_SUCCESS)
  207. {
  208. DEBUGMSG(DBG_ERROR, (" NdisMRegisterMiniport failed. Returned 0x%.8x.\n", status));
  209. }
  210. DEBUGMSG(DBG_FUNC, ("-DriverEntry(irsir)\n"));
  211. return status;
  212. }
  213. // Provide some default functions for dongle handling.
  214. NDIS_STATUS UnknownDongleInit(PDEVICE_OBJECT NotUsed)
  215. {
  216. return NDIS_STATUS_FAILURE;
  217. }
  218. NDIS_STATUS UnknownDongleQueryCaps(PDONGLE_CAPABILITIES NotUsed)
  219. {
  220. return NDIS_STATUS_FAILURE;
  221. }
  222. void UnknownDongleDeinit(PDEVICE_OBJECT NotUsed)
  223. {
  224. return;
  225. }
  226. NDIS_STATUS UnknownDongleSetSpeed(PDEVICE_OBJECT pSerialDevObj,
  227. UINT bitsPerSec,
  228. UINT currentSpeed
  229. )
  230. {
  231. return NDIS_STATUS_FAILURE;
  232. }
  233. NTSTATUS SetIrFunctions(PIR_DEVICE pThisDev)
  234. {
  235. NTSTATUS Status = STATUS_SUCCESS;
  236. //
  237. // Need to initialize the dongle code.
  238. //
  239. switch (pThisDev->transceiverType)
  240. {
  241. case STANDARD_UART:
  242. DEBUGMSG(DBG_OUT, ("IRSIR: Dongle type:%d -- UART\n", pThisDev->transceiverType));
  243. pThisDev->dongle.QueryCaps = StdUart_QueryCaps;
  244. pThisDev->dongle.Initialize = StdUart_Init;
  245. pThisDev->dongle.SetSpeed = StdUart_SetSpeed;
  246. pThisDev->dongle.Deinitialize = StdUart_Deinit;
  247. break;
  248. case ESI_9680:
  249. DEBUGMSG(DBG_OUT, ("IRSIR: Dongle type:%d -- ESI_9680\n", pThisDev->transceiverType));
  250. pThisDev->dongle.QueryCaps = ESI_QueryCaps;
  251. pThisDev->dongle.Initialize = ESI_Init;
  252. pThisDev->dongle.SetSpeed = ESI_SetSpeed;
  253. pThisDev->dongle.Deinitialize = ESI_Deinit;
  254. break;
  255. case PARALLAX:
  256. DEBUGMSG(DBG_OUT, ("IRSIR: Dongle type:%d -- PARALLAX\n", pThisDev->transceiverType));
  257. pThisDev->dongle.QueryCaps = PARALLAX_QueryCaps;
  258. pThisDev->dongle.Initialize = PARALLAX_Init;
  259. pThisDev->dongle.SetSpeed = PARALLAX_SetSpeed;
  260. pThisDev->dongle.Deinitialize = PARALLAX_Deinit;
  261. break;
  262. case ACTISYS_200L:
  263. DEBUGMSG(DBG_OUT, ("IRSIR: Dongle type:%d -- ACTISYS 200L\n", pThisDev->transceiverType));
  264. pThisDev->dongle.QueryCaps = ACT200L_QueryCaps;
  265. pThisDev->dongle.Initialize = ACT200L_Init;
  266. pThisDev->dongle.SetSpeed = ACT200L_SetSpeed;
  267. pThisDev->dongle.Deinitialize = ACT200L_Deinit;
  268. break;
  269. case ACTISYS_220L:
  270. DEBUGMSG(DBG_OUT, ("IRSIR: Dongle type:%d -- ACTISYS 220L\n", pThisDev->transceiverType));
  271. pThisDev->dongle.QueryCaps = ACT220L_QueryCaps;
  272. pThisDev->dongle.Initialize = ACT220L_Init;
  273. pThisDev->dongle.SetSpeed = ACT220L_SetSpeed;
  274. pThisDev->dongle.Deinitialize = ACT220L_Deinit;
  275. break;
  276. case ACTISYS_220LPLUS:
  277. DEBUGMSG(DBG_OUT, ("IRSIR: Dongle type:%d -- ACTISYS 220L\n", pThisDev->transceiverType));
  278. pThisDev->dongle.QueryCaps = ACT220LPlus_QueryCaps;
  279. pThisDev->dongle.Initialize = ACT220L_Init;
  280. pThisDev->dongle.SetSpeed = ACT220L_SetSpeed;
  281. pThisDev->dongle.Deinitialize = ACT220L_Deinit;
  282. break;
  283. case TEKRAM_IRMATE_210:
  284. DEBUGMSG(DBG_OUT, ("IRSIR: Dongle type:%d -- TEKRAM IRMATE 210 or PUMA\n", pThisDev->transceiverType));
  285. pThisDev->dongle.QueryCaps = TEKRAM_QueryCaps;
  286. pThisDev->dongle.Initialize = TEKRAM_Init;
  287. pThisDev->dongle.SetSpeed = TEKRAM_SetSpeed;
  288. pThisDev->dongle.Deinitialize = TEKRAM_Deinit;
  289. break;
  290. case AMP_PHASIR:
  291. DEBUGMSG(DBG_OUT, ("IRSIR: Dongle type:%d -- AMP PHASIR or CRYSTAL\n", pThisDev->transceiverType));
  292. pThisDev->dongle.QueryCaps = Crystal_QueryCaps;
  293. pThisDev->dongle.Initialize = Crystal_Init;
  294. pThisDev->dongle.SetSpeed = Crystal_SetSpeed;
  295. pThisDev->dongle.Deinitialize = Crystal_Deinit;
  296. break;
  297. case TEMIC_TOIM3232:
  298. DEBUGMSG(DBG_OUT, ("IRSIR: Dongle type:%d -- TEMIC TOIM3232\n", pThisDev->transceiverType));
  299. pThisDev->dongle.QueryCaps = TEMIC_QueryCaps;
  300. pThisDev->dongle.Initialize = TEMIC_Init;
  301. pThisDev->dongle.SetSpeed = TEMIC_SetSpeed;
  302. pThisDev->dongle.Deinitialize = TEMIC_Deinit;
  303. break;
  304. case GIRBIL:
  305. DEBUGMSG(DBG_OUT, ("IRSIR: Dongle type:%d -- GIRBIL\n", pThisDev->transceiverType));
  306. pThisDev->dongle.QueryCaps = GIRBIL_QueryCaps;
  307. pThisDev->dongle.Initialize = GIRBIL_Init;
  308. pThisDev->dongle.SetSpeed = GIRBIL_SetSpeed;
  309. pThisDev->dongle.Deinitialize = GIRBIL_Deinit;
  310. break;
  311. // case ADAPTEC:
  312. // case CRYSTAL:
  313. // case NSC_DEMO_BD:
  314. default:
  315. DEBUGMSG(DBG_ERROR, (" Failure: Tranceiver type is NOT supported!\n"));
  316. pThisDev->dongle.QueryCaps = UnknownDongleQueryCaps;
  317. pThisDev->dongle.Initialize = UnknownDongleInit;
  318. pThisDev->dongle.SetSpeed = UnknownDongleSetSpeed;
  319. pThisDev->dongle.Deinitialize = UnknownDongleDeinit;
  320. // The dongle functions have already been set to stubs in
  321. // InitializeDevice().
  322. Status = NDIS_STATUS_FAILURE;
  323. break;
  324. }
  325. return Status;
  326. }
  327. /*****************************************************************************
  328. *
  329. * Function: IrsirInitialize
  330. *
  331. * Synopsis: Initializes the NIC (serial.sys) and allocates all resources
  332. * required to carry out network io operations.
  333. *
  334. * Arguments: OpenErrorStatus - allows IrsirInitialize to return additional
  335. * status code NDIS_STATUS_xxx if returning
  336. * NDIS_STATUS_OPEN_FAILED
  337. * SelectedMediumIndex - specifies to NDIS the medium type the
  338. * driver uses
  339. * MediumArray - array of NdisMediumXXX the driver can choose
  340. * MediumArraySize
  341. * MiniportAdapterHandle - handle identifying miniport's NIC
  342. * WrapperConfigurationContext - used with Ndis config and init
  343. * routines
  344. *
  345. * Returns: NDIS_STATUS_SUCCESS if properly configure and resources allocated
  346. * NDIS_STATUS_FAILURE, otherwise
  347. * more specific failures:
  348. * NDIS_STATUS_UNSUPPORTED_MEDIA - driver can't support any medium
  349. * NDIS_STATUS_ADAPTER_NOT_FOUND - NdisOpenConfiguration or
  350. * NdisReadConfiguration failed
  351. * NDIS_STATUS_OPEN_FAILED - failed to open serial.sys
  352. * NDIS_STATUS_NOT_ACCEPTED - serial.sys does not accept the
  353. * configuration
  354. * NDIS_STATUS_RESOURCES - could not claim sufficient
  355. * resources
  356. *
  357. * Algorithm:
  358. *
  359. * History: dd-mm-yyyy Author Comment
  360. * 10/3/1996 sholden author
  361. *
  362. * Notes: NDIS will not submit requests until this is complete.
  363. *
  364. * This routine runs at IRQL PASSIVE_LEVEL.
  365. *
  366. *****************************************************************************/
  367. NDIS_STATUS
  368. IrsirInitialize(
  369. OUT PNDIS_STATUS OpenErrorStatus,
  370. OUT PUINT SelectedMediumIndex,
  371. IN PNDIS_MEDIUM MediumArray,
  372. IN UINT MediumArraySize,
  373. IN NDIS_HANDLE NdisAdapterHandle,
  374. IN NDIS_HANDLE WrapperConfigurationContext
  375. )
  376. {
  377. UINT i;
  378. PIR_DEVICE pThisDev = NULL;
  379. SERIAL_LINE_CONTROL serialLineControl;
  380. SERIAL_TIMEOUTS serialTimeouts;
  381. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  382. ULONG bitsPerSec = 9600;
  383. DEBUGMSG(DBG_FUNC, ("+IrsirInitialize\n"));
  384. //
  385. // Search for the irda medium in the medium array.
  386. //
  387. for (i = 0; i < MediumArraySize; i++)
  388. {
  389. if (MediumArray[i] == NdisMediumIrda)
  390. {
  391. break;
  392. }
  393. }
  394. if (i < MediumArraySize)
  395. {
  396. *SelectedMediumIndex = i;
  397. }
  398. else
  399. {
  400. //
  401. // Irda medium not found.
  402. //
  403. DEBUGMSG(DBG_ERROR, (" Failure: NdisMediumIrda not found!\n"));
  404. status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  405. goto done;
  406. }
  407. //
  408. // Allocate a device object and zero memory.
  409. //
  410. pThisDev = NewDevice();
  411. if (pThisDev == NULL)
  412. {
  413. DEBUGMSG(DBG_ERROR, (" NewDevice failed.\n"));
  414. status = NDIS_STATUS_RESOURCES;
  415. goto done;
  416. }
  417. pThisDev->dongle.Initialize = UnknownDongleInit;
  418. pThisDev->dongle.SetSpeed = UnknownDongleSetSpeed;
  419. pThisDev->dongle.Deinitialize = UnknownDongleDeinit;
  420. pThisDev->dongle.QueryCaps = UnknownDongleQueryCaps;
  421. //
  422. // Initialize device object and resources.
  423. // All the queues and buffer/packets etc. are allocated here.
  424. //
  425. status = InitializeDevice(pThisDev);
  426. if (status != NDIS_STATUS_SUCCESS)
  427. {
  428. DEBUGMSG(DBG_ERROR, (" InitializeDevice failed. Returned 0x%.8x\n",
  429. status));
  430. goto done;
  431. }
  432. //
  433. // Record the NdisAdapterHandle.
  434. //
  435. pThisDev->hNdisAdapter = NdisAdapterHandle;
  436. //
  437. // NdisMSetAttributes will associate our adapter handle with the wrapper's
  438. // adapter handle. The wrapper will then always use our handle
  439. // when calling us. We use a pointer to the device object as the context.
  440. //
  441. NdisMSetAttributesEx(NdisAdapterHandle,
  442. (NDIS_HANDLE)pThisDev,
  443. 0,
  444. NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND |
  445. NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT |
  446. NDIS_ATTRIBUTE_DESERIALIZE, // Magic bullet
  447. NdisInterfaceInternal);
  448. //
  449. // Initialize a notification event for signalling PassiveLevelThread.
  450. //
  451. KeInitializeEvent(
  452. &pThisDev->eventPassiveThread,
  453. SynchronizationEvent, // auto-clearing event
  454. FALSE // event initially non-signalled
  455. );
  456. KeInitializeEvent(
  457. &pThisDev->eventKillThread,
  458. SynchronizationEvent, // auto-clearing event
  459. FALSE // event initially non-signalled
  460. );
  461. //
  462. // Create a thread to run at IRQL PASSIVE_LEVEL.
  463. //
  464. status = (NDIS_STATUS) PsCreateSystemThread(
  465. &pThisDev->hPassiveThread,
  466. (ACCESS_MASK) 0L,
  467. NULL,
  468. NULL,
  469. NULL,
  470. PassiveLevelThread,
  471. DEV_TO_CONTEXT(pThisDev)
  472. );
  473. if (status != NDIS_STATUS_SUCCESS)
  474. {
  475. DEBUGMSG(DBG_ERROR, (" PsCreateSystemThread failed. Returned 0x%.8x\n", status));
  476. goto done;
  477. }
  478. // At this point we've done everything but actually touch the serial
  479. // port. We do so now.
  480. //
  481. // Get device configuration from the registry settings.
  482. // We are getting the transceiver type and which serial
  483. // device object to access.
  484. // The information which we get from the registry will outlast
  485. // any NIC resets.
  486. //
  487. status = GetDeviceConfiguration(
  488. pThisDev,
  489. WrapperConfigurationContext
  490. );
  491. if (status != NDIS_STATUS_SUCCESS)
  492. {
  493. DEBUGMSG(DBG_ERROR, (" GetDeviceConfiguration failed. Returned 0x%.8x\n",
  494. status));
  495. status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  496. goto done;
  497. }
  498. //
  499. // Open the serial device object specified in the registry.
  500. //
  501. status = SerialOpen(pThisDev);
  502. if (status != NDIS_STATUS_SUCCESS)
  503. {
  504. DEBUGMSG(DBG_ERROR, (" SerialOpen failed. Returned 0x%.8x\n", status));
  505. status = NDIS_STATUS_SUCCESS; // We'll get the port later.
  506. }
  507. if (pThisDev->pSerialDevObj)
  508. {
  509. {
  510. //
  511. // Set the minimum port buffering.
  512. //
  513. SERIAL_QUEUE_SIZE QueueSize;
  514. QueueSize.InSize = 3*1024; // 1.5 packet size
  515. QueueSize.OutSize = 0;
  516. // Ignore failure. We'll still work, just not as well.
  517. (void)SerialSetQueueSize(pThisDev->pSerialDevObj, &QueueSize);
  518. }
  519. #if 0
  520. {
  521. SERIAL_HANDFLOW Handflow;
  522. SerialGetHandflow(pThisDev->pSerialDevObj, &Handflow);
  523. DEBUGMSG(DBG_PNP, ("IRSIR: Serial Handflow was: %x %x %x %x\n",
  524. Handflow.ControlHandShake,
  525. Handflow.FlowReplace,
  526. Handflow.XonLimit,
  527. Handflow.XoffLimit));
  528. Handflow.ControlHandShake = 0;
  529. Handflow.FlowReplace = 0;
  530. SerialSetHandflow(pThisDev->pSerialDevObj, &Handflow);
  531. }
  532. #endif
  533. //
  534. // Must set the timeout value of the serial port
  535. // for a read.
  536. //
  537. status = (NDIS_STATUS) SerialSetTimeouts(pThisDev->pSerialDevObj,
  538. &SerialTimeoutsInit);
  539. if (status != NDIS_STATUS_SUCCESS)
  540. {
  541. DEBUGMSG(DBG_ERROR, (" SerialSetTimeouts failed. Returned 0x%.8x\n", status));
  542. status = NDIS_STATUS_FAILURE;
  543. goto done;
  544. }
  545. (void)SerialSetBaudRate(pThisDev->pSerialDevObj, &bitsPerSec);
  546. serialLineControl.StopBits = STOP_BIT_1;
  547. serialLineControl.Parity = NO_PARITY ;
  548. serialLineControl.WordLength = 8;
  549. status = (NDIS_STATUS) SerialSetLineControl(
  550. pThisDev->pSerialDevObj,
  551. &serialLineControl
  552. );
  553. if (status != NDIS_STATUS_SUCCESS)
  554. {
  555. DEBUGMSG(DBG_ERROR, (" SerialSetLineControl failed. Returned 0x%.8x\n", status));
  556. goto done;
  557. }
  558. }
  559. status = SetIrFunctions(pThisDev);
  560. if (status!=STATUS_SUCCESS)
  561. {
  562. goto done;
  563. }
  564. if (pThisDev->pSerialDevObj)
  565. {
  566. //
  567. // Now that a serial device object is open, we can initialize the
  568. // dongle and set the speed of the dongle to the default.
  569. //
  570. if (pThisDev->dongle.Initialize(pThisDev->pSerialDevObj)!=NDIS_STATUS_SUCCESS)
  571. {
  572. DEBUGMSG(DBG_ERROR, (" IRSIR: dongle failed to init!\n"));
  573. status = NDIS_STATUS_FAILURE;
  574. goto done;
  575. }
  576. }
  577. pThisDev->dongle.QueryCaps(&pThisDev->dongleCaps);
  578. if (pThisDev->pSerialDevObj)
  579. {
  580. //
  581. // Set the speed of the uart and the dongle.
  582. //
  583. status = (NDIS_STATUS) SetSpeed(pThisDev);
  584. if (status != NDIS_STATUS_SUCCESS)
  585. {
  586. DEBUGMSG(DBG_ERROR, (" IRSIR: Setspeed failed. Returned 0x%.8x\n", status));
  587. goto done;
  588. }
  589. //
  590. // Create an irp and do an MJ_READ to begin our receives.
  591. // NOTE: All other receive processing will be done in the read completion
  592. // routine which is done set from this MJ_READ.
  593. //
  594. status = InitializeReceive(pThisDev);
  595. if (status != NDIS_STATUS_SUCCESS)
  596. {
  597. DEBUGMSG(DBG_ERROR, (" InitializeReceive failed. Returned 0x%.8x\n", status));
  598. goto done;
  599. }
  600. }
  601. done:
  602. if (status != NDIS_STATUS_SUCCESS) {
  603. DEBUGMSG(DBG_ERR, ("IRSIR: IrsirInitialize failed %x\n", status));
  604. if (pThisDev != NULL) {
  605. if (pThisDev->hPassiveThread) {
  606. pThisDev->fPendingHalt = TRUE;
  607. StopWorkerThread(pThisDev);
  608. }
  609. if (pThisDev->pSerialDevObj != NULL) {
  610. if (pThisDev->dongle.Deinitialize) {
  611. pThisDev->dongle.Deinitialize(pThisDev->pSerialDevObj);
  612. }
  613. SerialClose(pThisDev);
  614. }
  615. DeinitializeDevice(pThisDev);
  616. FreeDevice(pThisDev);
  617. }
  618. }
  619. DEBUGMSG(DBG_FUNC, ("-IrsirInitialize\n"));
  620. return status;
  621. }
  622. /*****************************************************************************
  623. *
  624. * Function: IrsirHalt
  625. *
  626. * Synopsis: Deallocates resources when the NIC is removed and halts the
  627. * NIC.
  628. *
  629. * Arguments: Context - pointer to the ir device object
  630. *
  631. * Returns:
  632. *
  633. * Algorithm: Mirror image of IrsirInitialize...undoes everything initialize
  634. * did.
  635. *
  636. * History: dd-mm-yyyy Author Comment
  637. * 10/8/1996 sholden author
  638. *
  639. * Notes:
  640. *
  641. * This routine runs at IRQL PASSIVE_LEVEL.
  642. *
  643. *****************************************************************************/
  644. VOID
  645. IrsirHalt(
  646. IN NDIS_HANDLE Context
  647. )
  648. {
  649. PIR_DEVICE pThisDev;
  650. DEBUGMSG(DBG_FUNC, ("+IrsirHalt\n"));
  651. pThisDev = CONTEXT_TO_DEV(Context);
  652. //
  653. // Let the send completion and receive completion routine know that there
  654. // is a pending halt.
  655. //
  656. pThisDev->fPendingHalt = TRUE;
  657. //
  658. // We want to wait until all pending receives and sends to the
  659. // serial device object. We call serial purge to cancel any
  660. // irps. Wait until sends and receives have stopped.
  661. //
  662. SerialPurge(pThisDev->pSerialDevObj);
  663. PausePacketProcessing(&pThisDev->SendPacketQueue,TRUE);
  664. FlushQueuedPackets(&pThisDev->SendPacketQueue,pThisDev->hNdisAdapter);
  665. while(
  666. (pThisDev->fReceiving == TRUE)
  667. )
  668. {
  669. //
  670. // Sleep for 20 milliseconds.
  671. //
  672. NdisMSleep(20000);
  673. }
  674. //
  675. // Deinitialize the dongle.
  676. //
  677. ASSERT(pThisDev->packetsHeldByProtocol==0);
  678. pThisDev->dongle.Deinitialize(
  679. pThisDev->pSerialDevObj
  680. );
  681. //
  682. // Close the serial device object.
  683. //
  684. SerialClose(pThisDev);
  685. //
  686. // Need to terminate our worker threadxs. However, the thread
  687. // needs to call PsTerminateSystemThread itself. Therefore,
  688. // we will signal it.
  689. //
  690. StopWorkerThread(pThisDev);
  691. //
  692. // Deinitialize our own ir device object.
  693. //
  694. DeinitializeDevice(pThisDev);
  695. //
  696. // Free the device names.
  697. //
  698. if (pThisDev->serialDosName.Buffer)
  699. {
  700. MyMemFree(pThisDev->serialDosName.Buffer,
  701. MAX_SERIAL_NAME_SIZE
  702. );
  703. pThisDev->serialDosName.Buffer = NULL;
  704. }
  705. if (pThisDev->serialDevName.Buffer)
  706. {
  707. MyMemFree(
  708. pThisDev->serialDevName.Buffer,
  709. MAX_SERIAL_NAME_SIZE
  710. );
  711. pThisDev->serialDevName.Buffer = NULL;
  712. }
  713. //
  714. // Free our own ir device object.
  715. //
  716. FreeDevice(pThisDev);
  717. DEBUGMSG(DBG_FUNC, ("-IrsirHalt\n"));
  718. return;
  719. }
  720. VOID
  721. ResetCallback(
  722. PIR_WORK_ITEM pWorkItem
  723. )
  724. {
  725. PIR_DEVICE pThisDev = pWorkItem->pIrDevice;
  726. NDIS_STATUS status;
  727. BOOLEAN fSwitchSuccessful;
  728. NDIS_HANDLE hSwitchToMiniport;
  729. //
  730. // Reset this device by request of IrsirReset.
  731. //
  732. DEBUGMSG(DBG_STAT, (" primPassive = PASSIVE_RESET_DEVICE\n"));
  733. ASSERT(pThisDev->fPendingReset == TRUE);
  734. if (pThisDev->pSerialDevObj) {
  735. SerialPurge(pThisDev->pSerialDevObj);
  736. }
  737. PausePacketProcessing(&pThisDev->SendPacketQueue,TRUE);
  738. FlushQueuedPackets(&pThisDev->SendPacketQueue,pThisDev->hNdisAdapter);
  739. status = ResetIrDevice(pThisDev);
  740. #if DBG
  741. if (status != NDIS_STATUS_SUCCESS)
  742. {
  743. DEBUGMSG(DBG_ERROR, (" ResetIrDevice failed = 0x%.8x\n", status));
  744. }
  745. #endif //DBG
  746. //
  747. //
  748. if (status != STATUS_SUCCESS)
  749. {
  750. NdisWriteErrorLogEntry(pThisDev->hNdisAdapter,
  751. NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
  752. 1,
  753. status);
  754. status = NDIS_STATUS_HARD_ERRORS;
  755. }
  756. NdisMResetComplete(
  757. pThisDev->hNdisAdapter,
  758. (NDIS_STATUS)status,
  759. TRUE
  760. );
  761. FreeWorkItem(pWorkItem);
  762. ActivatePacketProcessing(&pThisDev->SendPacketQueue);
  763. return;
  764. }
  765. /*****************************************************************************
  766. *
  767. * Function: IrsirReset
  768. *
  769. * Synopsis: Resets the drivers software state.
  770. *
  771. * Arguments: AddressingReset - return arg. If set to TRUE, NDIS will call
  772. * MiniportSetInformation to restore addressing
  773. * information to the current values.
  774. * Context - pointer to ir device object
  775. *
  776. * Returns: NDIS_STATUS_PENDING
  777. *
  778. * Algorithm:
  779. *
  780. * History: dd-mm-yyyy Author Comment
  781. * 10/9/1996 sholden author
  782. *
  783. * Notes:
  784. *
  785. * Runs at IRQL_DISPATCH_LEVEL, therefore we need to call a thread at
  786. * passive level to perform the reset.
  787. *
  788. *****************************************************************************/
  789. NDIS_STATUS
  790. IrsirReset(
  791. OUT PBOOLEAN AddressingReset,
  792. IN NDIS_HANDLE MiniportAdapterContext
  793. )
  794. {
  795. PIR_DEVICE pThisDev;
  796. NDIS_STATUS status;
  797. DEBUGMSG(DBG_STAT, ("+IrsirReset\n"));
  798. pThisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
  799. //
  800. // Let the receive completion routine know that there
  801. // is a pending reset.
  802. //
  803. pThisDev->fPendingReset = TRUE;
  804. *AddressingReset = TRUE;
  805. if (ScheduleWorkItem(PASSIVE_RESET_DEVICE, pThisDev,
  806. ResetCallback, NULL, 0) != NDIS_STATUS_SUCCESS)
  807. {
  808. status = NDIS_STATUS_SUCCESS;
  809. }
  810. else
  811. {
  812. status = NDIS_STATUS_PENDING;
  813. }
  814. DEBUGMSG(DBG_STAT, ("-IrsirReset\n"));
  815. return status;
  816. }
  817. /*****************************************************************************
  818. *
  819. * Function: ResetIrDevice
  820. *
  821. * Synopsis:
  822. *
  823. * Arguments:
  824. *
  825. * Returns:
  826. *
  827. * Algorithm:
  828. *
  829. * History: dd-mm-yyyy Author Comment
  830. * 10/17/1996 sholden author
  831. *
  832. * Notes:
  833. *
  834. * The following elements of the ir device object outlast the reset:
  835. *
  836. * eventPassiveThread
  837. * hPassiveThread
  838. * primPassive
  839. *
  840. * serialDevName
  841. * pSerialDevObj
  842. * TransceiverType
  843. * dongle
  844. *
  845. * hNdisAdapter
  846. *
  847. *****************************************************************************/
  848. NDIS_STATUS
  849. ResetIrDevice(
  850. PIR_DEVICE pThisDev
  851. )
  852. {
  853. SERIAL_LINE_CONTROL serialLineControl;
  854. SERIAL_TIMEOUTS serialTimeouts;
  855. NDIS_STATUS status;
  856. ULONG bitsPerSec = 9600;
  857. DEBUGMSG(DBG_STAT, ("+ResetIrDeviceThread\n"));
  858. //
  859. // We need to wait for the completion of all pending sends and receives
  860. // to the serial driver.
  861. //
  862. //
  863. // We can speed up by purging the serial driver.
  864. //
  865. if (pThisDev->pSerialDevObj) {
  866. SerialPurge(pThisDev->pSerialDevObj);
  867. while(
  868. (pThisDev->fReceiving == TRUE)
  869. )
  870. {
  871. //
  872. // Sleep for 20 milliseconds.
  873. //
  874. NdisMSleep(20000);
  875. }
  876. //
  877. // Deinit the dongle.
  878. //
  879. pThisDev->dongle.Deinitialize(pThisDev->pSerialDevObj);
  880. } else {
  881. //
  882. // we were not able to open the serial driver when the miniport first initialized.
  883. // The thread will call this routine to attempt to open the device every 3 seconds.
  884. //
  885. status = SerialOpen(pThisDev);
  886. if (status != NDIS_STATUS_SUCCESS)
  887. {
  888. DEBUGMSG(DBG_ERROR, (" SerialOpen failed. Returned 0x%.8x\n", status));
  889. goto done;
  890. }
  891. }
  892. if (pThisDev->pSerialDevObj)
  893. {
  894. {
  895. //
  896. // Set the minimum port buffering.
  897. //
  898. SERIAL_QUEUE_SIZE QueueSize;
  899. QueueSize.InSize = 3*1024; // 1.5 packet size
  900. QueueSize.OutSize = 0;
  901. // Ignore failure. We'll still work, just not as well.
  902. (void)SerialSetQueueSize(pThisDev->pSerialDevObj, &QueueSize);
  903. }
  904. //
  905. // Must set the timeout value of the serial port
  906. // for a read.
  907. //
  908. status = (NDIS_STATUS) SerialSetTimeouts(pThisDev->pSerialDevObj,
  909. &SerialTimeoutsInit);
  910. if (status != NDIS_STATUS_SUCCESS)
  911. {
  912. DEBUGMSG(DBG_ERROR, (" SerialSetTimeouts failed. Returned 0x%.8x\n", status));
  913. status = NDIS_STATUS_FAILURE;
  914. goto done;
  915. }
  916. (void)SerialSetBaudRate(pThisDev->pSerialDevObj, &bitsPerSec);
  917. serialLineControl.StopBits = STOP_BIT_1;
  918. serialLineControl.Parity = NO_PARITY ;
  919. serialLineControl.WordLength = 8;
  920. status = (NDIS_STATUS) SerialSetLineControl(
  921. pThisDev->pSerialDevObj,
  922. &serialLineControl
  923. );
  924. if (status != NDIS_STATUS_SUCCESS)
  925. {
  926. DEBUGMSG(DBG_ERROR, (" SerialSetLineControl failed. Returned 0x%.8x\n", status));
  927. goto done;
  928. }
  929. }
  930. status = SetIrFunctions(pThisDev);
  931. if (status!=STATUS_SUCCESS)
  932. {
  933. goto done;
  934. }
  935. //
  936. // Initialize the dongle.
  937. //
  938. status = (NDIS_STATUS) SerialSetTimeouts(pThisDev->pSerialDevObj,
  939. &SerialTimeoutsInit);
  940. pThisDev->dongle.Initialize(pThisDev->pSerialDevObj);
  941. pThisDev->dongle.QueryCaps(&pThisDev->dongleCaps);
  942. //
  943. // Set the speed of the uart and the dongle.
  944. //
  945. status = (NDIS_STATUS) SetSpeed(pThisDev);
  946. if (status != NDIS_STATUS_SUCCESS)
  947. {
  948. DEBUGMSG(DBG_ERROR, (" SetSpeed failed. Returned 0x%.8x\n", status));
  949. // goto done;
  950. }
  951. serialLineControl.StopBits = STOP_BIT_1;
  952. serialLineControl.Parity = NO_PARITY ;
  953. serialLineControl.WordLength = 8;
  954. status = (NDIS_STATUS) SerialSetLineControl(
  955. pThisDev->pSerialDevObj,
  956. &serialLineControl
  957. );
  958. if (status != NDIS_STATUS_SUCCESS)
  959. {
  960. DEBUGMSG(DBG_ERROR, (" SerialSetLineControl failed. Returned 0x%.8x\n", status));
  961. // goto done;
  962. }
  963. //
  964. // Must set the timeout value of the serial port
  965. // for a read.
  966. //
  967. status = (NDIS_STATUS) SerialSetTimeouts(
  968. pThisDev->pSerialDevObj,
  969. &SerialTimeoutsInit
  970. );
  971. if (status != NDIS_STATUS_SUCCESS)
  972. {
  973. DEBUGMSG(DBG_ERROR, (" SerialSetTimeouts failed. Returned 0x%.8x\n", status));
  974. status = NDIS_STATUS_FAILURE;
  975. // goto done;
  976. }
  977. //
  978. // Initialize receive loop.
  979. //
  980. pThisDev->fPendingReset = FALSE;
  981. status = InitializeReceive(pThisDev);
  982. if (status != NDIS_STATUS_SUCCESS)
  983. {
  984. DEBUGMSG(DBG_ERROR, (" InitializeReceive failed. Returned 0x%.8x\n", status));
  985. status = NDIS_STATUS_FAILURE;
  986. // goto done;
  987. }
  988. done:
  989. DEBUGMSG(DBG_STAT, ("-ResetIrDeviceThread\n"));
  990. pThisDev->fPendingReset = FALSE;
  991. return status;
  992. }
  993. /*****************************************************************************
  994. *
  995. * Function: PassiveLevelThread
  996. *
  997. * Synopsis: Thread running at IRQL PASSIVE_LEVEL.
  998. *
  999. * Arguments:
  1000. *
  1001. * Returns:
  1002. *
  1003. * Algorithm:
  1004. *
  1005. * History: dd-mm-yyyy Author Comment
  1006. * 10/22/1996 sholden author
  1007. *
  1008. * Notes:
  1009. *
  1010. * Any PASSIVE_PRIMITIVE that can be called must be serialized.
  1011. * i.e. when IrsirReset is called, NDIS will not make any other
  1012. * requests of the miniport until NdisMResetComplete is called.
  1013. *
  1014. *****************************************************************************/
  1015. VOID
  1016. PassiveLevelThread(
  1017. IN OUT PVOID Context
  1018. )
  1019. {
  1020. PIR_DEVICE pThisDev;
  1021. NTSTATUS ntStatus;
  1022. PLIST_ENTRY pListEntry;
  1023. PKEVENT EventList[2];
  1024. LARGE_INTEGER Timeout;
  1025. ULONG ulSerialOpenAttempts = 100;
  1026. DEBUGMSG(DBG_FUNC, ("+PassiveLevelThread\n"));
  1027. KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
  1028. pThisDev = CONTEXT_TO_DEV(Context);
  1029. Timeout.QuadPart = -10000 * 1000 * 3; // 3 second relative delay
  1030. EventList[0] = &pThisDev->eventPassiveThread;
  1031. EventList[1] = &pThisDev->eventKillThread;
  1032. while (1) {
  1033. //
  1034. // The eventPassiveThread is an auto-clearing event, so
  1035. // we don't need to reset the event.
  1036. //
  1037. ntStatus = KeWaitForMultipleObjects(2,
  1038. EventList,
  1039. WaitAny,
  1040. Executive,
  1041. KernelMode,
  1042. FALSE,
  1043. (pThisDev->pSerialDevObj ? NULL : &Timeout),
  1044. NULL);
  1045. if (ntStatus==0 || ntStatus==STATUS_TIMEOUT) {
  1046. //
  1047. // either the first event was signaled or a timeout occurred
  1048. //
  1049. if (!pThisDev->pSerialDevObj) {
  1050. //
  1051. // we have not opened the serial driver yet, try again
  1052. //
  1053. ResetIrDevice(pThisDev);
  1054. if ((pThisDev->pSerialDevObj == NULL) && (--ulSerialOpenAttempts == 0)) {
  1055. //
  1056. // still could not open the device, tell ndis to remove it
  1057. //
  1058. NdisMRemoveMiniport(pThisDev->hNdisAdapter);
  1059. }
  1060. }
  1061. while (pListEntry = MyInterlockedRemoveHeadList(&pThisDev->leWorkItems,
  1062. &pThisDev->slWorkItem))
  1063. {
  1064. PIR_WORK_ITEM pWorkItem = CONTAINING_RECORD(pListEntry,
  1065. IR_WORK_ITEM,
  1066. ListEntry);
  1067. pWorkItem->Callback(pWorkItem);
  1068. }
  1069. } else {
  1070. if (ntStatus==1) {
  1071. //
  1072. // the second event was signaled, this means that the thread should exit
  1073. //
  1074. DEBUGMSG(DBG_STAT, (" Thread: HALT\n"));
  1075. // Free any pending requests
  1076. while (pListEntry = MyInterlockedRemoveHeadList(&pThisDev->leWorkItems,
  1077. &pThisDev->slWorkItem))
  1078. {
  1079. PIR_WORK_ITEM pWorkItem = CONTAINING_RECORD(pListEntry,
  1080. IR_WORK_ITEM,
  1081. ListEntry);
  1082. DEBUGMSG(DBG_WARN, ("IRSIR: Releasing work item %08x\n", pWorkItem->Callback));
  1083. FreeWorkItem(pWorkItem);
  1084. }
  1085. ASSERT(pThisDev->fPendingHalt == TRUE);
  1086. //
  1087. // out of loop
  1088. //
  1089. break;
  1090. }
  1091. }
  1092. }
  1093. DEBUGMSG(DBG_FUNC, ("-PassiveLevelThread\n"));
  1094. PsTerminateSystemThread(STATUS_SUCCESS);
  1095. }
  1096. VOID
  1097. StopWorkerThread(
  1098. PIR_DEVICE pThisDev
  1099. )
  1100. {
  1101. PVOID ThreadObject;
  1102. NTSTATUS Status;
  1103. //
  1104. // get an object handle fomr the thread handle
  1105. //
  1106. Status=ObReferenceObjectByHandle(
  1107. pThisDev->hPassiveThread,
  1108. 0,
  1109. NULL,
  1110. KernelMode,
  1111. &ThreadObject,
  1112. NULL
  1113. );
  1114. ASSERT(Status == STATUS_SUCCESS);
  1115. //
  1116. // tell the thread to exit
  1117. //
  1118. KeSetEvent(
  1119. &pThisDev->eventKillThread,
  1120. 0,
  1121. FALSE
  1122. );
  1123. if (NT_SUCCESS(Status)) {
  1124. KeWaitForSingleObject(
  1125. ThreadObject,
  1126. Executive,
  1127. KernelMode,
  1128. FALSE,
  1129. NULL
  1130. );
  1131. ObDereferenceObject(ThreadObject);
  1132. ThreadObject=NULL;
  1133. }
  1134. //
  1135. // close the thread handle
  1136. //
  1137. ZwClose(pThisDev->hPassiveThread);
  1138. pThisDev->hPassiveThread = NULL;
  1139. return;
  1140. }