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.

927 lines
28 KiB

  1. //===========================================================================
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1996 - 2000 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //===========================================================================
  11. /*++
  12. Module Name:
  13. CtrlPkt.c
  14. Abstract:
  15. Stream class based WDM driver for 1934 Desktop Camera.
  16. This file contains code to handle the stream class control packets.
  17. Author:
  18. Yee J. Wu 24-Jun-98
  19. Environment:
  20. Kernel mode only
  21. Revision History:
  22. --*/
  23. #include "strmini.h"
  24. #include "ksmedia.h"
  25. #include "1394.h"
  26. #include "wdm.h" // for DbgBreakPoint() defined in dbg.h
  27. #include "dbg.h"
  28. #include "dcamdef.h"
  29. #include "dcampkt.h"
  30. #include "sonydcam.h"
  31. #define WAIT_FOR_SLOW_DEVICE
  32. #ifdef ALLOC_PRAGMA
  33. #pragma alloc_text(PAGE, DCamSetKSStateSTOP)
  34. #pragma alloc_text(PAGE, DCamSetKSStatePAUSE)
  35. #pragma alloc_text(PAGE, DCamReceiveCtrlPacket)
  36. #endif
  37. NTSTATUS
  38. DCamToStopStateCR(
  39. IN PDEVICE_OBJECT DeviceObject,
  40. IN PIRP pIrp,
  41. IN PDCAM_IO_CONTEXT pDCamIoContext
  42. )
  43. /*++
  44. Routine Description:
  45. This is the state machine to set the streaming state to STOP.
  46. It start at PASSIVE_LEVEL and the lower driver may have raised it to DISPATCH_LEVEL.
  47. Arguments:
  48. DriverObject - Pointer to driver object created by system.
  49. pIrp - Irp that just completed
  50. pDCamIoContext - A structure that contain the context of this IO completion routine.
  51. Return Value:
  52. None.
  53. --*/
  54. {
  55. PDCAM_EXTENSION pDevExt;
  56. PSTREAMEX pStrmEx;
  57. NTSTATUS Status;
  58. PIRB pIrb;
  59. PIO_STACK_LOCATION NextIrpStack;
  60. if(!pDCamIoContext) {
  61. return STATUS_MORE_PROCESSING_REQUIRED;
  62. }
  63. pIrb = pDCamIoContext->pIrb;
  64. pDevExt = pDCamIoContext->pDevExt;
  65. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  66. DbgMsg2(("\'DCamToStopStateCR: completed DeviceState=%d; pIrp->IoStatus.Status=%x\n",
  67. pDCamIoContext->DeviceState, pIrp->IoStatus.Status));
  68. // Free MDL
  69. if(pIrb->FunctionNumber == REQUEST_ASYNC_WRITE) {
  70. DbgMsg3(("DCamToStopStateCR: IoFreeMdl\n"));
  71. IoFreeMdl(pIrb->u.AsyncWrite.Mdl);
  72. }
  73. // Return error status and free resoruce.
  74. if(pIrp->IoStatus.Status != STATUS_SUCCESS) {
  75. if(pDCamIoContext->pSrb) {
  76. ERROR_LOG(("DCamToStopStateCR: pIrp->IoStatus.Status %x; cancel all packets\n", pIrp->IoStatus.Status));
  77. // In order to stop streaming, we must cancel all pending IRPs
  78. // Cancel pending IRPS and complete SRB.
  79. DCamCancelAllPackets(
  80. pDCamIoContext->pSrb,
  81. pDevExt,
  82. &pDevExt->PendingReadCount
  83. );
  84. }
  85. DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
  86. return STATUS_MORE_PROCESSING_REQUIRED;
  87. }
  88. switch (pDCamIoContext->DeviceState) {
  89. case DCAM_STOPSTATE_SET_REQUEST_ISOCH_STOP:
  90. //
  91. // Now stop the stream at the device itself
  92. //
  93. // Next state:
  94. pDCamIoContext->DeviceState = DCAM_STOPSTATE_SET_STOP_ISOCH_TRANSMISSION; // Keep track of device state that we just set.
  95. pDCamIoContext->RegisterWorkArea.AsULONG = STOP_ISOCH_TRANSMISSION;
  96. pIrb->FunctionNumber = REQUEST_ASYNC_WRITE;
  97. pIrb->Flags = 0;
  98. pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High = INITIAL_REGISTER_SPACE_HI;
  99. pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  100. pDevExt->BaseRegister + FIELDOFFSET(CAMERA_REGISTER_MAP, IsoEnable);
  101. pIrb->u.AsyncWrite.nNumberOfBytesToWrite = sizeof(ULONG);
  102. pIrb->u.AsyncWrite.nBlockSize = 0;
  103. pIrb->u.AsyncWrite.fulFlags = 0;
  104. InterlockedExchange(&pIrb->u.AsyncWrite.ulGeneration, pDevExt->CurrentGeneration);
  105. pIrb->u.AsyncWrite.Mdl =
  106. IoAllocateMdl(&pDCamIoContext->RegisterWorkArea, sizeof(ULONG), FALSE, FALSE, NULL);
  107. MmBuildMdlForNonPagedPool(pIrb->u.AsyncWrite.Mdl);
  108. // Set once and used again in the completion routine.
  109. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  110. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  111. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  112. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  113. IoSetCompletionRoutine(
  114. pIrp,
  115. DCamToStopStateCR,
  116. pDCamIoContext,
  117. TRUE,
  118. TRUE,
  119. TRUE
  120. );
  121. Status =
  122. IoCallDriver(
  123. pDevExt->BusDeviceObject,
  124. pIrp
  125. );
  126. return STATUS_MORE_PROCESSING_REQUIRED;
  127. case DCAM_STOPSTATE_SET_STOP_ISOCH_TRANSMISSION:
  128. //
  129. // Detach all buffers that might still be attached.
  130. //
  131. DbgMsg2(("\'DCamToStopStateCR: IsListEmpty()=%s; PendingRead=%d\n",
  132. IsListEmpty(&pDevExt->IsochDescriptorList) ? "Yes" : "No", pDevExt->PendingReadCount));
  133. if(pDCamIoContext->pSrb) {
  134. //
  135. // Cancel all pending and waiting buffers;
  136. // and Complete DCamSetKSStateSTOP's SRB
  137. //
  138. DCamCancelAllPackets(
  139. pDCamIoContext->pSrb,
  140. pDevExt,
  141. &pDevExt->PendingReadCount
  142. );
  143. // This pDCamIoContext->pSrb will be completed in DCamCancelPacket()
  144. // But its Irb and Irp and context are freed here.
  145. DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
  146. return STATUS_MORE_PROCESSING_REQUIRED;
  147. } else {
  148. ERROR_LOG(("DCamToStopStateCR:CanNOT call DCamCancelPacket() with a null pSrb\n"));
  149. }
  150. break;
  151. default:
  152. ERROR_LOG(("\'DCamToStopStateCR: Unknown pDCamIoContext->DeviceState=%d\n", pDCamIoContext->DeviceState));
  153. ASSERT(FALSE);
  154. break;
  155. }
  156. if(pDCamIoContext->pSrb) {
  157. pDCamIoContext->pSrb->Status = pIrp->IoStatus.Status == STATUS_SUCCESS ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  158. COMPLETE_SRB(pDCamIoContext->pSrb)
  159. }
  160. DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
  161. return STATUS_MORE_PROCESSING_REQUIRED;
  162. }
  163. VOID
  164. DCamSetKSStateSTOP(
  165. IN PHW_STREAM_REQUEST_BLOCK pSrb
  166. )
  167. /*++
  168. Routine Description:
  169. Into STOP streaming state.
  170. (1) Stop device from steaming (!ISO_ENABLE)
  171. (2) Stop listening (controller)
  172. (3) Detach pending read buffer and return with Cancel, and
  173. start the waiting read to be put into the pengin read and then Cancel.
  174. Arguments:
  175. pSrb - Pointer to Stream request block
  176. Return Value:
  177. Nothing
  178. --*/
  179. {
  180. PDCAM_EXTENSION pDevExt;
  181. PSTREAMEX pStrmEx;
  182. PIRB pIrb;
  183. PIRP pIrp;
  184. PDCAM_IO_CONTEXT pDCamIoContext;
  185. PIO_STACK_LOCATION NextIrpStack;
  186. NTSTATUS Status, StatusWait;
  187. PAGED_CODE();
  188. pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
  189. ASSERT(pDevExt);
  190. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  191. ASSERT(pStrmEx);
  192. DbgMsg1(("\'DCamSetKSStateSTOP: Frame captured:%d\n", (DWORD) pStrmEx->FrameCaptured));
  193. //
  194. // After this, no more read will be accepted.
  195. //
  196. pStrmEx->KSState = KSSTATE_STOP;
  197. //
  198. // First stop the stream internally inside the PC's 1394
  199. // stack
  200. //
  201. if(!pDevExt->hResource) {
  202. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  203. COMPLETE_SRB(pSrb)
  204. return;
  205. }
  206. //
  207. // Wait for last read to complete.
  208. // After KState == KSSTATE_STOP, we will return all SRB_READ.
  209. //
  210. StatusWait = KeWaitForSingleObject( &pStrmEx->hMutex, Executive, KernelMode, FALSE, 0 );
  211. KeReleaseMutex(&pStrmEx->hMutex, FALSE);
  212. if(!DCamAllocateIrbIrpAndContext(&pDCamIoContext, &pIrb, &pIrp, pDevExt->BusDeviceObject->StackSize)) {
  213. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  214. COMPLETE_SRB(pSrb)
  215. return;
  216. }
  217. pDCamIoContext->DeviceState = DCAM_STOPSTATE_SET_REQUEST_ISOCH_STOP;
  218. pDCamIoContext->pSrb = pSrb; // To do StreamClassStreamNotification()
  219. pDCamIoContext->pDevExt = pDevExt;
  220. pIrb->FunctionNumber = REQUEST_ISOCH_STOP;
  221. pIrb->Flags = 0;
  222. pIrb->u.IsochStop.hResource = pDevExt->hResource;
  223. pIrb->u.IsochStop.fulFlags = 0;
  224. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  225. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  226. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  227. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  228. IoSetCompletionRoutine(
  229. pIrp,
  230. DCamToStopStateCR,
  231. pDCamIoContext,
  232. TRUE,
  233. TRUE,
  234. TRUE
  235. );
  236. Status =
  237. IoCallDriver(
  238. pDevExt->BusDeviceObject,
  239. pIrp
  240. );
  241. ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PENDING);
  242. return; // Do StreamClassStreamNotification() in IoCompletionRoutine
  243. }
  244. NTSTATUS
  245. DCamToPauseStateCR(
  246. IN PDEVICE_OBJECT DeviceObject,
  247. IN PIRP pIrp,
  248. IN PDCAM_IO_CONTEXT pDCamIoContext
  249. )
  250. /*++
  251. Routine Description:
  252. This routine is for use with synchronous IRP processing.
  253. All it does is signal an event, so the driver knows it
  254. can continue.
  255. Arguments:
  256. DriverObject - Pointer to driver object created by system.
  257. pIrp - Irp that just completed
  258. pDCamIoContext - A structure that contain the context of this IO completion routine.
  259. Return Value:
  260. None.
  261. --*/
  262. {
  263. PDCAM_EXTENSION pDevExt;
  264. PSTREAMEX pStrmEx;
  265. PIRB pIrb;
  266. if(!pDCamIoContext) {
  267. return STATUS_MORE_PROCESSING_REQUIRED;
  268. }
  269. pIrb = pDCamIoContext->pIrb;
  270. pDevExt = pDCamIoContext->pDevExt;
  271. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  272. ASSERT(pStrmEx);
  273. DbgMsg2(("\'DCamToPauseStateCR: completed DeviceState=%d; pIrp->IoStatus.Status=%x\n",
  274. pDCamIoContext->DeviceState, pIrp->IoStatus.Status));
  275. // No reason it would failed.
  276. ASSERT(pIrp->IoStatus.Status == STATUS_SUCCESS);
  277. switch (pDCamIoContext->DeviceState) {
  278. case DCAM_PAUSESTATE_SET_REQUEST_ISOCH_STOP:
  279. break;
  280. default:
  281. ERROR_LOG(("DCamToPauseStateCompletionRoutine: Unknown or unexpected pDCamIoContext->DeviceState=%d\n", pDCamIoContext->DeviceState));
  282. ASSERT(FALSE);
  283. break;
  284. }
  285. //
  286. // We are here only if switching from RUN->PAUSE,
  287. // It is alreay set to PAUSE state in DCamSetKSStatePAUSE
  288. //
  289. if(pDCamIoContext->pSrb) {
  290. pDCamIoContext->pSrb->Status = pIrp->IoStatus.Status == STATUS_SUCCESS ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  291. COMPLETE_SRB(pDCamIoContext->pSrb)
  292. }
  293. DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
  294. return STATUS_MORE_PROCESSING_REQUIRED;
  295. }
  296. VOID
  297. DCamSetKSStatePAUSE(
  298. IN PHW_STREAM_REQUEST_BLOCK pSrb
  299. )
  300. /*++
  301. Routine Description:
  302. Set KSSTATE to KSSTATE_PAUSE.
  303. Arguments:
  304. Srb - Pointer to Stream request block
  305. Return Value:
  306. Nothing
  307. --*/
  308. {
  309. PDCAM_EXTENSION pDevExt;
  310. PSTREAMEX pStrmEx;
  311. PIRB pIrb;
  312. PIRP pIrp;
  313. PDCAM_IO_CONTEXT pDCamIoContext;
  314. PIO_STACK_LOCATION NextIrpStack;
  315. NTSTATUS Status;
  316. PAGED_CODE();
  317. pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
  318. ASSERT(pDevExt);
  319. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  320. ASSERT(pStrmEx);
  321. pSrb->Status = STATUS_SUCCESS;
  322. switch(pStrmEx->KSState) {
  323. case KSSTATE_ACQUIRE:
  324. case KSSTATE_STOP:
  325. //
  326. // Out of STOP state,
  327. // initialize frame and timestamp information.
  328. // (Master's clock's stream time is also reset.)
  329. //
  330. pStrmEx->FrameCaptured = 0; // Actual count
  331. pStrmEx->FrameInfo.DropCount = 0;
  332. pStrmEx->FrameInfo.PictureNumber = 0;
  333. pStrmEx->FrameInfo.dwFrameFlags = 0;
  334. // Advanced one frame.
  335. pStrmEx->FirstFrameTime = pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
  336. DbgMsg2(("\'DCamSetKSStatePAUSE: FirstFrameTime(%d)\n", pStrmEx->FirstFrameTime));
  337. break;
  338. case KSSTATE_RUN:
  339. //
  340. // Will ask controll to stop listening.
  341. // All the pening buffer(s) are kept in the controller.
  342. // Before it completely stop (some latency here),
  343. // we might get some IsochCallback() with data.
  344. //
  345. if(!pDevExt->hResource) {
  346. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  347. break;
  348. }
  349. if(!DCamAllocateIrbIrpAndContext(&pDCamIoContext, &pIrb, &pIrp, pDevExt->BusDeviceObject->StackSize)) {
  350. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  351. break;
  352. }
  353. // Set to KSSTATE_PAUSE at the beginning to prvent CancelPacket being processed thinking
  354. // it is still in KSSTATE_RUN state.
  355. pStrmEx->KSState = KSSTATE_PAUSE;
  356. pDCamIoContext->DeviceState = DCAM_PAUSESTATE_SET_REQUEST_ISOCH_STOP;
  357. pDCamIoContext->pSrb = pSrb; // To do StreamClassStreamNotification()
  358. pDCamIoContext->pDevExt = pDevExt;
  359. pIrb->FunctionNumber = REQUEST_ISOCH_STOP;
  360. pIrb->Flags = 0;
  361. pIrb->u.IsochStop.hResource = pDevExt->hResource;
  362. pIrb->u.IsochStop.fulFlags = 0;
  363. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  364. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  365. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  366. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  367. IoSetCompletionRoutine(
  368. pIrp,
  369. DCamToPauseStateCR,
  370. pDCamIoContext,
  371. TRUE,
  372. TRUE,
  373. TRUE
  374. );
  375. Status =\
  376. IoCallDriver(
  377. pDevExt->BusDeviceObject,
  378. pIrp
  379. );
  380. return; // Do StreamClassStreamNotification() in IoCompletionRoutine
  381. case KSSTATE_PAUSE:
  382. ERROR_LOG(("DCamSetKSStatePAUSE: Already in KSSTATE_PAUSE state.\n"));
  383. ASSERT(pStrmEx->KSState != KSSTATE_PAUSE);
  384. break;
  385. }
  386. pStrmEx->KSState = KSSTATE_PAUSE;
  387. COMPLETE_SRB(pSrb)
  388. }
  389. NTSTATUS
  390. DCamToRunStateCR(
  391. IN PDEVICE_OBJECT DeviceObject,
  392. IN PIRP pIrp,
  393. IN PDCAM_IO_CONTEXT pDCamIoContext
  394. )
  395. /*++
  396. Routine Description:
  397. This routine is for use with synchronous IRP processing.
  398. All it does is signal an event, so the driver knows it
  399. can continue.
  400. Arguments:
  401. DriverObject - Pointer to driver object created by system.
  402. pIrp - Irp that just completed
  403. pDCamIoContext - A structure that contain the context of this IO completion routine.
  404. Return Value:
  405. None.
  406. --*/
  407. {
  408. PDCAM_EXTENSION pDevExt;
  409. PSTREAMEX pStrmEx;
  410. NTSTATUS Status;
  411. PIRB pIrb;
  412. PIO_STACK_LOCATION NextIrpStack;
  413. if(!pDCamIoContext) {
  414. return STATUS_MORE_PROCESSING_REQUIRED;
  415. }
  416. pIrb = pDCamIoContext->pIrb;
  417. pDevExt = pDCamIoContext->pDevExt;
  418. DbgMsg2(("\'DCamToRunStateCR: completed DeviceState=%d; pIrp->IoStatus.Status=%x\n",
  419. pDCamIoContext->DeviceState, pIrp->IoStatus.Status));
  420. // Free MDL
  421. if(pIrb->FunctionNumber == REQUEST_ASYNC_WRITE) {
  422. DbgMsg3(("DCamToRunStateCR: IoFreeMdl\n"));
  423. IoFreeMdl(pIrb->u.AsyncWrite.Mdl);
  424. }
  425. //
  426. // CAUTION:
  427. // STATUS_TIMEOUT can be a valid return that we may to try again.
  428. // But should it be a HW issue that it is not responding to our write.
  429. // Controller should have made many reties before return STATUS_TIMEOUT.
  430. //
  431. if(pIrp->IoStatus.Status != STATUS_SUCCESS) {
  432. if(DCAM_RUNSTATE_SET_REQUEST_ISOCH_LISTEN != pDCamIoContext->DeviceState ||
  433. STATUS_INSUFFICIENT_RESOURCES != pIrp->IoStatus.Status ) {
  434. ERROR_LOG(("DCamToRunStateCR: pIrp->IoStatus.Status=%x; free resoruce and STOP\n", pIrp->IoStatus.Status));
  435. if(pDCamIoContext->pSrb) {
  436. pDCamIoContext->pSrb->Status = pIrp->IoStatus.Status == STATUS_SUCCESS ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  437. COMPLETE_SRB(pDCamIoContext->pSrb);
  438. }
  439. DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
  440. return STATUS_MORE_PROCESSING_REQUIRED;
  441. } else {
  442. //
  443. // This is OK:
  444. // If we get an insufficient resources error that means
  445. // we don't have any Reads down yet. Set flag to TRUE
  446. // indicating that when we do get a Read down we'll
  447. // actually need to begin the listening process.
  448. //
  449. pDevExt->bNeedToListen = TRUE;
  450. DbgMsg1(("DCamToRunStateCR: ##### no read yet! set pDevExt->bNeedToListen = TRUE\n"));
  451. }
  452. }
  453. #ifdef WAIT_FOR_SLOW_DEVICE
  454. KeStallExecutionProcessor(5000); // 5 msec
  455. #endif
  456. switch (pDCamIoContext->DeviceState) {
  457. case DCAM_RUNSTATE_SET_REQUEST_ISOCH_LISTEN:
  458. //
  459. // Bit[24..26]0:0000 = CurrentFrameRate
  460. //
  461. pDCamIoContext->RegisterWorkArea.AsULONG = pDevExt->FrameRate << 5;
  462. DbgMsg2(("\'DCamToRunState: FrameRate %x\n", pDCamIoContext->RegisterWorkArea.AsULONG));
  463. pIrb->FunctionNumber = REQUEST_ASYNC_WRITE;
  464. pIrb->Flags = 0;
  465. pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High = INITIAL_REGISTER_SPACE_HI;
  466. pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  467. pDevExt->BaseRegister + FIELDOFFSET(CAMERA_REGISTER_MAP, CurrentVFrmRate);
  468. pIrb->u.AsyncWrite.nNumberOfBytesToWrite = sizeof(ULONG);
  469. pIrb->u.AsyncWrite.nBlockSize = 0;
  470. pIrb->u.AsyncWrite.fulFlags = 0;
  471. InterlockedExchange(&pIrb->u.AsyncWrite.ulGeneration, pDevExt->CurrentGeneration);
  472. break;
  473. case DCAM_RUNSTATE_SET_FRAME_RATE:
  474. //
  475. // Bit[24..26]0:0000 = CurrentVideoMode
  476. //
  477. pDCamIoContext->RegisterWorkArea.AsULONG = pDevExt->CurrentModeIndex << 5;
  478. DbgMsg2(("\'DCamToRunState: CurrentVideoMode %x\n", pDCamIoContext->RegisterWorkArea.AsULONG));
  479. pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  480. pDevExt->BaseRegister + FIELDOFFSET(CAMERA_REGISTER_MAP, CurrentVMode);
  481. break;
  482. case DCAM_RUNSTATE_SET_CURRENT_VIDEO_MODE:
  483. pDCamIoContext->RegisterWorkArea.AsULONG = FORMAT_VGA_NON_COMPRESSED;
  484. DbgMsg2(("\'DCamToRunState: VideoFormat %x\n", pDCamIoContext->RegisterWorkArea.AsULONG));
  485. pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  486. pDevExt->BaseRegister + FIELDOFFSET(CAMERA_REGISTER_MAP, CurrentVFormat);
  487. break;
  488. case DCAM_RUNSTATE_SET_CURRENT_VIDEO_FORMAT:
  489. //
  490. // Bit [24..27]:00[30..31] = IsoChannel:00SpeedCode
  491. //
  492. pDCamIoContext->RegisterWorkArea.AsULONG = (pDevExt->IsochChannel << 4) | pDevExt->SpeedCode;
  493. DbgMsg2(("\'DCamToRunState: pDevExt->SpeedCode 0x%x, Channel+SpeedCode %x\n", pDevExt->SpeedCode, pDCamIoContext->RegisterWorkArea.AsULONG));
  494. pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  495. pDevExt->BaseRegister + FIELDOFFSET(CAMERA_REGISTER_MAP, IsoChannel);
  496. break;
  497. case DCAM_RUNSTATE_SET_SPEED:
  498. //
  499. // Bit[24]000:0000 = start ? 1 : 0;
  500. //
  501. pDCamIoContext->RegisterWorkArea.AsULONG = START_ISOCH_TRANSMISSION;
  502. pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  503. pDevExt->BaseRegister + FIELDOFFSET(CAMERA_REGISTER_MAP, IsoEnable);
  504. break;
  505. case DCAM_RUNSTATE_SET_START:
  506. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  507. ASSERT(pStrmEx);
  508. pStrmEx->KSState = KSSTATE_RUN;
  509. // If this is called from a SRB, then completed it.
  510. if(pDCamIoContext->pSrb) {
  511. pDCamIoContext->pSrb->Status = pIrp->IoStatus.Status == STATUS_SUCCESS ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  512. COMPLETE_SRB(pDCamIoContext->pSrb);
  513. }
  514. //
  515. // This is last stop; so
  516. // we free what we allocated.
  517. //
  518. DbgMsg2(("\'DCamToRunStateCR: DONE!\n"));
  519. DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
  520. return STATUS_MORE_PROCESSING_REQUIRED;
  521. default:
  522. ERROR_LOG(("DCamToRunStateCR:DeviceState(%d) is not defined!\n\n", pDCamIoContext->DeviceState));
  523. ASSERT(FALSE);
  524. return STATUS_MORE_PROCESSING_REQUIRED;
  525. }
  526. pDCamIoContext->DeviceState++; // Keep track of device state that we just set.
  527. if(pIrb->FunctionNumber == REQUEST_ASYNC_WRITE) {
  528. pIrb->u.AsyncWrite.Mdl =
  529. IoAllocateMdl(&pDCamIoContext->RegisterWorkArea, sizeof(ULONG), FALSE, FALSE, NULL);
  530. MmBuildMdlForNonPagedPool(pIrb->u.AsyncWrite.Mdl);
  531. }
  532. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  533. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  534. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  535. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  536. IoSetCompletionRoutine(
  537. pIrp,
  538. DCamToRunStateCR,
  539. pDCamIoContext,
  540. TRUE,
  541. TRUE,
  542. TRUE
  543. );
  544. Status =
  545. IoCallDriver(
  546. pDevExt->BusDeviceObject,
  547. pIrp
  548. );
  549. DbgMsg2(("\'DCamToRunStateCR: IoCallDriver, Status=%x; STATUS_PENDING(%x)\n", Status, STATUS_PENDING));
  550. return STATUS_MORE_PROCESSING_REQUIRED;
  551. }
  552. VOID
  553. DCamSetKSStateRUN(
  554. PDCAM_EXTENSION pDevExt,
  555. IN PHW_STREAM_REQUEST_BLOCK pSrb // Needed only to complete the SRB; for bus reset, there is no SRB.
  556. )
  557. /*++
  558. Routine Description:
  559. Set KSSTATE to KSSTATE_RUN.
  560. Can be called at DISPATCH level for initializing the device after a bus reset.
  561. Arguments:
  562. pSrb - Pointer to Stream request block
  563. Return Value:
  564. Nothing
  565. --*/
  566. {
  567. PSTREAMEX pStrmEx;
  568. PIRB pIrb;
  569. PIRP pIrp;
  570. PDCAM_IO_CONTEXT pDCamIoContext;
  571. PIO_STACK_LOCATION NextIrpStack;
  572. NTSTATUS Status;
  573. ASSERT(pDevExt);
  574. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  575. ASSERT(pStrmEx);
  576. if(!DCamAllocateIrbIrpAndContext(&pDCamIoContext, &pIrb, &pIrp, pDevExt->BusDeviceObject->StackSize)) {
  577. if(pSrb) {
  578. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  579. COMPLETE_SRB(pSrb);
  580. }
  581. return;
  582. }
  583. pStrmEx->KSStateFinal = KSSTATE_RUN;
  584. pDCamIoContext->DeviceState = DCAM_RUNSTATE_SET_REQUEST_ISOCH_LISTEN;
  585. pDCamIoContext->pSrb = pSrb; // To do StreamClassStreamNotification()
  586. pDCamIoContext->pDevExt = pDevExt;
  587. pIrb->FunctionNumber = REQUEST_ISOCH_LISTEN;
  588. pIrb->Flags = 0;
  589. pIrb->u.IsochStop.hResource = pDevExt->hResource;
  590. pIrb->u.IsochStop.fulFlags = 0;
  591. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  592. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  593. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  594. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  595. // In case we time out, we will try again; apply only to start listen;
  596. // With little change, it can work with other operation as well.
  597. pDevExt->lRetries = 0;
  598. IoSetCompletionRoutine(
  599. pIrp,
  600. DCamToRunStateCR,
  601. pDCamIoContext,
  602. TRUE,
  603. TRUE,
  604. TRUE
  605. );
  606. Status =
  607. IoCallDriver(
  608. pDevExt->BusDeviceObject,
  609. pIrp
  610. );
  611. }
  612. VOID
  613. DCamReceiveCtrlPacket(
  614. IN PHW_STREAM_REQUEST_BLOCK pSrb
  615. )
  616. /*++
  617. Routine Description:
  618. Called with packet commands that control the video stream
  619. Arguments:
  620. pSrb - Pointer to Stream request block
  621. Return Value:
  622. Nothing
  623. --*/
  624. {
  625. PDCAM_EXTENSION pDevExt;
  626. PSTREAMEX pStrmEx;
  627. //
  628. // determine the type of packet.
  629. //
  630. PAGED_CODE();
  631. pSrb->Status = STATUS_SUCCESS; // default; called functions depends on this.
  632. pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
  633. ASSERT(pDevExt);
  634. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  635. ASSERT(pStrmEx);
  636. switch (pSrb->Command) {
  637. case SRB_GET_STREAM_STATE:
  638. VideoGetState (pSrb);
  639. break;
  640. case SRB_SET_STREAM_STATE:
  641. if(pStrmEx == NULL) {
  642. ERROR_LOG(("\'DCamReceiveCtrlPacket: SRB_SET_STREAM_STATE but pStrmEx is NULL.\n"));
  643. ASSERT(pStrmEx);
  644. pSrb->Status = STATUS_UNSUCCESSFUL;
  645. break;
  646. }
  647. DbgMsg2(("\'DCamReceiveCtrlPacket: Setting state from %d to %d; PendingRead %d\n",
  648. pStrmEx->KSState, pSrb->CommandData.StreamState, pDevExt->PendingReadCount));
  649. //
  650. // The control packet and data packet are not serialized by the stream class.
  651. // We need to watch for PAUSE->STOP transition.
  652. // In this transition, SRB_READ can still come in in a separate thread if
  653. // the client application has separate threads for setting state and read data.
  654. //
  655. // A "stop data packet" flag and a mutex is used for this synchronization.
  656. // So we set "stop data packet" flag to stop future read, and
  657. // wait to own the mutex (if read is in progress) and then set stream to STOP state.
  658. // This "stop data packet" flag can be the stream state.
  659. //
  660. switch (pSrb->CommandData.StreamState) {
  661. case KSSTATE_STOP:
  662. DCamSetKSStateSTOP(pSrb);
  663. return; // Complete Asynchronously in IoCompletionRoutine*
  664. case KSSTATE_PAUSE:
  665. DCamSetKSStatePAUSE(pSrb);
  666. return; // Complete Asynchronously in IoCompletionRoutine*
  667. case KSSTATE_RUN:
  668. DCamSetKSStateRUN(pDevExt, pSrb);
  669. return; // Complete Asynchronously in IoCompletionRoutine*
  670. case KSSTATE_ACQUIRE:
  671. pSrb->Status = STATUS_SUCCESS;
  672. break;
  673. default:
  674. ERROR_LOG(("\'DCamReceiveCtrlPacket: Error unknown state\n"));
  675. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  676. break;
  677. }
  678. pStrmEx->KSState = pSrb->CommandData.StreamState;
  679. break;
  680. case SRB_GET_STREAM_PROPERTY:
  681. DbgMsg3(("\'DCamReceiveCtrlPacket: SRB_GET_STREAM_PROPERTY\n"));
  682. VideoGetProperty(pSrb);
  683. break;
  684. case SRB_INDICATE_MASTER_CLOCK:
  685. //
  686. // Assigns a clock to a stream
  687. //
  688. VideoIndicateMasterClock (pSrb);
  689. break;
  690. default:
  691. //
  692. // invalid / unsupported command. Fail it as such
  693. //
  694. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  695. break;
  696. }
  697. StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
  698. }