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.

1975 lines
56 KiB

  1. /*++
  2. Module Name:
  3. Pnp.c
  4. Abstract:
  5. This module contains the code that handles the plug and play
  6. IRPs for the serial driver.
  7. Environment:
  8. Kernel mode
  9. --*/
  10. #include "precomp.h"
  11. #if 0
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text(PAGEMX0, MoxaCreateDevObj)
  14. #pragma alloc_text(PAGEMX0, MoxaAddDevice)
  15. #pragma alloc_text(PAGEMX0, MoxaPnpDispatch)
  16. #pragma alloc_text(PAGEMX0, MoxaStartDevice)
  17. #pragma alloc_text(PAGEMX0, MoxaFinishStartDevice)
  18. #pragma alloc_text(PAGEMX0, MoxaGetPortInfo)
  19. #pragma alloc_text(PAGEMX0, MoxaDoExternalNaming)
  20. #pragma alloc_text(PAGEMX0, MoxaUndoExternalNaming)
  21. #endif // ALLOC_PRAGMA
  22. #endif
  23. //
  24. // Instantiate the GUID
  25. //
  26. #if !defined(FAR)
  27. #define FAR
  28. #endif // !defined(FAR)
  29. #include <initguid.h>
  30. DEFINE_GUID(GUID_CLASS_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08,
  31. 0x00, 0x3e, 0x30, 0x1f, 0x73);
  32. #if DBG
  33. UCHAR *SerSystemCapString[] = {
  34. "PowerSystemUnspecified",
  35. "PowerSystemWorking",
  36. "PowerSystemSleeping1",
  37. "PowerSystemSleeping2",
  38. "PowerSystemSleeping3",
  39. "PowerSystemHibernate",
  40. "PowerSystemShutdown",
  41. "PowerSystemMaximum"
  42. };
  43. UCHAR *SerDeviceCapString[] = {
  44. "PowerDeviceUnspecified",
  45. "PowerDeviceD0",
  46. "PowerDeviceD1",
  47. "PowerDeviceD2",
  48. "PowerDeviceD3",
  49. "PowerDeviceMaximum"
  50. };
  51. #endif // DBG
  52. NTSTATUS
  53. MoxaSyncCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
  54. IN PKEVENT MoxaSyncEvent)
  55. {
  56. KeSetEvent(MoxaSyncEvent, IO_NO_INCREMENT, FALSE);
  57. return STATUS_MORE_PROCESSING_REQUIRED;
  58. }
  59. NTSTATUS
  60. MoxaCreateDevObj(IN PDRIVER_OBJECT DriverObject,
  61. IN PUNICODE_STRING pDeviceObjName,
  62. IN PDEVICE_SETTINGS pSettings,
  63. OUT PDEVICE_OBJECT *NewDeviceObject)
  64. /*++
  65. Routine Description:
  66. This routine will create and initialize a functional device object to
  67. be attached to a Serial controller PDO.
  68. Arguments:
  69. DriverObject - a pointer to the driver object this is created under
  70. NewDeviceObject - a location to store the pointer to the new device object
  71. Return Value:
  72. STATUS_SUCCESS if everything was successful
  73. reason for failure otherwise
  74. --*/
  75. {
  76. PDEVICE_OBJECT deviceObject = NULL;
  77. PMOXA_DEVICE_EXTENSION pDevExt = NULL;
  78. NTSTATUS status = STATUS_SUCCESS;
  79. HANDLE pnpKey;
  80. ULONG maxBaud,rxBufferSize,txBufferSize;
  81. // PAGED_CODE ();
  82. MoxaKdPrint(MX_DBG_TRACE,("Enter MoxaCreateDevObj\n"));
  83. if (pDeviceObjName == NULL) {
  84. MoxaLogError(DriverObject, NULL, MoxaPhysicalZero, MoxaPhysicalZero,
  85. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  86. 0, NULL, 0, NULL);
  87. MoxaKdPrint(MX_DBG_ERROR,("MoxaCreateDevice: Couldn't allocate memory for device name\n"));
  88. return STATUS_SUCCESS;
  89. }
  90. //
  91. // Create the device object
  92. //
  93. MoxaKdPrint(MX_DBG_TRACE,("Create the device object\n"));
  94. status = IoCreateDevice(DriverObject, sizeof(MOXA_DEVICE_EXTENSION),
  95. pDeviceObjName, FILE_DEVICE_SERIAL_PORT, 0, TRUE,
  96. &deviceObject);
  97. if (!NT_SUCCESS(status)) {
  98. MoxaKdPrint(MX_DBG_ERROR,("MoxaAddDevice: Create device failed - %x \n",
  99. status));
  100. goto MoxaCreateDevObjError;
  101. }
  102. //ASSERT(deviceObject != NULL);
  103. //
  104. // The device object has a pointer to an area of non-paged
  105. // pool allocated for this device. This will be the device
  106. // extension. Zero it out.
  107. //
  108. pDevExt = deviceObject->DeviceExtension;
  109. RtlZeroMemory(pDevExt, sizeof(MOXA_DEVICE_EXTENSION));
  110. //
  111. // Allocate Pool and save the nt device name in the device extension.
  112. //
  113. MoxaKdPrint(MX_DBG_TRACE,("Allocate Pool and save the nt device name in the device extension\n"));
  114. pDevExt->DeviceName.Buffer =
  115. ExAllocatePool(PagedPool, pDeviceObjName->Length + sizeof(WCHAR));
  116. if (!pDevExt->DeviceName.Buffer) {
  117. MoxaLogError(
  118. DriverObject,
  119. NULL,
  120. MoxaPhysicalZero,
  121. MoxaPhysicalZero,
  122. 0,
  123. 0,
  124. 0,
  125. 19,
  126. STATUS_SUCCESS,
  127. SERIAL_INSUFFICIENT_RESOURCES,
  128. 0,
  129. NULL,
  130. 0,
  131. NULL
  132. );
  133. MoxaKdPrint(MX_DBG_ERROR,
  134. ("MoxaAddDevice: Couldn't allocate memory for DeviceName\n"));
  135. status = STATUS_INSUFFICIENT_RESOURCES;
  136. goto MoxaCreateDevObjError;
  137. }
  138. pDevExt->DeviceName.MaximumLength = pDeviceObjName->Length
  139. + sizeof(WCHAR);
  140. //
  141. // Zero fill it.
  142. //
  143. RtlZeroMemory(pDevExt->DeviceName.Buffer,
  144. pDevExt->DeviceName.MaximumLength);
  145. RtlAppendUnicodeStringToString(&pDevExt->DeviceName, pDeviceObjName);
  146. //
  147. // Set up the device extension.
  148. //
  149. MoxaKdPrint(MX_DBG_TRACE,("Set up the device extension\n"));
  150. pDevExt->PortBase = pSettings->BaseAddress;
  151. pDevExt->PortOfs = pSettings->BaseAddress + Extern_table + Extern_size * pSettings->PortIndex;
  152. pDevExt->DeviceObject = deviceObject;
  153. pDevExt->DriverObject = DriverObject;
  154. switch (pSettings->BoardType) {
  155. case C218ISA :
  156. case C218PCI :
  157. case CP204J :
  158. maxBaud = 921600L;
  159. rxBufferSize = C218rx_size;
  160. txBufferSize = C218tx_size;
  161. break;
  162. default :
  163. maxBaud = 460800L;
  164. switch (pSettings->NumPorts) {
  165. case 8 :
  166. rxBufferSize = C320p8rx_size;
  167. txBufferSize = C320p8tx_size;
  168. break;
  169. case 16 :
  170. rxBufferSize = C320p16rx_size;
  171. txBufferSize = C320p16tx_size;
  172. break;
  173. case 24 :
  174. rxBufferSize = C320p24rx_size;
  175. txBufferSize = C320p24tx_size;
  176. break;
  177. case 32 :
  178. rxBufferSize = C320p32rx_size;
  179. txBufferSize = C320p32tx_size;
  180. break;
  181. }
  182. break;
  183. }
  184. MoxaKdPrint(MX_DBG_TRACE,("Init port,%d,%d,%d\n",rxBufferSize,txBufferSize,maxBaud));
  185. InitPort(pDevExt,rxBufferSize ,txBufferSize ,maxBaud);
  186. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  187. *NewDeviceObject = deviceObject;
  188. MoxaKdPrint(MX_DBG_TRACE,("Leave MoxaCreateDevObj\n") );
  189. return STATUS_SUCCESS;
  190. MoxaCreateDevObjError:
  191. MoxaKdPrint(MX_DBG_ERROR,("MoxaCreateDevObj Error, Cleaning up\n") );
  192. //
  193. // Free the allocated strings for the NT and symbolic names if they exist.
  194. //
  195. if (pDevExt) {
  196. if (pDevExt->DeviceName.Buffer != NULL) {
  197. ExFreePool(pDevExt->DeviceName.Buffer);
  198. }
  199. }
  200. if (deviceObject) {
  201. IoDeleteDevice(deviceObject);
  202. }
  203. *NewDeviceObject = NULL;
  204. MoxaKdPrint(MX_DBG_TRACE,("Leave MoxaCreateDevObj\n") );
  205. return status;
  206. }
  207. NTSTATUS
  208. MoxaAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PPdo)
  209. /*++
  210. Routine Description:
  211. This routine creates a functional device object for com ports in the
  212. system and attaches them to the physical device objects for the ports
  213. Arguments:
  214. DriverObject - a pointer to the object for this driver
  215. PPdo - a pointer to the PDO in the stack we need to attach to
  216. Return Value:
  217. status from device creation and initialization
  218. --*/
  219. {
  220. PDEVICE_OBJECT pNewDevObj = NULL;
  221. PDEVICE_OBJECT pLowerDevObj = NULL;
  222. NTSTATUS status;
  223. PMOXA_DEVICE_EXTENSION pDevExt;
  224. HANDLE keyHandle;
  225. UNICODE_STRING deviceObjName;
  226. DEVICE_SETTINGS settings;
  227. IO_STATUS_BLOCK IoStatusBlock;
  228. KEVENT event;
  229. ULONG comNo,i;
  230. WCHAR comName[8];
  231. //PAGED_CODE();
  232. MoxaKdPrint(MX_DBG_TRACE,("Enter MoxaAddDevice with PPdo 0x%x\n", PPdo));
  233. if (PPdo == NULL) {
  234. //
  235. // Return no more devices
  236. //
  237. MoxaKdPrint(MX_DBG_TRACE,("NO_MORE_ENTRIES\n"));
  238. return (STATUS_NO_MORE_ENTRIES);
  239. }
  240. KeInitializeEvent(&event, NotificationEvent, FALSE);
  241. MoxaKdPrint(MX_DBG_TRACE,("MoxaIoSyncIoctlEx\n"));
  242. status = MoxaIoSyncIoctlEx(IOCTL_MOXA_INTERNAL_BASIC_SETTINGS, TRUE,
  243. PPdo, &event, &IoStatusBlock,
  244. NULL, 0, &settings,
  245. sizeof(DEVICE_SETTINGS));
  246. MoxaKdPrint(MX_DBG_TRACE,("status=%x\n",status));
  247. if (!NT_SUCCESS(status)) {
  248. MoxaKdPrint (MX_DBG_TRACE,("Get settings Fail\n"));
  249. status = STATUS_UNSUCCESSFUL;
  250. return(status);
  251. }
  252. status = IoOpenDeviceRegistryKey(PPdo, PLUGPLAY_REGKEY_DEVICE,
  253. STANDARD_RIGHTS_READ, &keyHandle);
  254. if (!NT_SUCCESS(status)) {
  255. //
  256. // This is a fatal error. If we can't get to our registry key,
  257. // we are sunk.
  258. //
  259. MoxaKdPrint (MX_DBG_TRACE,
  260. ("IoOpenDeviceRegistryKey failed - %x\n", status));
  261. return (status);
  262. }
  263. status = MoxaGetRegistryKeyValue(
  264. keyHandle,
  265. L"PortName",
  266. sizeof(L"PortName"),
  267. comName,
  268. sizeof(comName),
  269. &i);
  270. ZwClose(keyHandle);
  271. if (status == STATUS_SUCCESS) {
  272. comName[i >>1] = (WCHAR )0;
  273. MoxaKdPrint (MX_DBG_TRACE,("Get settings OK\n"));
  274. MoxaKdPrint (MX_DBG_TRACE,("BoardIndex = %x\n",settings.BoardIndex));
  275. MoxaKdPrint (MX_DBG_TRACE,("PortIndex = %x\n",settings.PortIndex));
  276. MoxaKdPrint (MX_DBG_TRACE,("InterfaceType = %x\n",settings.InterfaceType));
  277. MoxaKdPrint (MX_DBG_TRACE,("BusNumber = %x\n",settings.BusNumber));
  278. MoxaKdPrint (MX_DBG_TRACE,("OriginalBaseAddress = %x\n",settings.OriginalBaseAddress.LowPart));
  279. MoxaKdPrint (MX_DBG_TRACE,("OriginalAckPort = %x\n",settings.OriginalAckPort.LowPart));
  280. MoxaKdPrint (MX_DBG_TRACE,("BaseAddress = %x\n",settings.BaseAddress));
  281. MoxaKdPrint (MX_DBG_TRACE,("AckPort = %x\n",settings.AckPort));
  282. MoxaKdPrint (MX_DBG_TRACE,("InterruptVector = %x\n",settings.Interrupt.Vector));
  283. MoxaKdPrint (MX_DBG_TRACE,("InterruptLevel = %x\n",settings.Interrupt.Level));
  284. MoxaKdPrint (MX_DBG_TRACE,("InterruptAffinity = %x\n",settings.Interrupt.Affinity));
  285. // MoxaKdPrint (MX_DBG_TRACE,("ComName = %ws\n",comName));
  286. }
  287. else {
  288. MoxaKdPrint (MX_DBG_TRACE,("Get settings Fail\n"));
  289. status = STATUS_UNSUCCESSFUL;
  290. return(status);
  291. }
  292. //
  293. // Zero out allocated memory pointers so we know if they must be freed
  294. //
  295. deviceObjName.MaximumLength = DEVICE_OBJECT_NAME_LENGTH * sizeof(WCHAR)
  296. + sizeof(WCHAR);
  297. deviceObjName.Buffer = ExAllocatePool(PagedPool,deviceObjName.MaximumLength);
  298. if (deviceObjName.Buffer == NULL) {
  299. MoxaKdPrint(MX_DBG_ERROR,("Unable to allocate buffer for device object name\n"));
  300. status = STATUS_INSUFFICIENT_RESOURCES;
  301. return (status);
  302. }
  303. RtlZeroMemory(deviceObjName.Buffer,deviceObjName.MaximumLength);
  304. deviceObjName.Length = 0;
  305. RtlAppendUnicodeToString(&deviceObjName, L"\\Device\\MxcardB00P000");
  306. deviceObjName.Buffer[15] = (WCHAR)('0' + settings.BoardIndex / 10);
  307. deviceObjName.Buffer[16] = (WCHAR)('0' + settings.BoardIndex % 10);
  308. deviceObjName.Buffer[18] = (WCHAR)('0' + settings.PortIndex / 100);
  309. deviceObjName.Buffer[19] = (WCHAR)('0' + (settings.PortIndex % 100)/10);
  310. deviceObjName.Buffer[20] = (WCHAR)('0' + (settings.PortIndex % 100)%10);
  311. // MoxaKdPrint(MX_DBG_TRACE,("Device->%ws\n",deviceObjName.Buffer));
  312. //
  313. // create and initialize the new device object
  314. //
  315. status = MoxaCreateDevObj(DriverObject, &deviceObjName,&settings,&pNewDevObj);
  316. if (deviceObjName.Buffer)
  317. ExFreePool(deviceObjName.Buffer);
  318. if (!NT_SUCCESS(status)) {
  319. MoxaKdPrint(MX_DBG_ERROR,
  320. ("MoxaAddDevice - error creating new devobj [%#08lx]\n",
  321. status));
  322. return status;
  323. }
  324. //
  325. // Layer our DO on top of the lower device object
  326. // The return value is a pointer to the device object to which the
  327. // DO is actually attached.
  328. //
  329. pLowerDevObj = IoAttachDeviceToDeviceStack(pNewDevObj, PPdo);
  330. //
  331. // No status. Do the best we can.
  332. //
  333. //ASSERT(pLowerDevObj != NULL);
  334. pDevExt = pNewDevObj->DeviceExtension;
  335. pDevExt->LowerDeviceObject = pLowerDevObj;
  336. pDevExt->Pdo = PPdo;
  337. //
  338. // Make the device visible via a device association as well.
  339. // The reference string is the eight digit device index
  340. //
  341. status = IoRegisterDeviceInterface(PPdo, (LPGUID)&GUID_CLASS_COMPORT,
  342. NULL, &pDevExt->DeviceClassSymbolicName);
  343. if (!NT_SUCCESS(status)) {
  344. /*
  345. MoxaKdPrint (MX_DBG_ERROR,("Couldn't register class association\n"
  346. "------- for port %wZ\n",
  347. &pDevExt->DeviceName));
  348. */
  349. pDevExt->DeviceClassSymbolicName.Buffer = NULL;
  350. }
  351. //
  352. // Specify that this driver only supports buffered IO. This basically
  353. // means that the IO system copies the users data to and from
  354. // system supplied buffers.
  355. //
  356. // Also specify that we are power pagable.
  357. //
  358. pNewDevObj->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
  359. //
  360. // Fill in global data
  361. //
  362. for (i = 0; i < MAX_CARD; i++)
  363. if ((MoxaGlobalData->CardType[i])
  364. &&(MoxaGlobalData->BoardIndex[i] == settings.BoardIndex))
  365. break;
  366. if (i == MAX_CARD) {
  367. for (i = 0; i < MAX_CARD; i++)
  368. if (!MoxaGlobalData->CardType[i])
  369. break;
  370. MoxaGlobalData->BoardIndex[i] = settings.BoardIndex;
  371. }
  372. pDevExt->BoardNo = i;
  373. MoxaKdPrint(MX_DBG_TRACE,("Board Number = %d\n",pDevExt->BoardNo));
  374. if (!MoxaGlobalData->CardType[pDevExt->BoardNo]) {
  375. MoxaGlobalData->PciBusNum[pDevExt->BoardNo] = (USHORT)settings.BusNumber;
  376. // USHORT PciDevNum[MAX_CARD];
  377. MoxaGlobalData->InterfaceType[pDevExt->BoardNo] = settings.InterfaceType;
  378. MoxaGlobalData->IntVector[pDevExt->BoardNo]= settings.Interrupt.Vector;
  379. RtlCopyMemory(&MoxaGlobalData->PciIntAckPort[pDevExt->BoardNo],&settings.OriginalAckPort,sizeof(PHYSICAL_ADDRESS));
  380. RtlCopyMemory(&MoxaGlobalData->BankAddr[pDevExt->BoardNo],&settings.OriginalBaseAddress,sizeof(PHYSICAL_ADDRESS));
  381. MoxaGlobalData->PciIntAckBase[pDevExt->BoardNo] = settings.AckPort;
  382. MoxaGlobalData->CardType[pDevExt->BoardNo] = settings.BoardType;
  383. MoxaGlobalData->CardBase[pDevExt->BoardNo] = settings.BaseAddress;
  384. MoxaGlobalData->IntNdx[pDevExt->BoardNo] = (PUSHORT)(settings.BaseAddress + IRQindex);
  385. MoxaGlobalData->IntPend[pDevExt->BoardNo] = settings.BaseAddress + IRQpending;
  386. MoxaGlobalData->IntTable[pDevExt->BoardNo] = settings.BaseAddress + IRQtable;
  387. MoxaGlobalData->NumPorts[pDevExt->BoardNo] = settings.NumPorts;
  388. MoxaKdPrint(MX_DBG_TRACE,("Int ndx,pend,table = %x,%x,%x\n",
  389. MoxaGlobalData->IntNdx[pDevExt->BoardNo],
  390. MoxaGlobalData->IntPend[pDevExt->BoardNo],
  391. MoxaGlobalData->IntTable[pDevExt->BoardNo])
  392. );
  393. }
  394. pDevExt->PortIndex = settings.PortIndex;
  395. pDevExt->PortNo = pDevExt->BoardNo*MAXPORT_PER_CARD + settings.PortIndex;
  396. RtlZeroMemory(pDevExt->DosName,
  397. sizeof(pDevExt->DosName));
  398. RtlCopyMemory(pDevExt->DosName,
  399. comName,
  400. wcslen(comName)*sizeof(WCHAR)
  401. );
  402. comNo = wcslen(comName);
  403. if (comNo >= 4) {
  404. comNo -= 3;
  405. if (comNo >= 3) {
  406. comNo = (comName[5] - '0') +
  407. (comName[4] - '0')*10 +
  408. (comName[3] - '0')*100;
  409. }
  410. else if (comNo >= 2) {
  411. comNo = (comName[4] - '0') +
  412. (comName[3] - '0')*10;
  413. }
  414. else if (comNo >= 1) {
  415. comNo = (comName[3] - '0');
  416. }
  417. }
  418. MoxaKdPrint(MX_DBG_TRACE,("ComNo=%d/len=%d\n",comNo,wcslen(comName)));
  419. if ((comNo > 0) && (comNo <= MAX_COM)) {
  420. MoxaExtension[comNo] = pDevExt;
  421. MoxaGlobalData->ComNo[pDevExt->BoardNo][pDevExt->PortIndex] = (USHORT)comNo;
  422. }
  423. else
  424. comNo = 0;
  425. MoxaGlobalData->Extension[pDevExt->PortNo] = pDevExt;
  426. MoxaKdPrint(MX_DBG_TRACE,("Leave MoxaAddDevice\n"));
  427. return status;
  428. }
  429. NTSTATUS
  430. MoxaFinishStartDevice(IN PDEVICE_OBJECT PDevObj)
  431. /*++
  432. Routine Description:
  433. This routine does serial-specific procedures to start a device. It
  434. does this either for a legacy device detected by its registry entries,
  435. or for a PnP device after the start IRP has been sent down the stack.
  436. Arguments:
  437. PDevObj - Pointer to the devobj that is starting
  438. Return Value:
  439. STATUS_SUCCESS on success, something else appropriate on failure
  440. --*/
  441. {
  442. PMOXA_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  443. NTSTATUS status = STATUS_SUCCESS;
  444. HANDLE pnpKey;
  445. ULONG i,com,one = 1;
  446. PKINTERRUPT moxaInterrupt;
  447. ULONG systemVector;
  448. KIRQL irql;
  449. KAFFINITY processorAffinity;
  450. PMOXA_CISR_SW cisrsw;
  451. PMOXA_MULTIPORT_DISPATCH dispatch;
  452. //PAGED_CODE();
  453. //
  454. // See if this is a restart, and if so don't reallocate the world
  455. //
  456. if (pDevExt->Flags & SERIAL_FLAGS_STOPPED) {
  457. MoxaClearFlags(pDevExt, SERIAL_FLAGS_STOPPED);
  458. pDevExt->PNPState = SERIAL_PNP_RESTARTING;
  459. }
  460. //
  461. // See if we are in the proper power state.
  462. //
  463. if (pDevExt->PowerState != PowerDeviceD0) {
  464. status = MoxaGotoPowerState(pDevExt->Pdo, pDevExt, PowerDeviceD0);
  465. if (!NT_SUCCESS(status)) {
  466. goto MoxaFinishStartDeviceError;
  467. }
  468. }
  469. //
  470. // The hardware that is set up to NOT interrupt, connect an interrupt.
  471. //
  472. if (!(MoxaGlobalData->Interrupt[pDevExt->BoardNo])
  473. && MoxaGlobalData->IntVector[pDevExt->BoardNo]) {
  474. KINTERRUPT_MODE interruptMode;
  475. /*
  476. MoxaKdPrint(MX_DBG_ERROR,("About to connect to interrupt for port %wZ\n"
  477. "------- address of extension is %x\n"
  478. "------- interface of device is %x\n"
  479. "------- bus number of device is %x\n"
  480. "------- int. vector of device is %x\n"
  481. "------- type of device is %d\n",
  482. &pDevExt->DeviceName, pDevExt,
  483. MoxaGlobalData->InterfaceType[pDevExt->BoardNo],
  484. MoxaGlobalData->PciBusNum[pDevExt->BoardNo],
  485. MoxaGlobalData->IntVector[pDevExt->BoardNo],
  486. MoxaGlobalData->CardType[pDevExt->BoardNo])
  487. );
  488. */
  489. cisrsw = ExAllocatePool(
  490. NonPagedPool,
  491. sizeof(MOXA_CISR_SW)
  492. );
  493. if (!cisrsw) {
  494. /*
  495. MoxaKdPrint(MX_DBG_ERROR,("Couldn't allocate CISR_SW for "
  496. "%wZ\n", &pDevExt->DeviceName));
  497. */
  498. status = SERIAL_INSUFFICIENT_RESOURCES;
  499. MoxaLogError(PDevObj->DriverObject, NULL,
  500. MoxaPhysicalZero,
  501. MoxaPhysicalZero, 0, 0, 0, 1, status,
  502. SERIAL_INSUFFICIENT_RESOURCES,
  503. pDevExt->DeviceName.Length + sizeof(WCHAR),
  504. pDevExt->DeviceName.Buffer, 0, NULL);
  505. goto MoxaFinishStartDeviceError;
  506. }
  507. dispatch = &cisrsw->Dispatch;
  508. dispatch->BoardNo = pDevExt->BoardNo;
  509. dispatch->GlobalData = MoxaGlobalData;
  510. for (i = 0; i < MAX_CARD; i++)
  511. if ((MoxaGlobalData->Interrupt[i]) &&
  512. (MoxaGlobalData->IntVector[i] == MoxaGlobalData->IntVector[pDevExt->BoardNo])&&
  513. (MoxaGlobalData->InterfaceType[i] == MoxaGlobalData->InterfaceType[pDevExt->BoardNo]))
  514. break;
  515. if (i != MAX_CARD) {
  516. MoxaGlobalData->Interrupt[pDevExt->BoardNo] =
  517. pDevExt->Interrupt = MoxaGlobalData->Interrupt[i];
  518. MoxaGlobalData->Irql[pDevExt->BoardNo] = MoxaGlobalData->Irql[i];
  519. MoxaGlobalData->ProcessorAffinity[pDevExt->BoardNo] = MoxaGlobalData->ProcessorAffinity[i];
  520. pDevExt->InterruptShareList=
  521. MoxaGlobalData->InterruptShareList[pDevExt->BoardNo] = MoxaGlobalData->InterruptShareList[i];
  522. InsertTailList(pDevExt->InterruptShareList,&cisrsw->SharerList);
  523. MoxaKdPrint(MX_DBG_ERROR,("Interrupt share with %d/%x\n",i,
  524. pDevExt->InterruptShareList));
  525. }
  526. else {
  527. /* for debug
  528. PLIST_ENTRY interruptEntry;
  529. PMOXA_CISR_SW cisrsw1;
  530. */
  531. MoxaGlobalData->InterruptShareList[pDevExt->BoardNo] = ExAllocatePool(
  532. NonPagedPool,
  533. sizeof(LIST_ENTRY)
  534. );
  535. if (!MoxaGlobalData->InterruptShareList[pDevExt->BoardNo]) {
  536. /*
  537. MoxaKdPrint(MX_DBG_ERROR,("Couldn't allocate InterruptShareList for "
  538. "%wZ\n", &pDevExt->DeviceName));
  539. */
  540. ExFreePool(cisrsw);
  541. status = SERIAL_INSUFFICIENT_RESOURCES;
  542. MoxaLogError(PDevObj->DriverObject, NULL,
  543. MoxaPhysicalZero,
  544. MoxaPhysicalZero, 0, 0, 0, 1, status,
  545. SERIAL_INSUFFICIENT_RESOURCES,
  546. pDevExt->DeviceName.Length + sizeof(WCHAR),
  547. pDevExt->DeviceName.Buffer, 0, NULL);
  548. goto MoxaFinishStartDeviceError;
  549. }
  550. pDevExt->InterruptShareList=MoxaGlobalData->InterruptShareList[pDevExt->BoardNo];
  551. InitializeListHead(pDevExt->InterruptShareList);
  552. InsertTailList(pDevExt->InterruptShareList,&cisrsw->SharerList);
  553. /*
  554. interruptEntry = interruptEntry->Flink;
  555. MoxaKdPrint(MX_DBG_ERROR,("list entry %x/%x/%x\n",interruptEntry,interruptEntry->Flink,
  556. interruptEntry->Blink));
  557. interruptEntry = pDevExt->InterruptShareList;
  558. MoxaKdPrint(MX_DBG_ERROR,("list head %x/%x/%x\n",interruptEntry,interruptEntry->Flink,
  559. interruptEntry->Blink));
  560. if (IsListEmpty(MoxaGlobalData->InterruptShareList[pDevExt->BoardNo]))
  561. MoxaKdPrint(MX_DBG_ERROR,("list empty\n"));
  562. cisrsw1 = CONTAINING_RECORD( interruptEntry,
  563. MOXA_CISR_SW,
  564. SharerList
  565. );
  566. MoxaKdPrint(MX_DBG_ERROR,("cisrsw %x/%x\n",cisrsw,cisrsw1));
  567. */
  568. systemVector = HalGetInterruptVector(
  569. (ULONG)MoxaGlobalData->InterfaceType[pDevExt->BoardNo],
  570. (ULONG)MoxaGlobalData->PciBusNum[pDevExt->BoardNo],
  571. MoxaGlobalData->IntVector[pDevExt->BoardNo],
  572. MoxaGlobalData->IntVector[pDevExt->BoardNo],
  573. &irql,
  574. &processorAffinity
  575. );
  576. MoxaKdPrint(MX_DBG_ERROR,("System Vector = %x,%x,%x,%x\n",systemVector,irql,processorAffinity,
  577. MoxaGlobalData->InterruptShareList[pDevExt->BoardNo]));
  578. if (MoxaGlobalData->InterfaceType[pDevExt->BoardNo] == PCIBus)
  579. interruptMode = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
  580. else
  581. interruptMode = CM_RESOURCE_INTERRUPT_LATCHED;
  582. status = IoConnectInterrupt(
  583. &moxaInterrupt,
  584. MoxaISR,
  585. MoxaGlobalData->InterruptShareList[pDevExt->BoardNo],
  586. NULL,
  587. systemVector,
  588. irql,
  589. irql,
  590. interruptMode,
  591. TRUE,
  592. processorAffinity,
  593. FALSE
  594. );
  595. if (!NT_SUCCESS(status)) {
  596. /*
  597. MoxaKdPrint(MX_DBG_ERROR,("Couldn't connect to interrupt for "
  598. "%wZ(status=%x)\n", &pDevExt->DeviceName,status));
  599. */
  600. ExFreePool(cisrsw);
  601. status = SERIAL_UNREPORTED_IRQL_CONFLICT;
  602. MoxaLogError(PDevObj->DriverObject, NULL,
  603. MoxaPhysicalZero,
  604. MoxaPhysicalZero, 0, 0, 0, 1, status,
  605. SERIAL_UNREPORTED_IRQL_CONFLICT,
  606. pDevExt->DeviceName.Length + sizeof(WCHAR),
  607. pDevExt->DeviceName.Buffer, 0, NULL);
  608. goto MoxaFinishStartDeviceError;
  609. }
  610. MoxaGlobalData->Interrupt[pDevExt->BoardNo] =
  611. pDevExt->Interrupt = moxaInterrupt;
  612. MoxaGlobalData->Irql[pDevExt->BoardNo] = irql;
  613. MoxaGlobalData->ProcessorAffinity[pDevExt->BoardNo] = processorAffinity;
  614. }
  615. }
  616. else {
  617. pDevExt->Interrupt = MoxaGlobalData->Interrupt[pDevExt->BoardNo];
  618. pDevExt->InterruptShareList=MoxaGlobalData->InterruptShareList[pDevExt->BoardNo];
  619. }
  620. //
  621. // Add the PDevObj to the master list
  622. //
  623. // InsertTailList(&MoxaGlobalData->AllDevObjs, &pDevExt->AllDevObjs);
  624. //
  625. // This should set up everything as it should be when
  626. // a device is to be opened. We do need to lower the
  627. // modem lines, and disable the recalcitrant fifo
  628. // so that it will show up if the user boots to dos.
  629. //
  630. /*
  631. KeSynchronizeExecution( //Disables the fifo.
  632. pDevExt->Interrupt,
  633. SerialMarkClose,
  634. pDevExt
  635. );
  636. */
  637. if (pDevExt->PNPState == SERIAL_PNP_ADDED ) {
  638. //
  639. // Do the external naming now that the device is accessible.
  640. //
  641. status = MoxaDoExternalNaming(pDevExt, pDevExt->DeviceObject->
  642. DriverObject);
  643. if (!NT_SUCCESS(status)) {
  644. MoxaKdPrint(MX_DBG_ERROR,("External Naming Failed - Status %x\n",
  645. status));
  646. //
  647. // Allow the device to start anyhow
  648. //
  649. status = STATUS_SUCCESS;
  650. // goto MoxaFinishStartDeviceError;
  651. }
  652. } else {
  653. MoxaKdPrint(MX_DBG_ERROR,("Not doing external naming -- state is %x\n",
  654. pDevExt->PNPState));
  655. }
  656. MoxaFinishStartDeviceError:;
  657. if (!NT_SUCCESS (status)) {
  658. MoxaKdPrint(MX_DBG_TRACE,("Cleaning up failed start\n"));
  659. //
  660. // Resources created by this routine will be cleaned up by the remove
  661. //
  662. if (pDevExt->PNPState == SERIAL_PNP_RESTARTING) {
  663. //
  664. // Kill all that lives and breathes -- we'll clean up the
  665. // rest on the impending remove
  666. //
  667. MoxaKillPendingIrps(PDevObj);
  668. //
  669. // In fact, pretend we're removing so we don't take any
  670. // more irps
  671. //
  672. MoxaSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  673. MoxaClearFlags(pDevExt, SERIAL_FLAGS_STARTED);
  674. }
  675. } else { // SUCCESS
  676. //
  677. // Fill in WMI hardware data
  678. //
  679. pDevExt->WmiHwData.IrqNumber = MoxaGlobalData->Irql[pDevExt->BoardNo];
  680. pDevExt->WmiHwData.IrqLevel = MoxaGlobalData->Irql[pDevExt->BoardNo];
  681. pDevExt->WmiHwData.IrqVector = MoxaGlobalData->IntVector[pDevExt->BoardNo];
  682. pDevExt->WmiHwData.IrqAffinityMask =MoxaGlobalData->ProcessorAffinity[pDevExt->BoardNo];
  683. pDevExt->WmiHwData.InterruptType = SERIAL_WMI_INTTYPE_LATCHED;
  684. pDevExt->WmiHwData.BaseIOAddress = (ULONGLONG)MoxaGlobalData->BankAddr[pDevExt->BoardNo].LowPart;
  685. //
  686. // Fill in WMI device state data (as defaults)
  687. //
  688. pDevExt->WmiCommData.BaudRate = pDevExt->CurrentBaud;
  689. switch (pDevExt->DataMode & MOXA_DATA_MASK) {
  690. case MOXA_5_DATA :
  691. pDevExt->WmiCommData.BitsPerByte = 5;
  692. break;
  693. case MOXA_6_DATA :
  694. pDevExt->WmiCommData.BitsPerByte = 6;
  695. break;
  696. case MOXA_7_DATA :
  697. pDevExt->WmiCommData.BitsPerByte = 7;
  698. break;
  699. case MOXA_8_DATA :
  700. default :
  701. pDevExt->WmiCommData.BitsPerByte = 8;
  702. break;
  703. }
  704. pDevExt->WmiCommData.ParityCheckEnable = (pDevExt->DataMode & MOXA_NONE_PARITY)
  705. ? FALSE : TRUE;
  706. switch (pDevExt->DataMode & MOXA_PARITY_MASK) {
  707. case MOXA_NONE_PARITY:
  708. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE;
  709. break;
  710. case MOXA_ODD_PARITY:
  711. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_ODD;
  712. break;
  713. case MOXA_EVEN_PARITY:
  714. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_EVEN;
  715. break;
  716. case MOXA_MARK_PARITY:
  717. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_MARK;
  718. break;
  719. case MOXA_SPACE_PARITY:
  720. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_SPACE;
  721. break;
  722. default:
  723. ASSERTMSG(0, "SERIAL: Illegal Parity setting for WMI");
  724. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE;
  725. break;
  726. }
  727. switch (pDevExt->DataMode & MOXA_STOP_MASK) {
  728. case MOXA_1_5_STOP :
  729. pDevExt->WmiCommData.StopBits = SERIAL_WMI_STOP_1_5;
  730. break;
  731. case MOXA_2_STOP :
  732. pDevExt->WmiCommData.StopBits = SERIAL_WMI_STOP_2;
  733. break;
  734. case MOXA_1_STOP :
  735. default :
  736. pDevExt->WmiCommData.StopBits = SERIAL_WMI_STOP_1;
  737. break;
  738. }
  739. pDevExt->WmiCommData.XoffCharacter = pDevExt->SpecialChars.XoffChar;
  740. pDevExt->WmiCommData.XoffXmitThreshold = pDevExt->HandFlow.XoffLimit;
  741. pDevExt->WmiCommData.XonCharacter = pDevExt->SpecialChars.XonChar;
  742. pDevExt->WmiCommData.XonXmitThreshold = pDevExt->HandFlow.XonLimit;
  743. pDevExt->WmiCommData.MaximumBaudRate
  744. = pDevExt->MaxBaud;
  745. pDevExt->WmiCommData.MaximumOutputBufferSize = pDevExt->TxBufferSize;
  746. pDevExt->WmiCommData.MaximumInputBufferSize = pDevExt->RxBufferSize;
  747. pDevExt->WmiCommData.Support16BitMode = FALSE;
  748. pDevExt->WmiCommData.SupportDTRDSR = TRUE;
  749. pDevExt->WmiCommData.SupportIntervalTimeouts = TRUE;
  750. pDevExt->WmiCommData.SupportParityCheck = TRUE;
  751. pDevExt->WmiCommData.SupportRTSCTS = TRUE;
  752. pDevExt->WmiCommData.SupportXonXoff = TRUE;
  753. pDevExt->WmiCommData.SettableBaudRate = TRUE;
  754. pDevExt->WmiCommData.SettableDataBits = TRUE;
  755. pDevExt->WmiCommData.SettableFlowControl = TRUE;
  756. pDevExt->WmiCommData.SettableParity = TRUE;
  757. pDevExt->WmiCommData.SettableParityCheck = TRUE;
  758. pDevExt->WmiCommData.SettableStopBits = TRUE;
  759. pDevExt->WmiCommData.IsBusy = FALSE;
  760. if (pDevExt->PNPState == SERIAL_PNP_ADDED) {
  761. PULONG countSoFar = &IoGetConfigurationInformation()->SerialCount;
  762. (*countSoFar)++;
  763. //
  764. // Register for WMI
  765. //
  766. pDevExt->WmiLibInfo.GuidCount = sizeof(MoxaWmiGuidList) /
  767. sizeof(WMIGUIDREGINFO);
  768. pDevExt->WmiLibInfo.GuidList = MoxaWmiGuidList;
  769. pDevExt->WmiLibInfo.QueryWmiRegInfo = MoxaQueryWmiRegInfo;
  770. pDevExt->WmiLibInfo.QueryWmiDataBlock = MoxaQueryWmiDataBlock;
  771. pDevExt->WmiLibInfo.SetWmiDataBlock = MoxaSetWmiDataBlock;
  772. pDevExt->WmiLibInfo.SetWmiDataItem = MoxaSetWmiDataItem;
  773. pDevExt->WmiLibInfo.ExecuteWmiMethod = NULL;
  774. pDevExt->WmiLibInfo.WmiFunctionControl = NULL;
  775. IoWMIRegistrationControl(PDevObj, WMIREG_ACTION_REGISTER);
  776. }
  777. if (pDevExt->PNPState == SERIAL_PNP_RESTARTING) {
  778. //
  779. // Release the stalled IRP's
  780. //
  781. MoxaUnstallIrps(pDevExt);
  782. }
  783. pDevExt->PNPState = SERIAL_PNP_STARTED;
  784. MoxaClearAccept(pDevExt, ~SERIAL_PNPACCEPT_OK);
  785. MoxaSetFlags(pDevExt, SERIAL_FLAGS_STARTED);
  786. /*
  787. MoxaLogError(PDevObj->DriverObject, NULL,
  788. MoxaPhysicalZero,
  789. MoxaPhysicalZero, 0, 0, 0, 1, status,
  790. SERIAL_PORT_FOUND,
  791. pDevExt->DosName.Length + sizeof(WCHAR),
  792. pDevExt->DosName.Buffer, 0, NULL);
  793. */
  794. }
  795. MoxaKdPrint(MX_DBG_TRACE,("leaving MoxaFinishStartDevice\n"));
  796. return status;
  797. }
  798. NTSTATUS
  799. MoxaStartDevice(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
  800. /*++
  801. Routine Description:
  802. This routine first passes the start device Irp down the stack then
  803. it picks up the resources for the device, ititializes, puts it on any
  804. appropriate lists (i.e shared interrupt or interrupt status) and
  805. connects the interrupt.
  806. Arguments:
  807. PDevObj - Pointer to the device object for this device
  808. PIrp - Pointer to the IRP for the current request
  809. Return Value:
  810. Return status
  811. --*/
  812. {
  813. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  814. NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  815. PMOXA_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  816. PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
  817. PKEVENT pStartEvent;
  818. //PAGED_CODE();
  819. pStartEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  820. if (pStartEvent == NULL) {
  821. PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  822. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  823. return STATUS_INSUFFICIENT_RESOURCES;
  824. }
  825. KeInitializeEvent(pStartEvent, SynchronizationEvent, FALSE);
  826. //
  827. // Pass this down to the next device object
  828. //
  829. KeInitializeEvent(pStartEvent, SynchronizationEvent,
  830. FALSE);
  831. IoCopyCurrentIrpStackLocationToNext(PIrp);
  832. IoSetCompletionRoutine(PIrp, MoxaSyncCompletion,
  833. pStartEvent, TRUE, TRUE, TRUE);
  834. status = IoCallDriver(pLowerDevObj, PIrp);
  835. //
  836. // Wait for lower drivers to be done with the Irp
  837. //
  838. if (status == STATUS_PENDING) {
  839. KeWaitForSingleObject (pStartEvent, Executive, KernelMode,
  840. FALSE, NULL);
  841. status = PIrp->IoStatus.Status;
  842. }
  843. ExFreePool(pStartEvent);
  844. if (!NT_SUCCESS(status)) {
  845. MoxaKdPrint(MX_DBG_TRACE,("error with IoCallDriver %x\n", status));
  846. return status;
  847. }
  848. //
  849. // Do the serial specific items to start the device
  850. //
  851. status = MoxaFinishStartDevice(PDevObj);
  852. return status;
  853. }
  854. NTSTATUS
  855. MoxaDoExternalNaming(IN PMOXA_DEVICE_EXTENSION PDevExt,
  856. IN PDRIVER_OBJECT PDrvObj)
  857. /*++
  858. Routine Description:
  859. This routine will be used to create a symbolic link
  860. to the driver name in the given object directory.
  861. It will also create an entry in the device map for
  862. this device - IF we could create the symbolic link.
  863. Arguments:
  864. Extension - Pointer to the device extension.
  865. Return Value:
  866. None.
  867. --*/
  868. {
  869. NTSTATUS status = STATUS_SUCCESS;
  870. UNICODE_STRING linkName;
  871. PDEVICE_OBJECT pLowerDevObj, pDevObj;
  872. ULONG bufLen,i;
  873. //PAGED_CODE();
  874. pDevObj = PDevExt->DeviceObject;
  875. pLowerDevObj = PDevExt->LowerDeviceObject;
  876. RtlZeroMemory(&linkName, sizeof(UNICODE_STRING));
  877. linkName.MaximumLength = SYMBOLIC_NAME_LENGTH*sizeof(WCHAR);
  878. linkName.Buffer = ExAllocatePool(PagedPool, linkName.MaximumLength
  879. + sizeof(WCHAR));
  880. if (linkName.Buffer == NULL) {
  881. MoxaLogError(PDrvObj, pDevObj, MoxaPhysicalZero, MoxaPhysicalZero,
  882. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  883. 0, NULL, 0, NULL);
  884. MoxaKdPrint (MX_DBG_ERROR, ("Couldn't allocate memory for device name"
  885. "\n"));
  886. status = STATUS_INSUFFICIENT_RESOURCES;
  887. goto MoxaDoExternalNamingError;
  888. }
  889. RtlZeroMemory(linkName.Buffer, linkName.MaximumLength + sizeof(WCHAR));
  890. bufLen = wcslen(PDevExt->DosName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
  891. PDevExt->WmiIdentifier.Buffer = ExAllocatePool(PagedPool, bufLen);
  892. if (PDevExt->WmiIdentifier.Buffer == NULL) {
  893. MoxaLogError(PDrvObj, pDevObj, MoxaPhysicalZero, MoxaPhysicalZero,
  894. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  895. 0, NULL, 0, NULL);
  896. MoxaKdPrint (MX_DBG_ERROR,
  897. (" Couldn't allocate memory for WMI name\n"));
  898. status = STATUS_INSUFFICIENT_RESOURCES;
  899. goto MoxaDoExternalNamingError;
  900. }
  901. RtlZeroMemory(PDevExt->WmiIdentifier.Buffer, bufLen);
  902. PDevExt->WmiIdentifier.Length = 0;
  903. PDevExt->WmiIdentifier.MaximumLength = (USHORT)bufLen;
  904. RtlAppendUnicodeToString(&PDevExt->WmiIdentifier, PDevExt->DosName);
  905. //
  906. // Create the "\\DosDevices\\<symbolicName>" string
  907. //
  908. RtlAppendUnicodeToString(&linkName, L"\\");
  909. RtlAppendUnicodeToString(&linkName, DEFAULT_DIRECTORY);
  910. RtlAppendUnicodeToString(&linkName, L"\\");
  911. RtlAppendUnicodeToString(&linkName, PDevExt->DosName);
  912. //
  913. // Allocate Pool and save the symbolic link name in the device extension.
  914. //
  915. PDevExt->SymbolicLinkName.MaximumLength = linkName.Length + sizeof(WCHAR);
  916. PDevExt->SymbolicLinkName.Buffer
  917. = ExAllocatePool(PagedPool, PDevExt->SymbolicLinkName.MaximumLength);
  918. if (!PDevExt->SymbolicLinkName.Buffer) {
  919. MoxaLogError(PDrvObj, pDevObj, MoxaPhysicalZero, MoxaPhysicalZero,
  920. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  921. 0, NULL, 0, NULL);
  922. MoxaKdPrint (MX_DBG_ERROR,
  923. ("Couldn't allocate memory for symbolic link name\n"));
  924. status = STATUS_INSUFFICIENT_RESOURCES;
  925. goto MoxaDoExternalNamingError;
  926. }
  927. //
  928. // Zero fill it.
  929. //
  930. RtlZeroMemory(PDevExt->SymbolicLinkName.Buffer,
  931. PDevExt->SymbolicLinkName.MaximumLength);
  932. RtlAppendUnicodeStringToString(&PDevExt->SymbolicLinkName,
  933. &linkName);
  934. // MoxaKdPrint (MX_DBG_ERROR,("DosName is %ws\n",
  935. // &PDevExt->DosName));
  936. //
  937. status = IoCreateSymbolicLink (&PDevExt->SymbolicLinkName,
  938. &PDevExt->DeviceName);
  939. if (!NT_SUCCESS(status)) {
  940. //
  941. // Oh well, couldn't create the symbolic link. No point
  942. // in trying to create the device map entry.
  943. //
  944. MoxaLogError(PDrvObj, pDevObj, MoxaPhysicalZero, MoxaPhysicalZero,
  945. 0, 0, 0, 52, status, SERIAL_NO_SYMLINK_CREATED,
  946. PDevExt->DeviceName.Length + sizeof(WCHAR),
  947. PDevExt->DeviceName.Buffer, 0, NULL);
  948. /*
  949. MoxaKdPrint (MX_DBG_ERROR,
  950. ("Couldn't create the symbolic link\n"
  951. "------- for port %wZ\n",
  952. &PDevExt->DeviceName)
  953. );
  954. */
  955. goto MoxaDoExternalNamingError;
  956. }
  957. PDevExt->CreatedSymbolicLink = TRUE;
  958. status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, L"SERIALCOMM",
  959. PDevExt->DeviceName.Buffer, REG_SZ,
  960. PDevExt->DosName,
  961. wcslen(PDevExt->DosName)*sizeof(WCHAR) + sizeof(WCHAR));
  962. if (!NT_SUCCESS(status)) {
  963. MoxaLogError(PDrvObj, pDevObj, MoxaPhysicalZero, MoxaPhysicalZero,
  964. 0, 0, 0, 53, status, SERIAL_NO_DEVICE_MAP_CREATED,
  965. PDevExt->DeviceName.Length + sizeof(WCHAR),
  966. PDevExt->DeviceName.Buffer, 0, NULL);
  967. /*
  968. MoxaKdPrint (MX_DBG_ERROR,("Couldn't create the device map entry\n"
  969. "------- for port %wZ\n", &PDevExt->DeviceName));
  970. */
  971. goto MoxaDoExternalNamingError;
  972. }
  973. PDevExt->CreatedSerialCommEntry = TRUE;
  974. //
  975. // Now set the symbolic link for the association
  976. //
  977. status = IoSetDeviceInterfaceState(&PDevExt->DeviceClassSymbolicName,
  978. TRUE);
  979. /*
  980. if (!NT_SUCCESS(status)) {
  981. MoxaKdPrint (MX_DBG_ERROR,("Couldn't set class association\n"
  982. "------- for port %wZ\n",
  983. &PDevExt->DeviceName));
  984. }
  985. */
  986. MoxaDoExternalNamingError:;
  987. //
  988. // Clean up error conditions
  989. //
  990. if (!NT_SUCCESS(status)) {
  991. if (PDevExt->CreatedSymbolicLink == TRUE) {
  992. IoDeleteSymbolicLink(&PDevExt->SymbolicLinkName);
  993. PDevExt->CreatedSymbolicLink = FALSE;
  994. }
  995. if (PDevExt->SymbolicLinkName.Buffer != NULL) {
  996. ExFreePool(PDevExt->SymbolicLinkName.Buffer);
  997. PDevExt->SymbolicLinkName.Buffer = NULL;
  998. }
  999. if (PDevExt->DeviceName.Buffer != NULL) {
  1000. RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
  1001. PDevExt->DeviceName.Buffer);
  1002. }
  1003. if (PDevExt->DeviceClassSymbolicName.Buffer) {
  1004. IoSetDeviceInterfaceState (&PDevExt->DeviceClassSymbolicName, FALSE);
  1005. }
  1006. if (PDevExt->WmiIdentifier.Buffer != NULL) {
  1007. ExFreePool(PDevExt->WmiIdentifier.Buffer);
  1008. PDevExt->WmiIdentifier.Buffer = NULL;
  1009. }
  1010. }
  1011. //
  1012. // Always clean up our temp buffers.
  1013. //
  1014. if (linkName.Buffer != NULL) {
  1015. ExFreePool(linkName.Buffer);
  1016. }
  1017. return status;
  1018. }
  1019. VOID
  1020. MoxaUndoExternalNaming(IN PMOXA_DEVICE_EXTENSION Extension)
  1021. /*++
  1022. Routine Description:
  1023. This routine will be used to delete a symbolic link
  1024. to the driver name in the given object directory.
  1025. It will also delete an entry in the device map for
  1026. this device if the symbolic link had been created.
  1027. Arguments:
  1028. Extension - Pointer to the device extension.
  1029. Return Value:
  1030. None.
  1031. --*/
  1032. {
  1033. NTSTATUS status;
  1034. //PAGED_CODE();
  1035. /*
  1036. MoxaKdPrint (MX_DBG_ERROR,("In MoxaUndoExternalNaming for\n"
  1037. "------- extension: %x of port %wZ\n",
  1038. Extension,&Extension->DeviceName)
  1039. );
  1040. */
  1041. //
  1042. // We're cleaning up here. One reason we're cleaning up
  1043. // is that we couldn't allocate space for the directory
  1044. // name or the symbolic link.
  1045. //
  1046. if (Extension->SymbolicLinkName.Buffer &&
  1047. Extension->CreatedSymbolicLink) {
  1048. if (Extension->DeviceClassSymbolicName.Buffer) {
  1049. status = IoSetDeviceInterfaceState (&Extension->
  1050. DeviceClassSymbolicName,
  1051. FALSE);
  1052. //
  1053. // IoRegisterDeviceClassInterface() allocated this string for us,
  1054. // and we no longer need it.
  1055. //
  1056. ExFreePool( Extension->DeviceClassSymbolicName.Buffer );
  1057. }
  1058. IoDeleteSymbolicLink (&Extension->SymbolicLinkName);
  1059. }
  1060. if (Extension->WmiIdentifier.Buffer) {
  1061. ExFreePool(Extension->WmiIdentifier.Buffer);
  1062. Extension->WmiIdentifier.MaximumLength
  1063. = Extension->WmiIdentifier.Length = 0;
  1064. Extension->WmiIdentifier.Buffer = NULL;
  1065. }
  1066. //
  1067. // We're cleaning up here. One reason we're cleaning up
  1068. // is that we couldn't allocate space for the NtNameOfPort.
  1069. //
  1070. if ((Extension->DeviceName.Buffer != NULL)
  1071. && Extension->CreatedSerialCommEntry) {
  1072. status = RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
  1073. Extension->DeviceName.Buffer);
  1074. if (!NT_SUCCESS(status)) {
  1075. MoxaLogError(
  1076. Extension->DeviceObject->DriverObject,
  1077. Extension->DeviceObject,
  1078. MoxaPhysicalZero,
  1079. MoxaPhysicalZero,
  1080. 0,
  1081. 0,
  1082. 0,
  1083. 55,
  1084. status,
  1085. SERIAL_NO_DEVICE_MAP_DELETED,
  1086. Extension->DeviceName.Length+sizeof(WCHAR),
  1087. Extension->DeviceName.Buffer,
  1088. 0,
  1089. NULL
  1090. );
  1091. /*
  1092. MoxaKdPrint (MX_DBG_ERROR,("Couldn't delete value entry %wZ\n",
  1093. &Extension->DeviceName)
  1094. );
  1095. */
  1096. }
  1097. }
  1098. }
  1099. NTSTATUS
  1100. MoxaPnpDispatch(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
  1101. /*++
  1102. Routine Description:
  1103. This is a dispatch routine for the IRPs that come to the driver with the
  1104. IRP_MJ_PNP major code (plug-and-play IRPs).
  1105. Arguments:
  1106. PDevObj - Pointer to the device object for this device
  1107. PIrp - Pointer to the IRP for the current request
  1108. Return Value:
  1109. The function value is the final status of the call
  1110. --*/
  1111. {
  1112. PMOXA_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1113. PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
  1114. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  1115. NTSTATUS status;
  1116. PDEVICE_CAPABILITIES pDevCaps;
  1117. //PAGED_CODE();
  1118. if (pDevExt->ControlDevice) { // Control Device
  1119. status = STATUS_CANCELLED;
  1120. PIrp->IoStatus.Information = 0L;
  1121. PIrp->IoStatus.Status = status;
  1122. IoCompleteRequest(
  1123. PIrp,
  1124. 0
  1125. );
  1126. return status;
  1127. }
  1128. if ((status = MoxaIRPPrologue(PIrp, pDevExt)) != STATUS_SUCCESS) {
  1129. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  1130. return status;
  1131. }
  1132. switch (pIrpStack->MinorFunction) {
  1133. case IRP_MN_QUERY_CAPABILITIES: {
  1134. PKEVENT pQueryCapsEvent;
  1135. SYSTEM_POWER_STATE cap;
  1136. MoxaKdPrint (MX_DBG_TRACE,("Got IRP_MN_QUERY_DEVICE_CAPABILITIES "
  1137. "IRP\n"));
  1138. pQueryCapsEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  1139. if (pQueryCapsEvent == NULL) {
  1140. PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  1141. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  1142. return STATUS_INSUFFICIENT_RESOURCES;
  1143. }
  1144. KeInitializeEvent(pQueryCapsEvent, SynchronizationEvent, FALSE);
  1145. IoCopyCurrentIrpStackLocationToNext(PIrp);
  1146. IoSetCompletionRoutine(PIrp, MoxaSyncCompletion, pQueryCapsEvent,
  1147. TRUE, TRUE, TRUE);
  1148. status = IoCallDriver(pLowerDevObj, PIrp);
  1149. //
  1150. // Wait for lower drivers to be done with the Irp
  1151. //
  1152. if (status == STATUS_PENDING) {
  1153. KeWaitForSingleObject(pQueryCapsEvent, Executive, KernelMode, FALSE,
  1154. NULL);
  1155. }
  1156. ExFreePool(pQueryCapsEvent);
  1157. status = PIrp->IoStatus.Status;
  1158. if (pIrpStack->Parameters.DeviceCapabilities.Capabilities == NULL) {
  1159. goto errQueryCaps;
  1160. }
  1161. //
  1162. // Save off their power capabilities
  1163. //
  1164. MoxaKdPrint (MX_DBG_ERROR,("SERIAL: Mapping power capabilities\n"));
  1165. pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  1166. pDevCaps = pIrpStack->Parameters.DeviceCapabilities.Capabilities;
  1167. for (cap = PowerSystemSleeping1; cap < PowerSystemMaximum;
  1168. cap++) {
  1169. #if DBG
  1170. MoxaKdPrint (MX_DBG_ERROR, (" SERIAL: %d: %s <--> %s\n",
  1171. cap, SerSystemCapString[cap],
  1172. SerDeviceCapString[pDevCaps->DeviceState[cap]]
  1173. ));
  1174. #endif
  1175. pDevExt->DeviceStateMap[cap] = pDevCaps->DeviceState[cap];
  1176. }
  1177. pDevExt->DeviceStateMap[PowerSystemUnspecified]
  1178. = PowerDeviceUnspecified;
  1179. pDevExt->DeviceStateMap[PowerSystemWorking]
  1180. = PowerDeviceD0;
  1181. pDevExt->SystemWake = pDevCaps->SystemWake;
  1182. pDevExt->DeviceWake = pDevCaps->DeviceWake;
  1183. errQueryCaps:;
  1184. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  1185. return status;
  1186. }
  1187. case IRP_MN_QUERY_DEVICE_RELATIONS:
  1188. //
  1189. // We just pass this down -- serenum enumerates our bus for us.
  1190. //
  1191. MoxaKdPrint (MX_DBG_TRACE,("Got IRP_MN_QUERY_DEVICE_RELATIONS "
  1192. "Irp\n"));
  1193. switch (pIrpStack->Parameters.QueryDeviceRelations.Type) {
  1194. case BusRelations:
  1195. MoxaKdPrint (MX_DBG_TRACE,("------- BusRelations Query\n"));
  1196. break;
  1197. case EjectionRelations:
  1198. MoxaKdPrint (MX_DBG_TRACE, ("------- EjectionRelations Query\n"));
  1199. break;
  1200. case PowerRelations:
  1201. MoxaKdPrint (MX_DBG_TRACE, ("------- PowerRelations Query\n"));
  1202. break;
  1203. case RemovalRelations:
  1204. MoxaKdPrint (MX_DBG_TRACE, ("------- RemovalRelations Query\n"));
  1205. break;
  1206. case TargetDeviceRelation:
  1207. MoxaKdPrint (MX_DBG_TRACE,("------- TargetDeviceRelation Query\n"));
  1208. break;
  1209. default:
  1210. MoxaKdPrint (MX_DBG_TRACE,("------- Unknown Query\n"));
  1211. break;
  1212. }
  1213. break;
  1214. case IRP_MN_START_DEVICE: {
  1215. PVOID startLockPtr;
  1216. MoxaKdPrint (MX_DBG_TRACE, ("Got IRP_MN_START_DEVICE Irp\n"));
  1217. //
  1218. // MoxaStartDevice will pass this Irp to the next driver,
  1219. // and process it as completion so just complete it here.
  1220. //
  1221. // to be finish
  1222. // MoxaLockPagableSectionByHandle(MoxaGlobalData->PAGESER_Handle);
  1223. //
  1224. // Make sure the stack is powered up
  1225. //
  1226. // status = MoxaGotoPowerState(PDevObj, pDevExt, PowerDeviceD0);
  1227. // if (status == STATUS_SUCCESS) {
  1228. status = MoxaStartDevice(PDevObj, PIrp);
  1229. // }
  1230. // MoxaUnlockPagableImageSection(MoxaGlobalData->PAGESER_Handle);
  1231. PIrp->IoStatus.Status = status;
  1232. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  1233. return status;
  1234. }
  1235. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  1236. {
  1237. MoxaKdPrint (MX_DBG_TRACE,("Got IRP_MN_QUERY_PNP_DEVICE_STATE Irp\n"));
  1238. if (pDevExt->Flags & SERIAL_FLAGS_BROKENHW) {
  1239. (PNP_DEVICE_STATE)PIrp->IoStatus.Information |= PNP_DEVICE_FAILED;
  1240. status = PIrp->IoStatus.Status = STATUS_SUCCESS;
  1241. }
  1242. IoCopyCurrentIrpStackLocationToNext(PIrp);
  1243. return MoxaIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  1244. }
  1245. case IRP_MN_STOP_DEVICE:
  1246. {
  1247. ULONG pendingIRPs;
  1248. KIRQL oldIrql;
  1249. MoxaKdPrint (MX_DBG_TRACE,("Got IRP_MN_STOP_DEVICE Irp\n"));
  1250. MoxaKdPrint (MX_DBG_TRACE, ("------- for device %x\n", pLowerDevObj));
  1251. MoxaSetFlags(pDevExt, SERIAL_FLAGS_STOPPED);
  1252. MoxaSetAccept(pDevExt,SERIAL_PNPACCEPT_STOPPED);
  1253. MoxaClearAccept(pDevExt, SERIAL_PNPACCEPT_STOPPING);
  1254. pDevExt->PNPState = SERIAL_PNP_STOPPING;
  1255. //
  1256. // From this point on all non-PNP IRP's will be queued
  1257. //
  1258. //
  1259. // Decrement for entry here
  1260. //
  1261. InterlockedDecrement(&pDevExt->PendingIRPCnt);
  1262. //
  1263. // Decrement for stopping
  1264. //
  1265. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  1266. if (pendingIRPs) {
  1267. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  1268. KernelMode, FALSE, NULL);
  1269. }
  1270. //
  1271. // Re-increment the count for later
  1272. //
  1273. InterlockedIncrement(&pDevExt->PendingIRPCnt);
  1274. //
  1275. // We need to free resources...basically this is a remove
  1276. // without the detach from the stack.
  1277. //
  1278. // if (pDevExt->Flags & SERIAL_FLAGS_STARTED) {
  1279. MoxaReleaseResources(pDevExt);
  1280. // }
  1281. //
  1282. // Pass the irp down
  1283. //
  1284. IoSkipCurrentIrpStackLocation(PIrp);
  1285. return IoCallDriver(pLowerDevObj, PIrp);
  1286. }
  1287. case IRP_MN_CANCEL_STOP_DEVICE:
  1288. MoxaKdPrint (MX_DBG_TRACE,("Got "
  1289. "IRP_MN_CANCEL_STOP_DEVICE Irp\n"));
  1290. MoxaKdPrint (MX_DBG_TRACE, ("------- for device %x\n", pLowerDevObj));
  1291. if (pDevExt->PNPState == SERIAL_PNP_QSTOP) {
  1292. //
  1293. // Restore the device state
  1294. //
  1295. pDevExt->PNPState = SERIAL_PNP_STARTED;
  1296. MoxaClearAccept(pDevExt, SERIAL_PNPACCEPT_STOPPING);
  1297. }
  1298. IoCopyCurrentIrpStackLocationToNext(PIrp);
  1299. return MoxaIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  1300. case IRP_MN_CANCEL_REMOVE_DEVICE:
  1301. MoxaKdPrint (MX_DBG_TRACE, ("Got "
  1302. "IRP_MN_CANCEL_REMOVE_DEVICE Irp\n"));
  1303. MoxaKdPrint (MX_DBG_TRACE, ("------- for device %x\n", pLowerDevObj));
  1304. //
  1305. // Restore the device state
  1306. //
  1307. pDevExt->PNPState = SERIAL_PNP_STARTED;
  1308. MoxaClearAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  1309. IoCopyCurrentIrpStackLocationToNext(PIrp);
  1310. return MoxaIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  1311. case IRP_MN_QUERY_REMOVE_DEVICE:
  1312. {
  1313. KIRQL oldIrql;
  1314. MoxaKdPrint (MX_DBG_TRACE, ("Got "
  1315. "IRP_MN_QUERY_REMOVE_DEVICE Irp\n"));
  1316. MoxaKdPrint (MX_DBG_TRACE,("------- for device %x\n", pLowerDevObj));
  1317. ExAcquireFastMutex(&pDevExt->OpenMutex);
  1318. //
  1319. // See if we should succeed a remove query
  1320. //
  1321. if (pDevExt->DeviceIsOpened) {
  1322. ExReleaseFastMutex(&pDevExt->OpenMutex);
  1323. status = PIrp->IoStatus.Status = STATUS_DEVICE_BUSY;
  1324. MoxaKdPrint (MX_DBG_TRACE,("------- failing; device open\n"));
  1325. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  1326. return status;
  1327. }
  1328. pDevExt->PNPState = SERIAL_PNP_QREMOVE;
  1329. MoxaSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  1330. ExReleaseFastMutex(&pDevExt->OpenMutex);
  1331. IoSkipCurrentIrpStackLocation(PIrp);
  1332. return MoxaIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  1333. }
  1334. case IRP_MN_SURPRISE_REMOVAL:
  1335. {
  1336. ULONG pendingIRPs;
  1337. KIRQL oldIrql;
  1338. MoxaKdPrint (MX_DBG_TRACE, ("Got IRP_MN_SURPRISE_REMOVAL Irp\n"));
  1339. MoxaKdPrint (MX_DBG_TRACE,("------- for device %x\n", pLowerDevObj));
  1340. //
  1341. // Prevent any new I/O to the device
  1342. //
  1343. MoxaSetAccept(pDevExt, SERIAL_PNPACCEPT_SURPRISE_REMOVING);
  1344. //
  1345. // Dismiss all pending requests
  1346. //
  1347. MoxaKillPendingIrps(PDevObj);
  1348. //
  1349. // Wait for any pending requests we raced on.
  1350. //
  1351. //
  1352. // Decrement once for ourselves
  1353. //
  1354. InterlockedDecrement(&pDevExt->PendingIRPCnt);
  1355. //
  1356. // Decrement for the remove
  1357. //
  1358. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  1359. if (pendingIRPs) {
  1360. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  1361. KernelMode, FALSE, NULL);
  1362. }
  1363. //
  1364. // Reset for subsequent remove
  1365. //
  1366. InterlockedIncrement(&pDevExt->PendingIRPCnt);
  1367. //
  1368. // Remove any external interfaces and release resources
  1369. //
  1370. MoxaDisableInterfacesResources(PDevObj, FALSE); // to be finish
  1371. IoSkipCurrentIrpStackLocation(PIrp);
  1372. return MoxaIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  1373. }
  1374. case IRP_MN_REMOVE_DEVICE:
  1375. {
  1376. ULONG pendingIRPs;
  1377. KIRQL oldIrql;
  1378. MoxaKdPrint (MX_DBG_TRACE,(" Got IRP_MN_REMOVE_DEVICE Irp\n"));
  1379. MoxaKdPrint (MX_DBG_TRACE, ("------- for device %x\n", pLowerDevObj));
  1380. //
  1381. // If we get this, we have to remove
  1382. //
  1383. //
  1384. // Mark as not accepting requests
  1385. //
  1386. MoxaSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  1387. //
  1388. // Complete all pending requests
  1389. //
  1390. MoxaKillPendingIrps(PDevObj);
  1391. //
  1392. // Pass the irp down
  1393. //
  1394. IoCopyCurrentIrpStackLocationToNext(PIrp);
  1395. //
  1396. // We do decrement here because we incremented on entry here.
  1397. //
  1398. status = MoxaIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  1399. //
  1400. // Wait for any pending requests we raced on.
  1401. //
  1402. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  1403. if (pendingIRPs) {
  1404. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  1405. KernelMode, FALSE, NULL);
  1406. }
  1407. //
  1408. // Remove us
  1409. //
  1410. MoxaRemoveDevObj(PDevObj);
  1411. return status;
  1412. }
  1413. default:
  1414. MoxaKdPrint (MX_DBG_TRACE,
  1415. (" Got PNP IRP %x,we don't process it and just pass it down.\n",
  1416. pIrpStack->MinorFunction));
  1417. break;
  1418. } // switch (pIrpStack->MinorFunction)
  1419. //
  1420. // Pass to driver beneath us
  1421. //
  1422. IoSkipCurrentIrpStackLocation(PIrp);
  1423. status = MoxaIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  1424. return status;
  1425. }