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.

2077 lines
63 KiB

  1. /*----------------------------------------------------------------------
  2. pnp.c -
  3. 4-18-00 Remove IoStartNextPacket call from PnPBoardFDO function
  4. 4-06-00 Reject irps for query_device_relations if not a bus_relation request
  5. 3-30-99 fix hybernate power on to restore dtr/rts states
  6. properly, in RestorePortSettings().
  7. 2-15-99 - allow to hibernate with open ports, restore ports when
  8. comes back up now - kpb.
  9. 11-24-98 - fix power handling to avoid crash,
  10. allow hibernation if no ports open. kpb
  11. ----------------------------------------------------------------------*/
  12. #include "precomp.h"
  13. #ifdef NT50
  14. NTSTATUS PnPBoardFDO(IN PDEVICE_OBJECT devobj, IN PIRP Irp);
  15. NTSTATUS PnPPortFDO(IN PDEVICE_OBJECT devobj, IN PIRP Irp);
  16. NTSTATUS PnpPortPDO(IN PDEVICE_OBJECT devobj, IN PIRP Irp);
  17. NTSTATUS BoardBusRelations(IN PDEVICE_OBJECT devobj, IN PIRP Irp);
  18. NTSTATUS WaitForLowerPdo(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
  19. NTSTATUS BoardFilterResReq(IN PDEVICE_OBJECT devobj, IN PIRP Irp);
  20. NTSTATUS SerialRemoveFdo(IN PDEVICE_OBJECT pFdo);
  21. NTSTATUS SerialIoCallDriver(PSERIAL_DEVICE_EXTENSION PDevExt,
  22. PDEVICE_OBJECT PDevObj,
  23. PIRP PIrp);
  24. NTSTATUS Serial_PDO_Power (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  25. NTSTATUS Serial_FDO_Power (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  26. NTSTATUS PowerUpDevice(PSERIAL_DEVICE_EXTENSION Ext);
  27. void RestorePortSettings(PSERIAL_DEVICE_EXTENSION Ext);
  28. //NTSTATUS SerialPoCallDriver(PSERIAL_DEVICE_EXTENSION PDevExt,
  29. // PDEVICE_OBJECT PDevObj,
  30. // PIRP PIrp);
  31. //NTSTATUS SerialSetPowerD0(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  32. NTSTATUS OurPowerCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
  33. NTSTATUS SerialD3Complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
  34. NTSTATUS SerialStartDevice(
  35. IN PDEVICE_OBJECT Fdo,
  36. IN PIRP Irp);
  37. NTSTATUS SerialSyncCompletion(
  38. IN PDEVICE_OBJECT DeviceObject,
  39. IN PIRP Irp,
  40. IN PKEVENT SerialSyncEvent
  41. );
  42. NTSTATUS SerialFinishStartDevice(IN PDEVICE_OBJECT Fdo,
  43. IN PCM_RESOURCE_LIST resourceList,
  44. IN PCM_RESOURCE_LIST trResourceList);
  45. static NTSTATUS RocketPortSpecialStartup(PSERIAL_DEVICE_EXTENSION Ext);
  46. #if DBG
  47. static char *power_strs[] = {
  48. "WAIT_WAKE", // 0x00
  49. "POWER_SEQUENCE", // 0x01
  50. "SET_POWER", // 0x02
  51. "QUERY_POWER", // 0x03
  52. "UNKNOWN", //
  53. NULL};
  54. static char *pnp_strs[] = {
  55. "START_DEVICE", // 0x00
  56. "QUERY_REMOVE_DEVICE", // 0x01
  57. "REMOVE_DEVICE", // 0x02
  58. "CANCEL_REMOVE_DEVICE", // 0x03
  59. "STOP_DEVICE", // 0x04
  60. "QUERY_STOP_DEVICE", // 0x05
  61. "CANCEL_STOP_DEVICE", // 0x06
  62. "QUERY_DEVICE_RELATIONS", // 0x07
  63. "QUERY_INTERFACE", // 0x08
  64. "QUERY_CAPABILITIES", // 0x09
  65. "QUERY_RESOURCES", // 0x0A
  66. "QUERY_RESOURCE_REQUIREMENTS", // 0x0B
  67. "QUERY_DEVICE_TEXT", // 0x0C
  68. "FILTER_RESOURCE_REQUIREMENTS", // 0x0D
  69. "UNKNOWN", //
  70. "READ_CONFIG", // 0x0F
  71. "WRITE_CONFIG", // 0x10
  72. "EJECT", // 0x11
  73. "SET_LOCK", // 0x12
  74. "QUERY_ID", // 0x13
  75. "QUERY_PNP_DEVICE_STATE", // 0x14
  76. "QUERY_BUS_INFORMATION", // 0x15
  77. "PAGING_NOTIFICATION", // 0x16
  78. NULL};
  79. #endif
  80. /*----------------------------------------------------------------------
  81. SerialPnpDispatch -
  82. This is a dispatch routine for the IRPs that come to the driver with the
  83. IRP_MJ_PNP major code (plug-and-play IRPs).
  84. |----------------------------------------------------------------------*/
  85. NTSTATUS SerialPnpDispatch(IN PDEVICE_OBJECT devobj, IN PIRP Irp)
  86. {
  87. PSERIAL_DEVICE_EXTENSION Ext = devobj->DeviceExtension;
  88. //PDEVICE_OBJECT pdo = Ext->LowerDeviceObject;
  89. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  90. NTSTATUS status = STATUS_NOT_SUPPORTED;
  91. BOOLEAN acceptingIRPs;
  92. int index;
  93. // dump out some debug info
  94. index = irpStack->MinorFunction;
  95. if (index > 0x16)
  96. index = 0x0e;
  97. #ifdef DO_BUS_EXTENDER
  98. if (Ext->IsPDO)
  99. {
  100. MyKdPrint(D_Pnp,("Port PDO %s PnPIrp:%d,%s\n",
  101. Ext->SymbolicLinkName, irpStack->MinorFunction,
  102. pnp_strs[index]))
  103. InterlockedIncrement(&Ext->PendingIRPCnt);
  104. return PnpPortPDO(devobj, Irp);
  105. }
  106. else
  107. #endif
  108. {
  109. if (Ext->DeviceType == DEV_BOARD)
  110. {
  111. MyKdPrint(D_Pnp,("Board %s PnPIrp:%d,%s\n",
  112. Ext->SymbolicLinkName, irpStack->MinorFunction,
  113. pnp_strs[index]))
  114. }
  115. else
  116. {
  117. MyKdPrint(D_Pnp,("Port %s PnPIrp:%d,%s\n",
  118. Ext->SymbolicLinkName, irpStack->MinorFunction,
  119. pnp_strs[index]))
  120. }
  121. acceptingIRPs = SerialIRPPrologue(Ext);
  122. #if 0
  123. if ((irpStack->MinorFunction != IRP_MN_REMOVE_DEVICE)
  124. && (irpStack->MinorFunction != IRP_MN_CANCEL_REMOVE_DEVICE)
  125. && (irpStack->MinorFunction != IRP_MN_STOP_DEVICE)
  126. && (irpStack->MinorFunction != IRP_MN_CANCEL_STOP_DEVICE)
  127. && (acceptingIRPs == FALSE))
  128. {
  129. MyKdPrint(D_Pnp,("Removed!\n"))
  130. Irp->IoStatus.Information = 0;
  131. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  132. SerialCompleteRequest(Ext, Irp, IO_NO_INCREMENT);
  133. return STATUS_NO_SUCH_DEVICE;
  134. }
  135. #endif
  136. if (Ext->DeviceType == DEV_BOARD)
  137. {
  138. return PnPBoardFDO(devobj, Irp);
  139. }
  140. else
  141. {
  142. //return PnPPortFDO(devobj, Irp);
  143. return PnPBoardFDO(devobj, Irp);
  144. }
  145. }
  146. }
  147. /*----------------------------------------------------------------------
  148. PnPBoardFDO - This handles both Board and Port FDO's
  149. |----------------------------------------------------------------------*/
  150. NTSTATUS PnPBoardFDO(IN PDEVICE_OBJECT devobj, IN PIRP Irp)
  151. {
  152. PSERIAL_DEVICE_EXTENSION Ext = devobj->DeviceExtension;
  153. PDEVICE_OBJECT pdo = Ext->LowerDeviceObject;
  154. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  155. NTSTATUS status = STATUS_NOT_SUPPORTED;
  156. ULONG pendingIRPs;
  157. int pass_down = 1;
  158. ASSERT( devobj );
  159. ASSERT( Ext );
  160. #if DBG
  161. if (* ((BYTE *)(Irp)) != 6) // in signiture of irp
  162. {
  163. MyKdPrint(D_Pnp,("bad irp!!!\n"))
  164. }
  165. #endif
  166. switch (irpStack->MinorFunction)
  167. {
  168. case IRP_MN_START_DEVICE: // 0x00
  169. MyKdPrint(D_Pnp,("StartDevice\n"))
  170. status = SerialStartDevice(devobj, Irp);
  171. //
  172. // Is this were we should register and enable the device, or should it be in
  173. // the PDO start? (see DoPnpAssoc(Pdo) in pnpadd.c)
  174. //
  175. Irp->IoStatus.Status = status;
  176. pass_down = 0; // already passed down
  177. break;
  178. case IRP_MN_STOP_DEVICE: // 0x04
  179. // need to unhook from resources so system rebalance resources
  180. // on the fly.
  181. MyKdPrint(D_Pnp,("StopDevice\n"))
  182. //Ext->Flags |= SERIAL_FLAGS_STOPPED;
  183. Ext->PNPState = SERIAL_PNP_STOPPING;
  184. Ext->DevicePNPAccept |= SERIAL_PNPACCEPT_STOPPED;
  185. Ext->DevicePNPAccept &= ~SERIAL_PNPACCEPT_STOPPING;
  186. InterlockedDecrement(&Ext->PendingIRPCnt); // after dec, =1
  187. pendingIRPs = InterlockedDecrement(&Ext->PendingIRPCnt); // after dec, =0
  188. if (pendingIRPs) {
  189. KeWaitForSingleObject(&Ext->PendingIRPEvent, Executive,
  190. KernelMode, FALSE, NULL);
  191. }
  192. Ext->FdoStarted = FALSE; // this should stop service of the device
  193. #ifdef NT50
  194. if (Ext->DeviceType != DEV_BOARD) {
  195. // Disable the interface
  196. status = IoSetDeviceInterfaceState( &Ext->DeviceClassSymbolicName,
  197. FALSE);
  198. if (!NT_SUCCESS(status)) {
  199. MyKdPrint(D_Error,("Couldn't clear class association for %s\n",
  200. UToC1(&Ext->DeviceClassSymbolicName)))
  201. }
  202. else {
  203. MyKdPrint(D_PnpAdd, ("Cleared class association for device: %s\n and ",
  204. UToC1(&Ext->DeviceClassSymbolicName)))
  205. }
  206. }
  207. #endif
  208. // Re-increment the count for exit
  209. InterlockedIncrement(&Ext->PendingIRPCnt); //after inc=1
  210. InterlockedIncrement(&Ext->PendingIRPCnt); //after inc=2
  211. // exit this irp decr it to=1
  212. status = STATUS_SUCCESS;
  213. Irp->IoStatus.Status = STATUS_SUCCESS;
  214. //Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  215. //pass_down = 0; // we are failing it
  216. break;
  217. #if 0
  218. case IRP_MN_QUERY_DEVICE_RELATIONS: // 0x7
  219. if ( irpStack->Parameters.QueryDeviceRelations.Type != BusRelations )
  220. {
  221. //
  222. // Verifier requires pass down is PDO present
  223. //
  224. if ( (Ext->DeviceType == DEV_BOARD) && (pdo == 0) )
  225. {
  226. status = STATUS_NOT_IMPLEMENTED;
  227. pass_down = 0;
  228. };
  229. break;
  230. }
  231. if (!Driver.NoPnpPorts)
  232. {
  233. if (Ext->DeviceType == DEV_BOARD)
  234. {
  235. status = BoardBusRelations(devobj, Irp);
  236. }
  237. }
  238. break;
  239. #endif
  240. #ifdef DO_BUS_EXTENDER
  241. case IRP_MN_QUERY_DEVICE_RELATIONS: // 0x7
  242. //
  243. // Verifier requires pass down is PDO present
  244. //
  245. if ( (Ext->DeviceType == DEV_BOARD) && (pdo == 0) )
  246. {
  247. pass_down = 0;
  248. }
  249. if ( irpStack->Parameters.QueryDeviceRelations.Type != BusRelations ) {
  250. status = STATUS_NOT_IMPLEMENTED;
  251. break;
  252. }
  253. if (!Driver.NoPnpPorts)
  254. {
  255. if (Ext->DeviceType == DEV_BOARD)
  256. {
  257. status = BoardBusRelations(devobj, Irp);
  258. }
  259. }
  260. break;
  261. #endif
  262. #ifdef DO_BRD_FILTER_RES_REQ
  263. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: // 0x0D
  264. if (Ext->DeviceType == DEV_BOARD)
  265. {
  266. status = BoardFilterResReq(devobj, Irp);
  267. pass_down = 0; // already passed down
  268. }
  269. break;
  270. #endif
  271. case IRP_MN_QUERY_STOP_DEVICE: // 0x05
  272. MyKdPrint(D_Pnp,("QueryStopDevice\n"))
  273. status = STATUS_SUCCESS;
  274. if (Ext->DeviceType == DEV_BOARD)
  275. {
  276. if (is_board_in_use(Ext))
  277. status = STATUS_DEVICE_BUSY;
  278. }
  279. else
  280. {
  281. if (Ext->DeviceIsOpen)
  282. status = STATUS_DEVICE_BUSY;
  283. }
  284. if (status == STATUS_DEVICE_BUSY)
  285. {
  286. MyKdPrint(D_Pnp,("Can't Remove, Busy\n"))
  287. Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
  288. pass_down = 0; // we are failing it out, no need to pass down
  289. }
  290. else
  291. {
  292. Ext->PNPState = SERIAL_PNP_QSTOP;
  293. // this is hosing up things(kpb)
  294. //Ext->DevicePNPAccept |= SERIAL_PNPACCEPT_STOPPING;
  295. Irp->IoStatus.Status = STATUS_SUCCESS;
  296. status = STATUS_SUCCESS;
  297. }
  298. break;
  299. case IRP_MN_CANCEL_STOP_DEVICE: // 0x06
  300. MyKdPrint(D_Pnp,("CancelStopDevice\n"))
  301. if (Ext->PNPState == SERIAL_PNP_QSTOP)
  302. {
  303. Ext->PNPState = SERIAL_PNP_STARTED;
  304. Ext->DevicePNPAccept &= ~SERIAL_PNPACCEPT_STOPPING;
  305. }
  306. Irp->IoStatus.Status = STATUS_SUCCESS;
  307. status = STATUS_SUCCESS;
  308. break;
  309. case IRP_MN_CANCEL_REMOVE_DEVICE:
  310. MyKdPrint(D_Pnp,("CancelRemoveDevice\n"))
  311. // Restore the device state
  312. Ext->PNPState = SERIAL_PNP_STARTED;
  313. Ext->DevicePNPAccept &= ~SERIAL_PNPACCEPT_REMOVING;
  314. Irp->IoStatus.Status = STATUS_SUCCESS;
  315. status = STATUS_SUCCESS;
  316. break;
  317. case IRP_MN_QUERY_REMOVE_DEVICE: // 0x01
  318. // If we were to fail this call then we would need to complete the
  319. // IRP here. Since we are not, set the status to SUCCESS and
  320. // call the next driver.
  321. MyKdPrint(D_Pnp,("QueryRemoveDevice\n"))
  322. status = STATUS_SUCCESS;
  323. if (Ext->DeviceType == DEV_BOARD)
  324. {
  325. if (is_board_in_use(Ext))
  326. status = STATUS_DEVICE_BUSY;
  327. }
  328. else
  329. {
  330. if (Ext->DeviceIsOpen)
  331. status = STATUS_DEVICE_BUSY;
  332. }
  333. if (status == STATUS_DEVICE_BUSY)
  334. {
  335. MyKdPrint(D_Pnp,("Can't Remove, Busy\n"))
  336. Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
  337. pass_down = 0; // we are failing it out, no need to pass down
  338. }
  339. else
  340. {
  341. Ext->PNPState = SERIAL_PNP_QREMOVE;
  342. Ext->DevicePNPAccept |= SERIAL_PNPACCEPT_REMOVING;
  343. Irp->IoStatus.Status = STATUS_SUCCESS;
  344. status = STATUS_SUCCESS;
  345. }
  346. break;
  347. case IRP_MN_REMOVE_DEVICE: // 0x02
  348. // If we get this, we have to remove
  349. // Mark as not accepting requests
  350. Ext->DevicePNPAccept |= SERIAL_PNPACCEPT_REMOVING;
  351. // Complete all pending requests
  352. SerialKillPendingIrps(devobj);
  353. // Pass the irp down
  354. //WaitForLowerPdo(devobj, Irp);
  355. Irp->IoStatus.Status = STATUS_SUCCESS;
  356. MyKdPrint(D_Pnp,("RemoveDevice\n"))
  357. IoSkipCurrentIrpStackLocation (Irp);
  358. //IoCopyCurrentIrpStackLocationToNext(Irp);
  359. // We do decrement here because we incremented on entry here.
  360. //SerialIRPEpilogue(Ext);
  361. SerialIoCallDriver(Ext, pdo, Irp);
  362. // Wait for any pending requests we raced on.
  363. pendingIRPs = InterlockedDecrement(&Ext->PendingIRPCnt);
  364. MyKdPrint(D_Pnp,("Remove, C\n"))
  365. if (pendingIRPs) {
  366. MyKdPrint(D_Pnp,("Irp Wait\n"))
  367. KeWaitForSingleObject(&Ext->PendingIRPEvent, Executive,
  368. KernelMode, FALSE, NULL);
  369. }
  370. // Remove us
  371. SerialRemoveFdo(devobj);
  372. status = STATUS_SUCCESS;
  373. // MyKdPrint(D_Pnp,("End PnPDispatch(Remove)\n"))
  374. return status; // BAIL
  375. case IRP_MN_QUERY_INTERFACE: // 0x8
  376. case IRP_MN_QUERY_RESOURCES : // 0x0A
  377. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: // 0x0B
  378. case IRP_MN_READ_CONFIG: // 0x0f
  379. case IRP_MN_WRITE_CONFIG: // 0x10
  380. case IRP_MN_EJECT: // 0x11
  381. case IRP_MN_SET_LOCK: // 0x12
  382. //case IRP_MN_PNP_DEVICE_STATE: // 0x14
  383. case IRP_MN_QUERY_BUS_INFORMATION: // 0x15
  384. //case IRP_MN_PAGING_NOTIFICATION: // 0x16
  385. default:
  386. MyKdPrint(D_Pnp,("Unhandled\n"));
  387. // all these get passed down, we don't set the status return code
  388. break;
  389. } // switch (irpStack->MinorFunction)
  390. #if DBG
  391. if (* ((BYTE *)(Irp)) != 6) // in signiture of irp
  392. {
  393. MyKdPrint(D_Pnp,("bad irp b!!!\n"))
  394. }
  395. #endif
  396. if (pass_down)
  397. {
  398. MyKdPrint(D_Pnp,(" Send irp down\n"))
  399. // Pass to driver beneath us
  400. IoSkipCurrentIrpStackLocation(Irp);
  401. status = SerialIoCallDriver(Ext, pdo, Irp);
  402. }
  403. else
  404. {
  405. Irp->IoStatus.Status = status;
  406. //MyKdPrint(D_Pnp,(" Complete irp\n"))
  407. SerialCompleteRequest(Ext, Irp, IO_NO_INCREMENT);
  408. }
  409. // MyKdPrint(D_Pnp,(" End PnPDispatch\n"))
  410. return status;
  411. }
  412. #ifdef DO_BUS_EXTENDER
  413. /*----------------------------------------------------------------------
  414. PnpPortPDO -
  415. |----------------------------------------------------------------------*/
  416. NTSTATUS PnpPortPDO(IN PDEVICE_OBJECT devobj, IN PIRP Irp)
  417. {
  418. PSERIAL_DEVICE_EXTENSION Ext = devobj->DeviceExtension;
  419. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  420. NTSTATUS status = Irp->IoStatus.Status;
  421. switch (irpStack->MinorFunction)
  422. {
  423. case IRP_MN_START_DEVICE: // 0x00
  424. status = STATUS_SUCCESS;
  425. break;
  426. case IRP_MN_STOP_DEVICE:
  427. status = STATUS_SUCCESS;
  428. break;
  429. case IRP_MN_REMOVE_DEVICE:
  430. MyKdPrint(D_Pnp,("Remove PDO\n"))
  431. // shut down everything, call iodelete device
  432. status = STATUS_SUCCESS;
  433. break;
  434. case IRP_MN_CANCEL_REMOVE_DEVICE:
  435. case IRP_MN_QUERY_REMOVE_DEVICE:
  436. case IRP_MN_CANCEL_STOP_DEVICE:
  437. case IRP_MN_QUERY_STOP_DEVICE:
  438. status = STATUS_SUCCESS;
  439. break;
  440. case IRP_MN_QUERY_CAPABILITIES: { // x09
  441. PDEVICE_CAPABILITIES deviceCapabilities;
  442. deviceCapabilities=irpStack->Parameters.DeviceCapabilities.Capabilities;
  443. MyKdPrint(D_Pnp,("Report Caps.\n"))
  444. // Set the capabilities.
  445. deviceCapabilities->Version = 1;
  446. deviceCapabilities->Size = sizeof (DEVICE_CAPABILITIES);
  447. // We cannot wake the system.
  448. deviceCapabilities->SystemWake = PowerSystemUnspecified;
  449. deviceCapabilities->DeviceWake = PowerDeviceUnspecified;
  450. // We have no latencies
  451. deviceCapabilities->D1Latency = 0;
  452. deviceCapabilities->D2Latency = 0;
  453. deviceCapabilities->D3Latency = 0;
  454. // No locking or ejection
  455. deviceCapabilities->LockSupported = FALSE;
  456. deviceCapabilities->EjectSupported = FALSE;
  457. // Device can be physically removed.
  458. // Technically there is no physical device to remove, but this bus
  459. // driver can yank the PDO from the PlugPlay system, when ever it
  460. // receives an IOCTL_GAMEENUM_REMOVE_PORT device control command.
  461. //deviceCapabilities->Removable = TRUE;
  462. // we switch this to FALSE to emulate the stock com port behavior, kpb
  463. deviceCapabilities->Removable = FALSE;
  464. // not Docking device
  465. deviceCapabilities->DockDevice = FALSE;
  466. // BUGBUG: should we do uniqueID???
  467. deviceCapabilities->UniqueID = FALSE;
  468. status = STATUS_SUCCESS;
  469. }
  470. break;
  471. case IRP_MN_QUERY_DEVICE_RELATIONS: // 0x7
  472. if (irpStack->Parameters.QueryDeviceRelations.Type !=
  473. TargetDeviceRelation)
  474. break; //
  475. {
  476. PDEVICE_RELATIONS pDevRel;
  477. // No one else should respond to this since we are the PDO
  478. ASSERT(Irp->IoStatus.Information == 0);
  479. if (Irp->IoStatus.Information != 0) {
  480. break;
  481. }
  482. pDevRel = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
  483. if (pDevRel == NULL) {
  484. status = STATUS_INSUFFICIENT_RESOURCES;
  485. break;
  486. }
  487. pDevRel->Count = 1;
  488. pDevRel->Objects[0] = devobj;
  489. ObReferenceObject(devobj);
  490. status = STATUS_SUCCESS;
  491. Irp->IoStatus.Information = (ULONG_PTR)pDevRel;
  492. }
  493. break;
  494. case IRP_MN_QUERY_ID: // 0x13
  495. {
  496. switch (irpStack->Parameters.QueryId.IdType)
  497. {
  498. case BusQueryInstanceID:
  499. {
  500. WCHAR *wstr;
  501. CHAR our_id[40];
  502. // Build an instance ID. This is what PnP uses to tell if it has
  503. // seen this thing before or not.
  504. // its used to form the ENUM\ key name along with the DeviceID.
  505. //Sprintf(our_id, "Ctm_%s", Ext->NtNameForPort);
  506. Sprintf(our_id, "Port%04d", PortExtToIndex(Ext,0));
  507. MyKdPrint(D_Pnp,("InstanceId:%s\n", our_id))
  508. wstr = str_to_wstr_dup(our_id, PagedPool);
  509. if ( wstr ) {
  510. // as per serenum bus enumerator:
  511. status = STATUS_SUCCESS;
  512. } else {
  513. status = STATUS_INSUFFICIENT_RESOURCES;
  514. }
  515. Irp->IoStatus.Information = (ULONG)wstr;
  516. }
  517. break;
  518. case BusQueryDeviceID:
  519. {
  520. // This is the name used under ENUM to form the device instance
  521. // name under which any new PDO nodes will be created.
  522. // after find new hardware install we find this as an example
  523. // new port node under ENUM:
  524. // Enum\CtmPort\RDevice\6&Port0000
  525. // Enum\CtmPort\RDevice\6&Port0000\Control
  526. // Enum\CtmPort\RDevice\6&Port0000\Device Parameters
  527. // Enum\CtmPort\RDevice\6&Port0000\LogConf
  528. WCHAR *wstr;
  529. CHAR our_id[40];
  530. #ifdef S_VS
  531. strcpy(our_id, "CtmPort\\VSPORT");
  532. #else
  533. strcpy(our_id, "CtmPort\\RKPORT");
  534. #endif
  535. wstr = str_to_wstr_dup(our_id, PagedPool);
  536. MyKdPrint(D_Pnp,("DevID:%s\n", our_id))
  537. Irp->IoStatus.Information = (ULONG)wstr;
  538. if ( wstr ) {
  539. status = STATUS_SUCCESS;
  540. } else {
  541. status = STATUS_INSUFFICIENT_RESOURCES;
  542. }
  543. }
  544. break;
  545. case BusQueryHardwareIDs:
  546. {
  547. // return a multi WCHAR (null terminated) string (null terminated)
  548. // array for use in matching hardare ids in inf files;
  549. WCHAR *wstr;
  550. CHAR our_id[40];
  551. #ifdef S_VS
  552. Sprintf(our_id, "CtmvPort%04d",
  553. PortExtToIndex(Ext, 0 /* driver_flag */) );
  554. #else
  555. Sprintf(our_id, "CtmPort%04d",
  556. PortExtToIndex(Ext, 0 /* driver_flag */) );
  557. #endif
  558. MyKdPrint(D_Pnp,("HrdwrID:%s\n", our_id))
  559. wstr = str_to_wstr_dup(our_id, PagedPool);
  560. Irp->IoStatus.Information = (ULONG)wstr;
  561. if ( wstr ) {
  562. status = STATUS_SUCCESS;
  563. } else {
  564. status = STATUS_INSUFFICIENT_RESOURCES;
  565. }
  566. } //BusQueryHardwareIDs
  567. break;
  568. case BusQueryCompatibleIDs:
  569. {
  570. #if 0
  571. WCHAR *wstr;
  572. CHAR our_id[40];
  573. // The generic ids for installation of this pdo.
  574. Sprintf(our_id, "Cpt_CtmPort0001");
  575. MyKdPrint(D_Pnp,("CompID:%s\n", our_id))
  576. wstr = str_to_wstr_dup(our_id, PagedPool);
  577. Irp->IoStatus.Information = (ULONG)wstr;
  578. status = STATUS_SUCCESS;
  579. #endif
  580. // no compatible id's
  581. Irp->IoStatus.Information = 0;
  582. status = STATUS_SUCCESS;
  583. }
  584. break;
  585. default:
  586. MyKdPrint(D_Pnp,(" UnHandled\n"))
  587. // Irp->IoStatus.Information = 0;
  588. // status = STATUS_SUCCESS;
  589. break;
  590. } // switch IdType
  591. } // IRP_MN_QUERY_ID
  592. break;
  593. case IRP_MN_QUERY_DEVICE_TEXT: // 0x0C
  594. MyKdPrint(D_Pnp,("QueryDevText\n"))
  595. if (irpStack->Parameters.QueryDeviceText.DeviceTextType
  596. != DeviceTextDescription)
  597. {
  598. MyKdPrint(D_Pnp,(" Unhandled Text Type\n"))
  599. break;
  600. }
  601. {
  602. // this is put in the Found New Hardware dialog box message.
  603. WCHAR *wstr;
  604. #if DBG
  605. if (Irp->IoStatus.Information != 0)
  606. {
  607. MyKdPrint(D_Error,("StrExists!\n"))
  608. }
  609. #endif
  610. #ifdef S_VS
  611. wstr = str_to_wstr_dup("Comtrol VS Port", PagedPool);
  612. #else
  613. wstr = str_to_wstr_dup("Comtrol Port", PagedPool);
  614. #endif
  615. Irp->IoStatus.Information = (ULONG)wstr;
  616. if ( wstr ) {
  617. status = STATUS_SUCCESS;
  618. } else {
  619. status = STATUS_INSUFFICIENT_RESOURCES;
  620. }
  621. }
  622. break; // IRP_MN_QUERY_DEVICE_TEXT
  623. default:
  624. //MyKdPrint(D_Pnp,(" PDO Unhandled\n"))
  625. break;
  626. }
  627. Irp->IoStatus.Status = status;
  628. InterlockedDecrement(&Ext->PendingIRPCnt);
  629. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  630. MyKdPrint(D_Pnp,(" PDO Dispatch End\n"))
  631. return status;
  632. }
  633. /*----------------------------------------------------------------------
  634. BoardBusRelations - handle IRP_MN_QUERY_DEVICE_RELATIONS: // 0x7
  635. for our board FDO entity.
  636. |----------------------------------------------------------------------*/
  637. NTSTATUS BoardBusRelations(IN PDEVICE_OBJECT devobj, IN PIRP Irp)
  638. {
  639. PSERIAL_DEVICE_EXTENSION Ext = devobj->DeviceExtension;
  640. PDEVICE_OBJECT pdo = Ext->LowerDeviceObject;
  641. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  642. NTSTATUS status = STATUS_NOT_SUPPORTED;
  643. ULONG i, length, NumPDOs;
  644. PDEVICE_RELATIONS relations;
  645. PSERIAL_DEVICE_EXTENSION ext;
  646. ASSERT( devobj );
  647. switch (irpStack->Parameters.QueryDeviceRelations.Type)
  648. {
  649. case BusRelations:
  650. MyKdPrint(D_Pnp,("BusRelations\n"))
  651. // Tell the plug and play system about all the PDOs.
  652. //
  653. // There might also be device relations below and above this FDO,
  654. // so, be sure to propagate the relations from the upper drivers.
  655. //
  656. // No Completion routine is needed so long as the status is preset
  657. // to success. (PDOs complete plug and play irps with the current
  658. // IoStatus.Status and IoStatus.Information as the default.)
  659. //
  660. NumPDOs = 0; // count the number of pdo's
  661. // count up pdo's for device
  662. ext = Ext->port_pdo_ext;
  663. while (ext != NULL)
  664. {
  665. ++NumPDOs;
  666. ext = ext->port_ext;
  667. }
  668. // The current number of PDOs
  669. i = 0;
  670. if (Irp->IoStatus.Information != 0)
  671. i = ((PDEVICE_RELATIONS) Irp->IoStatus.Information)->Count;
  672. MyKdPrint(D_Pnp, ("Num PDOs:%d + %d\n", i, NumPDOs))
  673. length = sizeof(DEVICE_RELATIONS) +
  674. ((NumPDOs + i) * sizeof (PDEVICE_OBJECT));
  675. relations = (PDEVICE_RELATIONS) ExAllocatePool (NonPagedPool, length);
  676. if (NULL == relations) {
  677. return STATUS_INSUFFICIENT_RESOURCES;
  678. }
  679. // Copy in the device objects so far
  680. if (i) {
  681. RtlCopyMemory (
  682. relations->Objects,
  683. ((PDEVICE_RELATIONS) Irp->IoStatus.Information)->Objects,
  684. i * sizeof (PDEVICE_OBJECT));
  685. }
  686. relations->Count = NumPDOs + i;
  687. //
  688. // For each PDO on this bus add a pointer to the device relations
  689. // buffer, being sure to take out a reference to that object.
  690. // The PlugPlay system will dereference the object when it is done with
  691. // it and free the device relations buffer.
  692. //
  693. ext = Ext->port_pdo_ext;
  694. while (ext != NULL)
  695. {
  696. relations->Objects[i++] = ext->DeviceObject;
  697. ObReferenceObject (ext->DeviceObject); // add 1 to lock on this object
  698. ext = ext->port_ext;
  699. }
  700. // Set up and pass the IRP further down the stack
  701. Irp->IoStatus.Status = STATUS_SUCCESS;
  702. if (0 != Irp->IoStatus.Information) {
  703. ExFreePool ((PVOID) Irp->IoStatus.Information);
  704. }
  705. Irp->IoStatus.Information = (ULONG) relations;
  706. break;
  707. case EjectionRelations:
  708. MyKdPrint(D_Pnp, ("EjectRelations\n"))
  709. break;
  710. case PowerRelations:
  711. MyKdPrint(D_Pnp,("PowerRelations\n"))
  712. break;
  713. case RemovalRelations:
  714. MyKdPrint(D_Pnp,("RemovalRelations\n"))
  715. break;
  716. case TargetDeviceRelation:
  717. MyKdPrint(D_Pnp,("TargetDeviceRelations\n"))
  718. break;
  719. default:
  720. MyKdPrint(D_Pnp,("UnknownRelations\n"))
  721. break;
  722. } // switch .Type
  723. status = STATUS_SUCCESS;
  724. return status;
  725. }
  726. #endif
  727. /*----------------------------------------------------------------------
  728. WaitForLowerPdo -
  729. |----------------------------------------------------------------------*/
  730. NTSTATUS WaitForLowerPdo(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
  731. {
  732. PSERIAL_DEVICE_EXTENSION Ext = fdo->DeviceExtension;
  733. PDEVICE_OBJECT pdo = Ext->LowerDeviceObject;
  734. NTSTATUS status;
  735. KEVENT Event;
  736. KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
  737. IoCopyCurrentIrpStackLocationToNext(Irp);
  738. IoSetCompletionRoutine(Irp, SerialSyncCompletion, &Event,
  739. TRUE, TRUE, TRUE);
  740. status = IoCallDriver(pdo, Irp);
  741. // Wait for lower drivers to be done with the Irp
  742. if (status == STATUS_PENDING)
  743. {
  744. MyKdPrint(D_Pnp,("WaitPend\n"))
  745. KeWaitForSingleObject (&Event, Executive, KernelMode, FALSE,
  746. NULL);
  747. status = Irp->IoStatus.Status;
  748. }
  749. if (!NT_SUCCESS(status))
  750. {
  751. MyKdPrint(D_Pnp,("WaitErr\n"))
  752. return status;
  753. }
  754. return 0;
  755. }
  756. /*----------------------------------------------------------------------
  757. SerialPowerDispatch -
  758. This is a dispatch routine for the IRPs that come to the driver with the
  759. IRP_MJ_POWER major code (power IRPs).
  760. Arguments:
  761. DeviceObject - Pointer to the device object for this device
  762. Irp - Pointer to the IRP for the current request
  763. Return Value:
  764. The function value is the final status of the call
  765. |----------------------------------------------------------------------*/
  766. NTSTATUS SerialPowerDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  767. {
  768. PSERIAL_DEVICE_EXTENSION Ext = DeviceObject->DeviceExtension;
  769. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  770. NTSTATUS status = STATUS_SUCCESS;
  771. BOOLEAN hook_it = FALSE;
  772. PDEVICE_OBJECT pdo = Ext->LowerDeviceObject;
  773. BOOLEAN acceptingIRPs = TRUE;
  774. int index;
  775. // dump out some debug info
  776. index = irpStack->MinorFunction;
  777. if (index > 0x3)
  778. index = 0x4;
  779. if (Ext->IsPDO)
  780. {
  781. #if DBG
  782. MyKdPrint(D_PnpPower,("Port PDO PowerIrp:%d,%s\n", irpStack->MinorFunction,
  783. power_strs[index]))
  784. #endif
  785. return Serial_PDO_Power (DeviceObject, Irp);
  786. }
  787. // else it's a FDO
  788. #if DBG
  789. if (Ext->DeviceType == DEV_BOARD)
  790. {
  791. MyKdPrint(D_PnpPower,("Board PowerIrp:%d,%s\n", irpStack->MinorFunction,
  792. power_strs[index]))
  793. }
  794. else
  795. {
  796. MyKdPrint(D_PnpPower,("Port PowerIrp:%d,%s\n", irpStack->MinorFunction,
  797. power_strs[index]))
  798. }
  799. #endif
  800. return Serial_FDO_Power (DeviceObject, Irp);
  801. }
  802. /*----------------------------------------------------------------------
  803. Serial_FDO_Power - Handle board and port FDO power handling.
  804. |----------------------------------------------------------------------*/
  805. NTSTATUS Serial_FDO_Power (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  806. {
  807. PSERIAL_DEVICE_EXTENSION Ext = DeviceObject->DeviceExtension;
  808. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  809. NTSTATUS status = STATUS_SUCCESS;
  810. BOOLEAN hook_it = FALSE;
  811. PDEVICE_OBJECT pdo = Ext->LowerDeviceObject;
  812. PDEVICE_OBJECT pPdo = Ext->Pdo;
  813. BOOLEAN acceptingIRPs = TRUE;
  814. POWER_STATE powerState;
  815. POWER_STATE_TYPE powerType;
  816. int ChangePower = 0;
  817. int fail_it = 0;
  818. powerType = irpStack->Parameters.Power.Type;
  819. powerState = irpStack->Parameters.Power.State;
  820. status = STATUS_SUCCESS;
  821. acceptingIRPs = SerialIRPPrologue(Ext);
  822. if (acceptingIRPs == FALSE)
  823. {
  824. MyKdPrint(D_PnpPower,("Removed!\n"))
  825. status = STATUS_NO_SUCH_DEVICE; // ?????????????
  826. fail_it = 1;
  827. }
  828. else
  829. {
  830. switch (irpStack->MinorFunction)
  831. {
  832. case IRP_MN_SET_POWER:
  833. MyKdPrint(D_PnpPower,("SET_POWER Type %d, SysState %d, DevStat %d\n",powerType,powerState.SystemState,powerState.DeviceState));
  834. // Perform different ops if it was system or device
  835. switch (irpStack->Parameters.Power.Type)
  836. {
  837. case DevicePowerState:
  838. // do power up & down work on device
  839. ChangePower = 1;
  840. break;
  841. case SystemPowerState:
  842. //if (pDevExt->OwnsPowerPolicy != TRUE) {
  843. // status = STATUS_SUCCESS;
  844. // goto PowerExit;
  845. // }
  846. ChangePower = 1;
  847. switch (irpStack->Parameters.Power.State.SystemState)
  848. {
  849. case PowerSystemUnspecified:
  850. powerState.DeviceState = PowerDeviceUnspecified;
  851. break;
  852. case PowerSystemWorking:
  853. powerState.DeviceState = PowerDeviceD0;
  854. break;
  855. case PowerSystemSleeping1:
  856. case PowerSystemSleeping2:
  857. case PowerSystemSleeping3:
  858. case PowerSystemHibernate:
  859. case PowerSystemShutdown:
  860. case PowerSystemMaximum:
  861. default:
  862. powerState.DeviceState = PowerDeviceD3;
  863. break;
  864. }
  865. break; // end case SystemPowerState
  866. } // end switch
  867. if (ChangePower)
  868. {
  869. // If we are already in the requested state, just pass the IRP down
  870. if (Ext->PowerState == powerState.DeviceState)
  871. {
  872. MyKdPrint(D_PnpPower,(" Same\n"))
  873. status = STATUS_SUCCESS;
  874. Irp->IoStatus.Status = status;
  875. ChangePower = 0;
  876. }
  877. }
  878. if (ChangePower)
  879. {
  880. MyKdPrint(D_PnpPower,("ExtPowerState %d, DeviceState %d\n",Ext->PowerState,powerState.DeviceState));
  881. switch (powerState.DeviceState)
  882. {
  883. case PowerDeviceD0:
  884. if (Ext->DeviceType == DEV_BOARD)
  885. {
  886. // powering up board.
  887. MyKdPrint(D_PnpPower,(" Hook\n"))
  888. ASSERT(Ext->LowerDeviceObject);
  889. hook_it = TRUE;
  890. }
  891. break;
  892. case PowerDeviceD1:
  893. case PowerDeviceD2:
  894. case PowerDeviceD3:
  895. default:
  896. // we should be doing this on the way up in the hook routine.
  897. MyKdPrint(D_PnpPower,(" PwDown\n"))
  898. // Before we power down, call PoSetPowerState
  899. PoSetPowerState(DeviceObject, powerType, powerState);
  900. // Shut it down
  901. //.....
  902. //
  903. Ext->PowerState = powerState.DeviceState; // PowerDeviceD0;
  904. if (Ext->DeviceType == DEV_BOARD)
  905. {
  906. MyKdPrint(D_PnpPower,(" PwDown Board\n"))
  907. // shut some things down, so it comes back up ok
  908. #if S_RK
  909. Ext->config->RocketPortFound = 0; // this tells if its started
  910. #endif
  911. Ext->config->HardwareStarted = FALSE;
  912. }
  913. Irp->IoStatus.Status = STATUS_SUCCESS;
  914. status = STATUS_SUCCESS;
  915. break;
  916. } // switch (IrpSp->Parameters.Power.State.DeviceState)
  917. } // ChangePower
  918. break; // SET_POWER
  919. case IRP_MN_QUERY_POWER:
  920. MyKdPrint(D_PnpPower,(" QueryPower SystemState 0x%x\n",irpStack->Parameters.Power.State.SystemState))
  921. // if they want to go to a power-off state(sleep, hibernate, etc)
  922. if (irpStack->Parameters.Power.State.SystemState != PowerSystemWorking)
  923. {
  924. MyKdPrint(D_PnpPower,(" QueryPower turn off\n"))
  925. // only handle power logic for the board as a whole
  926. if (Ext->DeviceType == DEV_BOARD)
  927. {
  928. MyKdPrint(D_PnpPower,(" PwDown Board\n"))
  929. // if a port is open and being used, then fail the request
  930. #if 0
  931. // try to get the wake up restore of hardware working...
  932. // kpb, 2-7-99
  933. if (is_board_in_use(Ext))
  934. {
  935. MyKdPrint(D_PnpPower,(" PwDown Board In Use!\n"))
  936. // if wants to powerdown
  937. // BUGBUG:, refuse hibernation
  938. status = STATUS_NO_SUCH_DEVICE; // ?
  939. fail_it = 1;
  940. }
  941. else
  942. #endif
  943. {
  944. MyKdPrint(D_PnpPower,(" PwDown Board, allow it!\n"))
  945. #ifdef MTM_CLOSE_NIC_ATTEMPT
  946. if ( Driver.nics ) {
  947. for( i=0; i<VS1000_MAX_NICS; i++ ) {
  948. if ( Driver.nics[i].NICHandle ) {
  949. MyKdPrint(D_PnpPower,("Closing Nic %d\n",i))
  950. NicClose( &Driver.nics[i] );
  951. }
  952. }
  953. }
  954. #endif
  955. }
  956. }
  957. }
  958. if (!fail_it)
  959. {
  960. status = STATUS_SUCCESS;
  961. Irp->IoStatus.Status = status;
  962. }
  963. break;
  964. //case IRP_MN_WAIT_WAKE:
  965. // Here is where support for a
  966. // serial device (like a modem) waking the system when the
  967. // phone rings.
  968. //case IRP_MN_POWER_SEQUENCE:
  969. default:
  970. break;
  971. } // switch (irpStack->MinorFunction)
  972. } // else, handle irp
  973. if (fail_it)
  974. {
  975. // status assumed set above
  976. PoStartNextPowerIrp (Irp);
  977. Irp->IoStatus.Information = 0;
  978. Irp->IoStatus.Status = status;
  979. InterlockedDecrement(&Ext->PendingIRPCnt);
  980. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  981. return status;
  982. }
  983. // Pass to the lower driver
  984. if (hook_it)
  985. {
  986. IoCopyCurrentIrpStackLocationToNext (Irp);
  987. MyKdPrint(D_PnpPower,(" Hooked\n"))
  988. IoSetCompletionRoutine(Irp, OurPowerCompletion, NULL, TRUE, TRUE, TRUE);
  989. MyKdPrint(D_PnpPower,(" Ready to send Irp 0x%x to PDO 0x%x\n", Irp, pdo))
  990. status = PoCallDriver(pdo, Irp);
  991. // hooking proc is responsible for decrementing reference count in ext
  992. // and calling PoStartNextPowerIrp().
  993. }
  994. else
  995. {
  996. IoCopyCurrentIrpStackLocationToNext (Irp);
  997. /// try this ^ instead ---- IoSkipCurrentIrpStackLocation (Irp);
  998. MyKdPrint(D_PnpPower,(" Passed\n"))
  999. PoStartNextPowerIrp(Irp);
  1000. status = PoCallDriver(pdo, Irp);
  1001. SerialIRPEpilogue(Ext);
  1002. }
  1003. MyKdPrint(D_PnpPower,("End PowerDisp\n"))
  1004. return status;
  1005. }
  1006. /*----------------------------------------------------------------------
  1007. Serial_PDO_Power - Handle port PDO power handling.
  1008. |----------------------------------------------------------------------*/
  1009. NTSTATUS Serial_PDO_Power (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  1010. {
  1011. PSERIAL_DEVICE_EXTENSION Ext = DeviceObject->DeviceExtension;
  1012. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1013. NTSTATUS status = STATUS_SUCCESS;
  1014. BOOLEAN hook_it = FALSE;
  1015. PDEVICE_OBJECT pdo = Ext->LowerDeviceObject;
  1016. BOOLEAN acceptingIRPs = TRUE;
  1017. POWER_STATE powerState;
  1018. POWER_STATE_TYPE powerType;
  1019. powerType = irpStack->Parameters.Power.Type;
  1020. powerState = irpStack->Parameters.Power.State;
  1021. status = STATUS_SUCCESS;
  1022. switch (irpStack->MinorFunction)
  1023. {
  1024. case IRP_MN_SET_POWER:
  1025. if (powerType == SystemPowerState)
  1026. {
  1027. MyKdPrint(D_PnpPower,(" SysPower\n"))
  1028. status = STATUS_SUCCESS;
  1029. Irp->IoStatus.Status = status;
  1030. break;
  1031. }
  1032. if (powerType != DevicePowerState)
  1033. {
  1034. MyKdPrint(D_PnpPower,(" OtherType\n"))
  1035. // They asked for a system power state change which we can't do.
  1036. // Pass it down to the lower driver.
  1037. status = STATUS_SUCCESS;
  1038. Irp->IoStatus.Status = status;
  1039. break;
  1040. }
  1041. // If we are already in the requested state, just pass the IRP down
  1042. if (Ext->PowerState == powerState.DeviceState)
  1043. {
  1044. MyKdPrint(D_PnpPower,(" Same\n"))
  1045. status = STATUS_SUCCESS;
  1046. Irp->IoStatus.Status = status;
  1047. break;
  1048. }
  1049. MyKdPrint(D_PnpPower,(" Set\n"))
  1050. Ext->PowerState = powerState.DeviceState; // PowerDeviceD0;
  1051. PoSetPowerState(DeviceObject, powerType, powerState);
  1052. break;
  1053. case IRP_MN_QUERY_POWER:
  1054. status = STATUS_SUCCESS;
  1055. break;
  1056. case IRP_MN_WAIT_WAKE:
  1057. case IRP_MN_POWER_SEQUENCE:
  1058. default:
  1059. MyKdPrint(D_PnpPower,("Not Imp!\n"))
  1060. status = STATUS_NOT_IMPLEMENTED;
  1061. break;
  1062. }
  1063. Irp->IoStatus.Status = status;
  1064. PoStartNextPowerIrp (Irp);
  1065. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  1066. MyKdPrint(D_PnpPower,("End PDO PowerDisp\n"))
  1067. return status;
  1068. }
  1069. /*----------------------------------------------------------------------
  1070. SerialStartDevice -
  1071. This routine first passes the start device Irp down the stack then
  1072. it picks up the resources for the device, ititializes, puts it on any
  1073. appropriate lists (i.e shared interrupt or interrupt status) and
  1074. connects the interrupt.
  1075. Arguments:
  1076. Fdo - Pointer to the functional device object for this device
  1077. Irp - Pointer to the IRP for the current request
  1078. Return Value:
  1079. Return status
  1080. |----------------------------------------------------------------------*/
  1081. NTSTATUS SerialStartDevice(
  1082. IN PDEVICE_OBJECT Fdo,
  1083. IN PIRP Irp)
  1084. {
  1085. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1086. NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  1087. PSERIAL_DEVICE_EXTENSION Ext = Fdo->DeviceExtension;
  1088. PDEVICE_OBJECT pdo = Ext->LowerDeviceObject;
  1089. MyKdPrint(D_Pnp,("SerialStartDevice\n"))
  1090. // Set up the external naming and create the symbolic link
  1091. // Pass this down to the Pdo
  1092. status = WaitForLowerPdo(Fdo, Irp);
  1093. status = STATUS_SUCCESS;
  1094. // Do the serial specific items to start the device
  1095. status = SerialFinishStartDevice(Fdo,
  1096. irpStack->Parameters.StartDevice.AllocatedResources,
  1097. irpStack->Parameters.StartDevice.AllocatedResourcesTranslated);
  1098. Irp->IoStatus.Status = status;
  1099. MyKdPrint(D_Pnp,("End Start Dev\n"))
  1100. return status;
  1101. }
  1102. /*----------------------------------------------------------------------
  1103. SerialSyncCompletion -
  1104. |----------------------------------------------------------------------*/
  1105. NTSTATUS SerialSyncCompletion(
  1106. IN PDEVICE_OBJECT DeviceObject,
  1107. IN PIRP Irp,
  1108. IN PKEVENT SerialSyncEvent
  1109. )
  1110. {
  1111. KeSetEvent(SerialSyncEvent, IO_NO_INCREMENT, FALSE);
  1112. return STATUS_MORE_PROCESSING_REQUIRED;
  1113. }
  1114. /*----------------------------------------------------------------------
  1115. SerialFinishStartDevice -
  1116. This routine starts driver hardware. On the RocketPort, this is
  1117. a board, or a port. On the VS, this would be the whole VS driver
  1118. (all boxes) or a individual port.
  1119. A Pnp ADDDEVICE call(in pnpadd.c) should have been seen before this
  1120. to setup the driver. After this, we may see Starts or Stops on the
  1121. hardware, which the OS may start and stop to change resource assignments,
  1122. etc.
  1123. Arguments:
  1124. Fdo - Pointer to the Functional Device Object that is starting
  1125. resourceList - Pointer to the untranslated resources needed by this device
  1126. trResourceList - Pointer to the translated resources needed by this device
  1127. PUserData - Pointer to the user-specified resources/attributes
  1128. Return Value:
  1129. STATUS_SUCCESS on success, something else appropriate on failure
  1130. |----------------------------------------------------------------------*/
  1131. NTSTATUS SerialFinishStartDevice(IN PDEVICE_OBJECT Fdo,
  1132. IN PCM_RESOURCE_LIST resourceList,
  1133. IN PCM_RESOURCE_LIST trResourceList)
  1134. {
  1135. PSERIAL_DEVICE_EXTENSION Ext = Fdo->DeviceExtension;
  1136. NTSTATUS status;
  1137. DEVICE_CONFIG *pConfig;
  1138. PSERIAL_DEVICE_EXTENSION newExtension = NULL;
  1139. PDEVICE_OBJECT NewDevObj;
  1140. int ch;
  1141. int is_fdo = 1;
  1142. #ifdef NT50
  1143. PWSTR iBuffer;
  1144. #endif
  1145. MyKdPrint(D_Pnp,("SerialFinishStartDevice\n"))
  1146. pConfig = Ext->config;
  1147. MyKdPrint(D_Pnp,("ChkPt A\n"))
  1148. if (Ext->DeviceType != DEV_BOARD)
  1149. {
  1150. MyKdPrint(D_Pnp,("Start PnpPort\n"))
  1151. Ext->FdoStarted = TRUE; // i don't thinks this is used on ports
  1152. #ifdef NT50
  1153. // Create a symbolic link with IoRegisterDeviceInterface()
  1154. //
  1155. status = IoRegisterDeviceInterface( Ext->Pdo,
  1156. (LPGUID)&GUID_CLASS_COMPORT,
  1157. NULL,
  1158. &Ext->DeviceClassSymbolicName );
  1159. if (!NT_SUCCESS(status)) {
  1160. MyKdPrint(D_Error,("Couldn't register class association\n"))
  1161. Ext->DeviceClassSymbolicName.Buffer = NULL;
  1162. }
  1163. else {
  1164. MyKdPrint(D_Init, ("Registering class association for:\n PDO:0x%8x\nSymLink %s\n",
  1165. Ext->Pdo, UToC1(&Ext->DeviceClassSymbolicName)))
  1166. }
  1167. // Now set the symbolic link for the interface association
  1168. //
  1169. status = IoSetDeviceInterfaceState( &Ext->DeviceClassSymbolicName,
  1170. TRUE);
  1171. if (!NT_SUCCESS(status)) {
  1172. MyKdPrint(D_Error,("Couldn't set class association for %s\n",
  1173. UToC1(&Ext->DeviceClassSymbolicName)))
  1174. }
  1175. else {
  1176. MyKdPrint(D_PnpAdd, ("Enable class association for device: %s\n",
  1177. UToC1(&Ext->DeviceClassSymbolicName)))
  1178. }
  1179. #if 0
  1180. // Strictly for verification - get the entire list of COM class interfaces
  1181. // for up to 6 COM ports
  1182. status = IoGetDeviceInterfaces( (LPGUID)&GUID_CLASS_COMPORT,
  1183. NULL, // No PDO - get 'em all
  1184. 0,
  1185. &iBuffer );
  1186. if (!NT_SUCCESS(status)) {
  1187. MyKdPrint(D_Error,("Couldn't get interface list for GUID_CLASS_COMPORT\n"))
  1188. }
  1189. else {
  1190. PWCHAR pwbuf = iBuffer;
  1191. char cbuf[128];
  1192. int j = 0;
  1193. int ofs = 0;
  1194. while ( (pwbuf != 0) && (j < 8) ){
  1195. WStrToCStr( cbuf, pwbuf, sizeof(cbuf) );
  1196. MyKdPrint(D_Pnp, ("COM port interface %d: %s\n", j, cbuf))
  1197. ofs += strlen(cbuf) + 1;
  1198. pwbuf = &iBuffer[ofs];
  1199. j++;
  1200. }
  1201. ExFreePool(iBuffer);
  1202. }
  1203. #endif
  1204. #endif
  1205. status = STATUS_SUCCESS;
  1206. return status;
  1207. }
  1208. if (Ext->FdoStarted == TRUE)
  1209. {
  1210. MyKdPrint(D_Error,("ReStart PnpBrd\n"))
  1211. status = STATUS_SUCCESS;
  1212. return status;
  1213. }
  1214. if (!Driver.NoPnpPorts)
  1215. is_fdo = 0; // eject PDOs representing port hardware.
  1216. // Get the configuration info for the device.
  1217. #ifdef S_RK
  1218. status = RkGetPnpResourceToConfig(Fdo, resourceList, trResourceList,
  1219. pConfig);
  1220. if (!NT_SUCCESS (status)) {
  1221. Eprintf("StartErr 1N");
  1222. return status;
  1223. }
  1224. #ifdef DO_ISA_BUS_ALIAS_IO
  1225. status = Report_Alias_IO(Ext);
  1226. if (status != 0)
  1227. {
  1228. Eprintf("StartErr Alias-IO");
  1229. MyKdPrint(D_Pnp,("Error 1P\n"))
  1230. status = STATUS_INSUFFICIENT_RESOURCES;
  1231. return status;
  1232. }
  1233. MyKdPrint(D_Pnp,("ChkPt B\n"))
  1234. #endif
  1235. //DELF
  1236. MyKdPrint(D_Pnp,("INIT RCK\n"))
  1237. //END DELF
  1238. status = RocketPortSpecialStartup(Ext);
  1239. if (status != STATUS_SUCCESS)
  1240. {
  1241. Eprintf("StartErr 1J");
  1242. return status;
  1243. }
  1244. #endif
  1245. MyKdPrint(D_Pnp,("ChkPt C\n"))
  1246. #ifdef S_VS
  1247. status = VSSpecialStartup(Ext);
  1248. if (status != STATUS_SUCCESS)
  1249. {
  1250. Eprintf("StartErr 1J");
  1251. return status;
  1252. }
  1253. #endif
  1254. //----- Create our port devices, if we are doing pnp ports, then
  1255. // create PDO's, if not, then create normal com-port device objects
  1256. // (same as FDO's.)
  1257. for (ch=0; ch<Ext->config->NumPorts; ch++)
  1258. {
  1259. //MyKdPrint(D_Pnp,("FS,ChanInit:%d\n", ch))
  1260. status = CreatePortDevice(
  1261. Driver.GlobalDriverObject,
  1262. Ext, // parent ext.
  1263. &newExtension,
  1264. ch,
  1265. is_fdo);
  1266. if (status != STATUS_SUCCESS)
  1267. {
  1268. Eprintf("StartErr 1Q");
  1269. return status;
  1270. }
  1271. NewDevObj = newExtension->DeviceObject; //return the new device object
  1272. NewDevObj->Flags |= DO_POWER_PAGABLE;
  1273. if (!is_fdo) // eject PDOs representing port hardware.
  1274. newExtension->IsPDO = 1; // we are a pdo
  1275. #if S_RK
  1276. if (Ext->config->RocketPortFound) // if started(not delayed isa)
  1277. #endif
  1278. {
  1279. status = StartPortHardware(newExtension,
  1280. ch); // channel num, port index
  1281. if (status != STATUS_SUCCESS)
  1282. {
  1283. Eprintf("StartErr 1O");
  1284. return status;
  1285. }
  1286. }
  1287. } // for ports
  1288. #ifdef S_RK
  1289. if (Ext->config->RocketPortFound) // if started(not delayed isa)
  1290. #endif
  1291. {
  1292. Ext->config->HardwareStarted = TRUE;
  1293. // send ROW configuration to SocketModems
  1294. InitSocketModems(Ext);
  1295. #ifdef S_RK
  1296. InitRocketModemII (Ext);
  1297. #endif
  1298. }
  1299. MyKdPrint(D_Pnp,("ChkPt D\n"))
  1300. //---- start up the timer
  1301. if (!Driver.TimerCreated)
  1302. {
  1303. #ifdef S_RK
  1304. Driver.SetupIrq = 0;
  1305. #endif
  1306. //MyKdPrint(D_Pnp,("before rcktinitpolltimer\n"))
  1307. RcktInitPollTimer();
  1308. //MyKdPrint(D_Pnp,("after rcktinitpolltimer\n"))
  1309. KeSetTimer(&Driver.PollTimer,
  1310. Driver.PollIntervalTime,
  1311. &Driver.TimerDpc);
  1312. }
  1313. MyKdPrint(D_Pnp,("ChkPt F, after\n"))
  1314. Ext->FdoStarted = TRUE;
  1315. //if (Drier.VerboseLog)
  1316. // Eprintf("Success start dev");
  1317. status = STATUS_SUCCESS;
  1318. return status;
  1319. }
  1320. #ifdef S_RK
  1321. /*-----------------------------------------------------------------------
  1322. RocketPortSpecialStartup -
  1323. |-----------------------------------------------------------------------*/
  1324. static NTSTATUS RocketPortSpecialStartup(PSERIAL_DEVICE_EXTENSION Ext)
  1325. {
  1326. int ch;
  1327. int start_isa_flag;
  1328. NTSTATUS status = STATUS_SUCCESS;
  1329. PSERIAL_DEVICE_EXTENSION tmpExt;
  1330. PSERIAL_DEVICE_EXTENSION newExt;
  1331. if (Ext->config->BusType == Isa)
  1332. {
  1333. MyKdPrint(D_PnpPower,("pnp- ISA brd Index:%d\n",
  1334. Ext->config->ISABrdIndex))
  1335. if (Ext->config->ISABrdIndex == 0)
  1336. start_isa_flag = 1;
  1337. else if (is_first_isa_card_started())
  1338. start_isa_flag = 1;
  1339. else
  1340. {
  1341. MyKdPrint(D_PnpPower,("Delay 2ndary ISA card start\n"))
  1342. start_isa_flag = 0;
  1343. }
  1344. }
  1345. //----- Init the RocketPort hardware
  1346. if ((Ext->config->BusType == Isa) && (!start_isa_flag))
  1347. status = 0; // skip, can't start until we get the first board
  1348. else
  1349. {
  1350. status = InitController(Ext); // this sets RocketPortFound = TRUE if ok
  1351. if (status != 0)
  1352. {
  1353. status = STATUS_INSUFFICIENT_RESOURCES;
  1354. MyKdPrint(D_Error,("Brd failed startup\n"))
  1355. //if (Driver.VerboseLog)
  1356. // Eprintf("Error InitCtrl");
  1357. return status;
  1358. }
  1359. MyKdPrint(D_PnpPower,("Brd started\n"))
  1360. }
  1361. if ((Ext->config->BusType == Isa) && (is_first_isa_card_started()) &&
  1362. (is_isa_cards_pending_start()) )
  1363. {
  1364. MyKdPrint(D_Pnp,("Do Pending\n"))
  1365. tmpExt = Driver.board_ext;
  1366. while (tmpExt)
  1367. {
  1368. if ((tmpExt->config->BusType == Isa) &&
  1369. (!tmpExt->config->RocketPortFound)) // this tells if its started
  1370. {
  1371. MyKdPrint(D_Pnp,("Pending 1A\n"))
  1372. status = InitController(tmpExt); // this sets RocketPortFound = TRUE if ok
  1373. if (status != 0)
  1374. {
  1375. status = STATUS_INSUFFICIENT_RESOURCES;
  1376. if (Driver.VerboseLog)
  1377. Eprintf("Error 5C");
  1378. return status;
  1379. }
  1380. MyKdPrint(D_Pnp,("Pend 2A\n"))
  1381. //----- Find and initialize the controller ports
  1382. newExt = tmpExt->port_ext;
  1383. ch=0;
  1384. while (newExt)
  1385. {
  1386. status = StartPortHardware(newExt,
  1387. ch); // channel num, port index
  1388. if (status != STATUS_SUCCESS)
  1389. {
  1390. Eprintf("StartErr 1N");
  1391. return status;
  1392. }
  1393. newExt = newExt->port_ext;
  1394. ++ch;
  1395. }
  1396. tmpExt->config->HardwareStarted = TRUE;
  1397. // send ROW configuration to SocketModems
  1398. InitSocketModems(tmpExt);
  1399. MyKdPrint(D_Pnp,("Pending OK\n"))
  1400. }
  1401. tmpExt = tmpExt->board_ext;
  1402. }
  1403. } // if isa boards to startup
  1404. return status;
  1405. }
  1406. #endif
  1407. /*-----------------------------------------------------------------------
  1408. This routine kills any irps pending for the passed device object.
  1409. Arguments:
  1410. DeviceObject - Pointer to the device object whose irps must die.
  1411. Return Value:
  1412. VOID
  1413. |-----------------------------------------------------------------------*/
  1414. VOID SerialKillPendingIrps(PDEVICE_OBJECT DeviceObject)
  1415. {
  1416. PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  1417. KIRQL oldIrql;
  1418. //PAGED_CODE();
  1419. //SerialDump (SERTRACECALLS,("SERIAL: Enter SerialKillPendingIrps\n"));
  1420. // this is for the FDO, which currently is the BOARD, so we have to
  1421. // do all ports for this board.(THIS IS NOT A PORT EXTENSION!!!!!)
  1422. // First kill all the reads and writes.
  1423. SerialKillAllReadsOrWrites(
  1424. DeviceObject,
  1425. &extension->WriteQueue,
  1426. &extension->CurrentWriteIrp
  1427. );
  1428. SerialKillAllReadsOrWrites(
  1429. DeviceObject,
  1430. &extension->ReadQueue,
  1431. &extension->CurrentReadIrp
  1432. );
  1433. // Next get rid of purges.
  1434. SerialKillAllReadsOrWrites(
  1435. DeviceObject,
  1436. &extension->PurgeQueue,
  1437. &extension->CurrentPurgeIrp
  1438. );
  1439. // Now get rid a pending wait mask irp.
  1440. IoAcquireCancelSpinLock(&oldIrql);
  1441. if (extension->CurrentWaitIrp) {
  1442. PDRIVER_CANCEL cancelRoutine;
  1443. cancelRoutine = extension->CurrentWaitIrp->CancelRoutine;
  1444. extension->CurrentWaitIrp->Cancel = TRUE;
  1445. if (cancelRoutine) {
  1446. extension->CurrentWaitIrp->CancelIrql = oldIrql;
  1447. extension->CurrentWaitIrp->CancelRoutine = NULL;
  1448. cancelRoutine(
  1449. DeviceObject,
  1450. extension->CurrentWaitIrp
  1451. );
  1452. }
  1453. } else {
  1454. IoReleaseCancelSpinLock(oldIrql);
  1455. }
  1456. //SerialDump (SERTRACECALLS,("SERIAL: Leave SerialKillPendingIrps\n"));
  1457. }
  1458. /*-----------------------------------------------------------------------
  1459. This function must be called at any IRP dispatch entry point. It,
  1460. with SerialIRPPrologue(), keeps track of all pending IRP's for the given
  1461. PDevObj.
  1462. Arguments:
  1463. PDevObj - Pointer to the device object we are tracking pending IRP's for.
  1464. Return Value:
  1465. None.
  1466. |-----------------------------------------------------------------------*/
  1467. VOID SerialIRPEpilogue(IN PSERIAL_DEVICE_EXTENSION PDevExt)
  1468. {
  1469. ULONG pendingCnt;
  1470. pendingCnt = InterlockedDecrement(&PDevExt->PendingIRPCnt);
  1471. #if DBG
  1472. //MyKdPrint(D_Pnp,("Exit PendingIrpCnt:%d\n", PDevExt->PendingIRPCnt))
  1473. #endif
  1474. if (pendingCnt == 0)
  1475. {
  1476. MyKdPrint(D_Pnp,("Set PendingIRPEvent\n"))
  1477. KeSetEvent(&PDevExt->PendingIRPEvent, IO_NO_INCREMENT, FALSE);
  1478. }
  1479. }
  1480. /*-----------------------------------------------------------------------
  1481. SerialIoCallDriver -
  1482. |-----------------------------------------------------------------------*/
  1483. NTSTATUS SerialIoCallDriver(PSERIAL_DEVICE_EXTENSION PDevExt,
  1484. PDEVICE_OBJECT PDevObj,
  1485. PIRP PIrp)
  1486. {
  1487. NTSTATUS status;
  1488. ASSERT( PDevObj );
  1489. status = IoCallDriver(PDevObj, PIrp);
  1490. SerialIRPEpilogue(PDevExt);
  1491. return status;
  1492. }
  1493. /*-----------------------------------------------------------------------
  1494. SerialPoCallDriver -
  1495. |-----------------------------------------------------------------------*/
  1496. NTSTATUS SerialPoCallDriver(PSERIAL_DEVICE_EXTENSION PDevExt,
  1497. PDEVICE_OBJECT PDevObj,
  1498. PIRP PIrp)
  1499. {
  1500. NTSTATUS status;
  1501. status = PoCallDriver(PDevObj, PIrp);
  1502. SerialIRPEpilogue(PDevExt);
  1503. return status;
  1504. }
  1505. /*-----------------------------------------------------------------------
  1506. This routine is a completion handler that is called after the COM port
  1507. has been powered up. It sets the COM port in a known state by calling
  1508. SerialReset, SerialMarkClose, SerialClrRTS, and SerialClrDTR. The it
  1509. does a PoCompleteRequest to finish off the power Irp.
  1510. Arguments:
  1511. DeviceObject - Pointer to the device object for this device
  1512. Irp - Pointer to the IRP for the current request
  1513. Context - None
  1514. Return Value:
  1515. Return status in IRP when being called (if not STATUS_SUCCESS) or
  1516. STATUS_SUCCESS.
  1517. |-----------------------------------------------------------------------*/
  1518. NTSTATUS OurPowerCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
  1519. {
  1520. NTSTATUS status = Irp->IoStatus.Status;
  1521. PSERIAL_DEVICE_EXTENSION Ext = DeviceObject->DeviceExtension;
  1522. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1523. POWER_STATE powerState;
  1524. POWER_STATE_TYPE powerType;
  1525. powerType = irpStack->Parameters.Power.Type;
  1526. powerState = irpStack->Parameters.Power.State;
  1527. MyKdPrint(D_PnpPower,("In OurPowerCompletion\n"))
  1528. if (irpStack->MinorFunction == IRP_MN_SET_POWER)
  1529. {
  1530. if (powerState.DeviceState == PowerDeviceD0)
  1531. {
  1532. MyKdPrint(D_PnpPower,("Restoring to Power On State D0\n"))
  1533. status = STATUS_SUCCESS;
  1534. // set hardware to known power up state
  1535. Ext->PowerState = powerState.DeviceState; // PowerDeviceD0;
  1536. if (Ext->DeviceType == DEV_BOARD)
  1537. {
  1538. status = PowerUpDevice(Ext);
  1539. } // board device
  1540. else if (Ext->DeviceType == DEV_PORT)
  1541. {
  1542. Ext->config->HardwareStarted = TRUE;
  1543. }
  1544. PoSetPowerState(DeviceObject, powerType, powerState);
  1545. }
  1546. else // if (powerState.DeviceState == PowerDeviceD3)
  1547. {
  1548. status = STATUS_SUCCESS;
  1549. // Clear the flag saying we are waiting for a power down
  1550. Ext->ReceivedQueryD3 = FALSE;
  1551. Ext->PowerState = PowerDeviceD3;
  1552. }
  1553. }
  1554. InterlockedDecrement(&Ext->PendingIRPCnt);
  1555. PoStartNextPowerIrp(Irp);
  1556. return status;
  1557. }
  1558. /*-----------------------------------------------------------------------
  1559. RestorePortSettings - Try to restore port hardware settings. Called
  1560. after power-off sleep mode.
  1561. |-----------------------------------------------------------------------*/
  1562. void RestorePortSettings(PSERIAL_DEVICE_EXTENSION Ext)
  1563. {
  1564. SERIAL_HANDFLOW TempHandFlow;
  1565. DWORD TempDTRRTSStatus;
  1566. DWORD xorDTRRTSStatus;
  1567. #ifdef S_RK
  1568. // remember what the status of pins are coming into this
  1569. // so we can try to put them back to what they were prior to
  1570. // hardware re-initialization.
  1571. TempDTRRTSStatus = Ext->DTRRTSStatus; // SERIAL_DTR_STATE;
  1572. if(sGetChanStatus(Ext->ChP) & STATMODE)
  1573. { // Take channel out of statmode if necessary
  1574. sDisRxStatusMode(Ext->ChP);
  1575. }
  1576. // pDisLocalLoopback(Ext->Port);
  1577. // Clear any pending modem changes
  1578. sGetChanIntID(Ext->ChP);
  1579. sEnRxFIFO(Ext->ChP); // Enable Rx
  1580. sEnTransmit(Ext->ChP); // Enable Tx
  1581. sSetRxTrigger(Ext->ChP,TRIG_1); // always trigger
  1582. sEnInterrupts(Ext->ChP, Ext->IntEnables);// allow interrupts
  1583. ForceExtensionSettings(Ext);
  1584. // make a temp. copy of handflow struct
  1585. memcpy(&TempHandFlow, &Ext->HandFlow, sizeof(TempHandFlow));
  1586. // force updates in SerialSetHandFlow, which looks for delta change.
  1587. Ext->HandFlow.ControlHandShake = ~TempHandFlow.ControlHandShake;
  1588. Ext->HandFlow.FlowReplace = ~TempHandFlow.FlowReplace;
  1589. SerialSetHandFlow(Ext, &TempHandFlow); // in ioctl.c
  1590. // program hardware baudrate
  1591. ProgramBaudRate(Ext, Ext->BaudRate);
  1592. xorDTRRTSStatus = Ext->DTRRTSStatus ^ TempDTRRTSStatus;
  1593. // try to restore the actual dtr & rts outputs
  1594. if (xorDTRRTSStatus & SERIAL_DTR_STATE) // changed
  1595. {
  1596. // if not auto-handshake dtr mode
  1597. if (!((Ext->HandFlow.ControlHandShake & SERIAL_DTR_MASK) ==
  1598. SERIAL_DTR_HANDSHAKE ))
  1599. {
  1600. if (TempDTRRTSStatus & SERIAL_DTR_STATE) // was on
  1601. {
  1602. sSetDTR(Ext->ChP);
  1603. }
  1604. else
  1605. {
  1606. sClrDTR(Ext->ChP);
  1607. }
  1608. } // not auto-dtr flow
  1609. } // chg in dtr
  1610. if (xorDTRRTSStatus & SERIAL_RTS_STATE) // changed
  1611. {
  1612. // if not auto-flow control rts
  1613. if (!((Ext->HandFlow.ControlHandShake & SERIAL_RTS_MASK) ==
  1614. SERIAL_RTS_HANDSHAKE))
  1615. {
  1616. if (TempDTRRTSStatus & SERIAL_RTS_STATE) // was on
  1617. {
  1618. sSetRTS(Ext->ChP);
  1619. }
  1620. else
  1621. {
  1622. sClrRTS(Ext->ChP);
  1623. }
  1624. } // chg in rts
  1625. Ext->DTRRTSStatus = TempDTRRTSStatus;
  1626. }
  1627. #endif
  1628. // the VS boxes will not be powered off, and will hold their state
  1629. // so no hardware re-initialization is needed. The box will have
  1630. // probably timed out the connection, and force a re-sync operation,
  1631. // we might want to pro-actively start this so there is a smaller
  1632. // delay...
  1633. }
  1634. /*-----------------------------------------------------------------------
  1635. PowerUpDevice - Used to bring power back on after turning it off.
  1636. |-----------------------------------------------------------------------*/
  1637. NTSTATUS PowerUpDevice(PSERIAL_DEVICE_EXTENSION Ext)
  1638. {
  1639. PSERIAL_DEVICE_EXTENSION port_ext;
  1640. int ch;
  1641. NTSTATUS status = STATUS_SUCCESS;
  1642. #ifdef S_RK
  1643. MyKdPrint(D_PnpPower,("RocketPort Init %d\n",Ext->config->HardwareStarted))
  1644. status = RocketPortSpecialStartup(Ext);
  1645. if (status != STATUS_SUCCESS)
  1646. {
  1647. MyKdPrint(D_Error,("RocketPort Init Failed\n"))
  1648. //return status;
  1649. }
  1650. if (Ext->config->RocketPortFound) // if started(not delayed isa)
  1651. Ext->config->HardwareStarted = TRUE;
  1652. #endif
  1653. #ifdef S_VS
  1654. MyKdPrint(D_PnpPower,("VS Init\n"))
  1655. status = VSSpecialStartup(Ext);
  1656. if (status != STATUS_SUCCESS)
  1657. {
  1658. MyKdPrint(D_Error,("VS Init Failed\n"))
  1659. //return status;
  1660. }
  1661. Ext->config->HardwareStarted = TRUE;
  1662. #endif
  1663. if (Ext->config->HardwareStarted == TRUE)
  1664. {
  1665. if (Ext->port_ext == NULL)
  1666. {MyKdPrint(D_Error,("No Ports\n")) }
  1667. //----- Find and initialize the controller ports
  1668. port_ext = Ext->port_ext;
  1669. ch=0;
  1670. while (port_ext)
  1671. {
  1672. MyKdPrint(D_PnpPower,("PowerUp Port %d\n", ch))
  1673. status = StartPortHardware(port_ext,
  1674. ch); // channel num, port index
  1675. if (status != STATUS_SUCCESS)
  1676. {
  1677. MyKdPrint(D_Error,("PortPowerUp Err1\n"))
  1678. return status;
  1679. }
  1680. MyKdPrint(D_PnpPower,("PowerUp Port %d Restore\n", ch))
  1681. RestorePortSettings(port_ext);
  1682. port_ext = port_ext->port_ext;
  1683. ++ch;
  1684. }
  1685. }
  1686. else
  1687. {
  1688. MyKdPrint(D_Error,("Not started\n"))
  1689. }
  1690. // send ROW configuration to SocketModems
  1691. //InitSocketModems(Ext);
  1692. status = STATUS_SUCCESS;
  1693. return status;
  1694. }
  1695. /*-----------------------------------------------------------------------
  1696. SerialRemoveFdo -
  1697. |-----------------------------------------------------------------------*/
  1698. NTSTATUS SerialRemoveFdo(IN PDEVICE_OBJECT pFdo)
  1699. {
  1700. PSERIAL_DEVICE_EXTENSION extension = pFdo->DeviceExtension;
  1701. MyKdPrint(D_Pnp,("SerialRemoveFdo\n"))
  1702. // Only do these things if the device has started
  1703. //(comment out 8-15-98) if (extension->FdoStarted)
  1704. {
  1705. if (extension->DeviceType == DEV_BOARD)
  1706. {
  1707. // BUGBUG, shut down this board(are we deallocating resources?)!!!
  1708. RcktDeleteBoard(extension);
  1709. if (Driver.board_ext == NULL) // no more boards, so delete driver obj
  1710. {
  1711. // Delete Driver obj
  1712. RcktDeleteDriverObj(Driver.driver_ext);
  1713. Driver.driver_ext = NULL; // no more boards
  1714. #ifdef S_VS
  1715. // to allow the driver to unload from nt50, we need to
  1716. // stop the nic-binding thread, shut down the nic
  1717. // cards and the protocol from ndis
  1718. init_stop(); // unload thread, ndis nic cards, etc
  1719. #endif
  1720. {
  1721. PDEVICE_OBJECT currentDevice = Driver.GlobalDriverObject->DeviceObject;
  1722. int i;
  1723. i = 0;
  1724. while(currentDevice)
  1725. {
  1726. currentDevice = currentDevice->NextDevice;
  1727. if (currentDevice)
  1728. ++i;
  1729. }
  1730. if (i != 0)
  1731. {
  1732. MyKdPrint(D_Pnp,("Err, %d Devices still remain\n",i))
  1733. }
  1734. else
  1735. {
  1736. MyKdPrint(D_Pnp,("Ok remove\n"))
  1737. }
  1738. }
  1739. }
  1740. }
  1741. else
  1742. {
  1743. RcktDeletePort(extension);
  1744. // must be a port fdo, kill it
  1745. }
  1746. }
  1747. MyKdPrint(D_Pnp,("End SerialRemoveFdo\n"))
  1748. return STATUS_SUCCESS;
  1749. }
  1750. #endif // NT50
  1751. /*-----------------------------------------------------------------------
  1752. This function must be called at any IRP dispatch entry point. It,
  1753. with SerialIRPEpilogue(), keeps track of all pending IRP's for the given
  1754. PDevObj.
  1755. Arguments:
  1756. PDevObj - Pointer to the device object we are tracking pending IRP's for.
  1757. Return Value:
  1758. TRUE if the device can accept IRP's.
  1759. |-----------------------------------------------------------------------*/
  1760. BOOLEAN SerialIRPPrologue(IN PSERIAL_DEVICE_EXTENSION PDevExt)
  1761. {
  1762. InterlockedIncrement(&PDevExt->PendingIRPCnt);
  1763. #ifdef NT50
  1764. return PDevExt->DevicePNPAccept == SERIAL_PNPACCEPT_OK ? TRUE : FALSE;
  1765. #else
  1766. return TRUE;
  1767. #endif
  1768. }