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.

705 lines
18 KiB

  1. /*++
  2. Module Name:
  3. openclos.c
  4. Environment:
  5. Kernel mode
  6. Revision History :
  7. --*/
  8. #include "precomp.h"
  9. NTSTATUS
  10. MoxaGetPortPropertyFromRegistry(IN PMOXA_DEVICE_EXTENSION extension)
  11. {
  12. NTSTATUS status;
  13. HANDLE keyHandle;
  14. ULONG data=0,dataLen;
  15. extension->RxFifoTrigger = 3; // for 550C UART
  16. extension->TxFifoAmount = 16; // for 550C UART
  17. extension->PortFlag = 0;
  18. status = IoOpenDeviceRegistryKey(extension->Pdo, PLUGPLAY_REGKEY_DEVICE,
  19. STANDARD_RIGHTS_READ, &keyHandle);
  20. if (!NT_SUCCESS(status)) {
  21. //
  22. // This is a fatal error. If we can't get to our registry key,
  23. // we are sunk.
  24. //
  25. return (status);
  26. }
  27. status = MoxaGetRegistryKeyValue(
  28. keyHandle,
  29. L"DisableFiFo",
  30. sizeof(L"DisableFiFo"),
  31. &data,
  32. sizeof(ULONG),
  33. &dataLen);
  34. if (NT_SUCCESS(status)) {
  35. if (data) {
  36. extension->RxFifoTrigger = 0;
  37. extension->TxFifoAmount = 1;
  38. }
  39. }
  40. MoxaKdPrint(MX_DBG_TRACE,
  41. ("TxFifoSize/RxFifoTrig=%x/%x\n", extension->TxFifoAmount ,extension->RxFifoTrigger ));
  42. status = MoxaGetRegistryKeyValue(
  43. keyHandle,
  44. L"TxMode",
  45. sizeof(L"TxMode"),
  46. &data,
  47. sizeof(ULONG),
  48. &dataLen);
  49. if (NT_SUCCESS(status) && data )
  50. extension->PortFlag = NORMAL_TX_MODE;
  51. MoxaKdPrint(MX_DBG_TRACE,
  52. ("TxMode=%x/%x\n", extension->PortFlag ,status));
  53. ZwClose(keyHandle);
  54. return (status);
  55. }
  56. NTSTATUS
  57. MoxaCreateOpen(
  58. IN PDEVICE_OBJECT DeviceObject,
  59. IN PIRP Irp
  60. )
  61. {
  62. PMOXA_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  63. NTSTATUS status;
  64. MoxaKdPrint(MX_DBG_TRACE,("MoxaCreateOpen\n"));
  65. if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Create.Options &
  66. FILE_DIRECTORY_FILE) {
  67. Irp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
  68. Irp->IoStatus.Information = 0;
  69. IoCompleteRequest(
  70. Irp,
  71. IO_NO_INCREMENT
  72. );
  73. MoxaKdPrint(MX_DBG_TRACE,("Is a directory,open failed\n"));
  74. return STATUS_NOT_A_DIRECTORY;
  75. }
  76. if (extension->ControlDevice) {
  77. extension->ErrorWord = 0;
  78. extension->DeviceIsOpened = TRUE;
  79. Irp->IoStatus.Status = STATUS_SUCCESS;
  80. Irp->IoStatus.Information = 0;
  81. IoCompleteRequest(
  82. Irp,
  83. IO_NO_INCREMENT
  84. );
  85. return STATUS_SUCCESS;
  86. }
  87. if (!extension->PortExist) {
  88. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  89. Irp->IoStatus.Information = 0;
  90. IoCompleteRequest(
  91. Irp,
  92. IO_NO_INCREMENT
  93. );
  94. MoxaKdPrint(MX_DBG_TRACE,("No such device,open failed\n"));
  95. return STATUS_NO_SUCH_DEVICE;
  96. }
  97. if (extension->PNPState != SERIAL_PNP_STARTED) {
  98. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  99. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  100. MoxaKdPrint(MX_DBG_TRACE,("Device is not started,open failed\n"));
  101. return STATUS_INSUFFICIENT_RESOURCES;
  102. }
  103. //
  104. // Lock out changes to PnP state until we have our open state decided
  105. //
  106. ExAcquireFastMutex(&extension->OpenMutex);
  107. if ((status = MoxaIRPPrologue(Irp, extension)) != STATUS_SUCCESS) {
  108. ExReleaseFastMutex(&extension->OpenMutex);
  109. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  110. MoxaKdPrint(MX_DBG_TRACE,("MoxaIRPPrologue status=%x,open failed\n",status));
  111. return status;
  112. }
  113. if (InterlockedIncrement(&extension->OpenCount) != 1) {
  114. ExReleaseFastMutex(&extension->OpenMutex);
  115. InterlockedDecrement(&extension->OpenCount);
  116. Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
  117. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  118. MoxaKdPrint(MX_DBG_TRACE,("Open count greater than 1,open failed\n",status));
  119. return STATUS_ACCESS_DENIED;
  120. }
  121. //
  122. // Ok, it looks like we really are going to open. Lock down the
  123. // driver.
  124. //
  125. // MoxaLockPagableSectionByHandle(MoxaGlobalsData->PAGESER_Handle);
  126. //
  127. // Retreive the properties of port
  128. //
  129. MoxaGetPortPropertyFromRegistry(extension);
  130. //
  131. // Power up the stack
  132. //
  133. // (void)MoxaGotoPowerState(DeviceObject, extension, PowerDeviceD0);
  134. if ((extension->PowerState != PowerDeviceD0)||
  135. (MoxaGlobalData->BoardReady[extension->BoardNo] == FALSE)) {
  136. MoxaKdPrint(MX_DBG_TRACE,("Board is not ready,open failed\n"));
  137. ExReleaseFastMutex(&extension->OpenMutex);
  138. InterlockedDecrement(&extension->OpenCount);
  139. Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
  140. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  141. return STATUS_ACCESS_DENIED;
  142. }
  143. MoxaKdPrint(MX_DBG_TRACE,("Device Opened,TxFiFo=%d,RxFiFo=%d,PortFlag=%x\n",
  144. extension->TxFifoAmount,extension->RxFifoTrigger,extension->PortFlag));
  145. //
  146. // Not currently waiting for wake up
  147. //
  148. extension->SendWaitWake = FALSE;
  149. extension->HandFlow.XoffLimit = extension->RxBufferSize >> 3;
  150. extension->HandFlow.XonLimit = extension->RxBufferSize >> 1;
  151. extension->BufferSizePt8 = ((3*(extension->RxBufferSize>>2))+
  152. (extension->RxBufferSize>>4));
  153. extension->WriteLength = 0;
  154. extension->ReadLength = 0;
  155. extension->TotalCharsQueued = 0;
  156. extension->IrpMaskLocation = NULL;
  157. extension->HistoryMask = 0;
  158. extension->IsrWaitMask = 0;
  159. extension->WmiCommData.XoffXmitThreshold = extension->HandFlow.XoffLimit;
  160. extension->WmiCommData.XonXmitThreshold = extension->HandFlow.XonLimit;
  161. //
  162. // Clear out the statistics.
  163. //
  164. KeSynchronizeExecution(
  165. extension->Interrupt,
  166. MoxaClearStats,
  167. extension
  168. );
  169. extension->EscapeChar = 0;
  170. extension->ErrorWord = 0;
  171. MoxaReset(extension);
  172. MoxaFuncWithLock(extension, FC_SetTxFIFOCnt, extension->TxFifoAmount);
  173. MoxaFuncWithLock(extension, FC_SetRxFIFOTrig,extension->RxFifoTrigger);
  174. MoxaFuncWithLock(extension, FC_EnableCH, Magic_code);
  175. /* 6-1-1998 by William */
  176. /* 4-26-99 by William */
  177. MoxaFuncWithLock(extension, FC_SetLineIrq,Magic_code);
  178. /* 5-31-1998 by William
  179. MoxaFuncWithLock(extension, FC_GetAll, 0);
  180. extension->ModemStatus = *(PUSHORT)(extension->PortOfs + FuncArg + 2);
  181. */
  182. extension->ModemStatus = *(PUSHORT)(extension->PortOfs + FlagStat) >> 4;
  183. Irp->IoStatus.Status = STATUS_SUCCESS;
  184. Irp->IoStatus.Information = 0L;
  185. extension->DeviceIsOpened = TRUE;
  186. //
  187. // Mark the device as busy for WMI
  188. //
  189. extension->WmiCommData.IsBusy = TRUE;
  190. //
  191. // 7-20-01 by William
  192. //
  193. MoxaAddTimeOutProc(extension);
  194. ExReleaseFastMutex(&extension->OpenMutex);
  195. MoxaCompleteRequest(
  196. extension,
  197. Irp,
  198. IO_NO_INCREMENT
  199. );
  200. return STATUS_SUCCESS;
  201. }
  202. VOID
  203. MoxaReset(
  204. IN PMOXA_DEVICE_EXTENSION Extension
  205. )
  206. {
  207. SHORT divisor;
  208. PUCHAR ofs;
  209. MOXA_IOCTL_SYNC S;
  210. ofs = Extension->PortOfs;
  211. MoxaKdPrint (MX_DBG_TRACE, ("Enter MoxaReset\n"));
  212. MoxaFuncWithLock(Extension, FC_ChannelReset, Magic_code);
  213. MoxaFuncWithLock(Extension, FC_SetDataMode, Extension->DataMode);
  214. MoxaGetDivisorFromBaud(
  215. Extension->ClockType,
  216. Extension->CurrentBaud,
  217. &divisor
  218. );
  219. MoxaFuncWithLock(Extension, FC_SetBaud, divisor);
  220. S.Extension = Extension;
  221. S.Data = &Extension->HandFlow;
  222. MoxaSetupNewHandFlow(
  223. &S
  224. );
  225. *(PUSHORT)(ofs + Tx_trigger) = (USHORT)MoxaTxLowWater;
  226. }
  227. NTSTATUS
  228. MoxaClose(
  229. IN PDEVICE_OBJECT DeviceObject,
  230. IN PIRP Irp
  231. )
  232. {
  233. PMOXA_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  234. LARGE_INTEGER allSentDelay;
  235. LARGE_INTEGER charTime;
  236. PUCHAR ofs;
  237. LONG count,count1;
  238. ULONG openCount,pendingDPCs;
  239. NTSTATUS status;
  240. // MoxaKdPrint(MX_DBG_TRACE,("%ws,Closing ...\n",extension->DosName));
  241. if (extension->ControlDevice) {
  242. MoxaKdPrint(MX_DBG_TRACE,("Control Device Closed\n"));
  243. Irp->IoStatus.Status = STATUS_SUCCESS;
  244. Irp->IoStatus.Information=0L;
  245. extension->DeviceIsOpened = FALSE;
  246. IoCompleteRequest(
  247. Irp,
  248. IO_NO_INCREMENT
  249. );
  250. return STATUS_SUCCESS;
  251. }
  252. //
  253. // Grab a mutex
  254. //
  255. ExAcquireFastMutex(&extension->CloseMutex);
  256. //
  257. // We succeed a close on a removing device
  258. //
  259. //
  260. // 7-20-01 by William
  261. //
  262. MoxaDelTimeOutProc(extension);
  263. if ((status = MoxaIRPPrologue(Irp, extension)) != STATUS_SUCCESS) {
  264. MoxaKdPrint (MX_DBG_ERROR,("Close prologue failed for: %x\n",Irp));
  265. if (status == STATUS_DELETE_PENDING) {
  266. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  267. }
  268. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  269. openCount = InterlockedDecrement(&extension->OpenCount);
  270. // ASSERT(openCount == 0);
  271. ExReleaseFastMutex(&extension->CloseMutex);
  272. return status;
  273. }
  274. //ASSERT(extension->OpenCount == 1);
  275. if (extension->OpenCount != 1) {
  276. MoxaKdPrint (MX_DBG_ERROR,("Close open count bad for: 0x%x\n",Irp));
  277. MoxaKdPrint (MX_DBG_ERROR,("------: Count: %x Addr: 0x%x\n",
  278. extension->OpenCount, &extension->OpenCount));
  279. ExReleaseFastMutex(&extension->CloseMutex);
  280. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  281. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  282. return STATUS_INVALID_DEVICE_REQUEST;
  283. }
  284. charTime = RtlLargeIntegerNegate(MoxaGetCharTime(extension));
  285. extension->DeviceIsOpened = FALSE;
  286. //
  287. // Mark device as not busy for WMI
  288. //
  289. extension->WmiCommData.IsBusy = FALSE;
  290. ofs = extension->PortOfs;
  291. if (extension->SendBreak) {
  292. MoxaFuncWithLock(extension, FC_StopBreak, Magic_code);
  293. extension->SendBreak = FALSE;
  294. }
  295. if (*(ofs + FlagStat) & Rx_xoff)
  296. MoxaFuncWithLock(extension, FC_SendXon, 0);
  297. /* 7-21-99 by William
  298. count = GetDeviceTxQueueWithLock(extension);
  299. count += extension->TotalCharsQueued;
  300. //
  301. // Wait data all sent
  302. //
  303. count += 10;
  304. allSentDelay = RtlExtendedIntegerMultiply(
  305. charTime,
  306. count
  307. );
  308. KeDelayExecutionThread(
  309. KernelMode,
  310. TRUE,
  311. &allSentDelay
  312. );
  313. */
  314. //
  315. // Wait data all sent
  316. //
  317. count1 = 0;
  318. while (TRUE) {
  319. count = GetDeviceTxQueueWithLock(extension);
  320. count += extension->TotalCharsQueued;
  321. if (count == count1)
  322. break;
  323. else
  324. count1 = count;
  325. allSentDelay = RtlExtendedIntegerMultiply(
  326. charTime,
  327. count + 10
  328. );
  329. KeDelayExecutionThread(
  330. KernelMode,
  331. TRUE,
  332. &allSentDelay
  333. );
  334. }
  335. MoxaFuncWithLock(extension, FC_SetFlowCtl, 0);
  336. MoxaFuncWithLock(extension, FC_DTRcontrol, 0); /* clear DTR */
  337. MoxaFuncWithLock(extension, FC_RTScontrol, 0); /* clear RTS */
  338. MoxaFuncWithLock(extension, FC_ClrLineIrq, Magic_code);
  339. MoxaFlagBit[extension->PortNo] &= 0xFC;
  340. *(PUSHORT)(ofs + HostStat) = 0;
  341. MoxaFuncWithLock(extension, FC_DisableCH, Magic_code);
  342. //
  343. // Stop waiting for wakeup
  344. //
  345. extension->SendWaitWake = FALSE;
  346. if (extension->PendingWakeIrp != NULL) {
  347. IoCancelIrp(extension->PendingWakeIrp);
  348. }
  349. //
  350. // Power down our device stack
  351. //
  352. // (void)MoxaGotoPowerState(DeviceObject, extension, PowerDeviceD3);
  353. Irp->IoStatus.Status = STATUS_SUCCESS;
  354. Irp->IoStatus.Information=0L;
  355. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  356. //
  357. // Unlock the pages. If this is the last reference to the section
  358. // then the driver code will be flushed out.
  359. //
  360. //
  361. // First, we have to let the DPC's drain. No more should be queued
  362. // since we aren't taking interrupts now....
  363. //
  364. pendingDPCs = InterlockedDecrement(&extension->DpcCount);
  365. if (pendingDPCs) {
  366. MoxaKdPrint(MX_DBG_TRACE,("DpcCount = %d\n",extension->DpcCount));
  367. MoxaKdPrint(MX_DBG_TRACE,("Drainging DPC's: %x\n",Irp));
  368. KeWaitForSingleObject(&extension->PendingDpcEvent, Executive,
  369. KernelMode, FALSE, NULL);
  370. }
  371. //
  372. // Pages must be locked to release the mutex, so don't unlock
  373. // them until after we release the mutex
  374. //
  375. ExReleaseFastMutex(&extension->CloseMutex);
  376. //
  377. // Reset for next open
  378. //
  379. InterlockedIncrement(&extension->DpcCount);
  380. openCount = InterlockedDecrement(&extension->OpenCount);
  381. //ASSERT(openCount == 0);
  382. // MoxaKdPrint(MX_DBG_TRACE,("%ws,close completed.\n",extension->DosName));
  383. // MoxaUnlockPagableImageSection(MoxaGlobalsData->PAGESER_Handle);
  384. return STATUS_SUCCESS;
  385. }
  386. LARGE_INTEGER
  387. MoxaGetCharTime(
  388. IN PMOXA_DEVICE_EXTENSION Extension
  389. )
  390. {
  391. ULONG dataSize;
  392. ULONG paritySize;
  393. ULONG stopSize;
  394. ULONG charTime;
  395. ULONG bitTime;
  396. if ((Extension->DataMode & MOXA_DATA_MASK)
  397. == MOXA_5_DATA) {
  398. dataSize = 5;
  399. } else if ((Extension->DataMode & MOXA_DATA_MASK)
  400. == MOXA_6_DATA) {
  401. dataSize = 6;
  402. } else if ((Extension->DataMode & MOXA_DATA_MASK)
  403. == MOXA_7_DATA) {
  404. dataSize = 7;
  405. } else if ((Extension->DataMode & MOXA_DATA_MASK)
  406. == MOXA_8_DATA) {
  407. dataSize = 8;
  408. } else {
  409. dataSize = 8;
  410. }
  411. paritySize = 1;
  412. if ((Extension->DataMode & MOXA_PARITY_MASK)
  413. == MOXA_NONE_PARITY) {
  414. paritySize = 0;
  415. }
  416. if (Extension->DataMode & MOXA_STOP_MASK) {
  417. //
  418. // Even if it is 1.5, for sanities sake were going
  419. // to say 2.
  420. //
  421. stopSize = 2;
  422. } else {
  423. stopSize = 1;
  424. }
  425. //
  426. // First we calculate the number of 100 nanosecond intervals
  427. // are in a single bit time (Approximately).
  428. //
  429. bitTime = (10000000+(Extension->CurrentBaud-1))/Extension->CurrentBaud;
  430. charTime = bitTime + ((dataSize+paritySize+stopSize)*bitTime);
  431. return RtlConvertUlongToLargeInteger(charTime);
  432. }
  433. NTSTATUS
  434. MoxaCleanup(
  435. IN PDEVICE_OBJECT DeviceObject,
  436. IN PIRP Irp
  437. )
  438. {
  439. PMOXA_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  440. KIRQL oldIrql;
  441. NTSTATUS status;
  442. if ((!extension->ControlDevice)&&(extension->DeviceIsOpened == TRUE)) {
  443. //
  444. // We succeed a cleanup on a removing device
  445. //
  446. if ((status = MoxaIRPPrologue(Irp, extension)) != STATUS_SUCCESS) {
  447. if (status == STATUS_DELETE_PENDING) {
  448. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  449. }
  450. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  451. return status;
  452. }
  453. //
  454. // First kill all the reads and writes.
  455. //
  456. MoxaKillAllReadsOrWrites(
  457. DeviceObject,
  458. &extension->WriteQueue,
  459. &extension->CurrentWriteIrp
  460. );
  461. MoxaKillAllReadsOrWrites(
  462. DeviceObject,
  463. &extension->ReadQueue,
  464. &extension->CurrentReadIrp
  465. );
  466. //
  467. // Next get rid of purges.
  468. //
  469. MoxaKillAllReadsOrWrites(
  470. DeviceObject,
  471. &extension->PurgeQueue,
  472. &extension->CurrentPurgeIrp
  473. );
  474. //
  475. // Get rid of any mask operations.
  476. //
  477. MoxaKillAllReadsOrWrites(
  478. DeviceObject,
  479. &extension->MaskQueue,
  480. &extension->CurrentMaskIrp
  481. );
  482. //
  483. // Now get rid a pending wait mask irp.
  484. //
  485. IoAcquireCancelSpinLock(&oldIrql);
  486. if (extension->CurrentWaitIrp) {
  487. PDRIVER_CANCEL cancelRoutine;
  488. cancelRoutine = extension->CurrentWaitIrp->CancelRoutine;
  489. extension->CurrentWaitIrp->Cancel = TRUE;
  490. if (cancelRoutine) {
  491. extension->CurrentWaitIrp->CancelIrql = oldIrql;
  492. extension->CurrentWaitIrp->CancelRoutine = NULL;
  493. cancelRoutine(
  494. DeviceObject,
  495. extension->CurrentWaitIrp
  496. );
  497. }
  498. /* 8-30-01 by William */
  499. else
  500. IoReleaseCancelSpinLock(oldIrql);
  501. }
  502. else
  503. IoReleaseCancelSpinLock(oldIrql);
  504. Irp->IoStatus.Status = STATUS_SUCCESS;
  505. Irp->IoStatus.Information=0L;
  506. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  507. }
  508. else {
  509. Irp->IoStatus.Status = STATUS_SUCCESS;
  510. Irp->IoStatus.Information=0L;
  511. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  512. }
  513. return STATUS_SUCCESS;
  514. }