Source code of Windows XP (NT5)
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.

1312 lines
37 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. DataPkt.c
  14. Abstract:
  15. Stream class based WDM driver for 1934 Desktop Camera.
  16. This file contains code to handle the stream class 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. extern CAMERA_ISOCH_INFO IsochInfoTable[];
  32. #ifdef ALLOC_PRAGMA
  33. #pragma alloc_text(PAGE, DCamSurpriseRemoval)
  34. #pragma alloc_text(PAGE, DCamReceiveDataPacket)
  35. #endif
  36. NTSTATUS
  37. DCamCancelOnePacketCR(
  38. IN PDEVICE_OBJECT DeviceObject,
  39. IN PIRP pIrp,
  40. PISOCH_DESCRIPTOR IsochDescriptor
  41. )
  42. /*++
  43. Routine Description:
  44. Completion routine for detach an isoch descriptor associate with a pending read SRB.
  45. Will cancel the pending SRB here if detaching descriptor has suceeded.
  46. Arguments:
  47. DriverObject - Pointer to driver object created by system.
  48. pIrp - Allocated locally, need to be free here.
  49. IsochDescriptor - Isoch descriptor containing the SRB to be cancelled.
  50. Return Value:
  51. None.
  52. --*/
  53. {
  54. PHW_STREAM_REQUEST_BLOCK pSrbToCancel;
  55. PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
  56. PDCAM_EXTENSION pDevExt;
  57. if(STATUS_SUCCESS != pIrp->IoStatus.Status) {
  58. ERROR_LOG(("DCamCancelOnePacketCR: Detach buffer failed with pIrp->IoStatus.Status= %x (! STATUS_SUCCESS) \n", pIrp->IoStatus.Status));
  59. ASSERT(STATUS_SUCCESS == pIrp->IoStatus.Status);
  60. } else {
  61. IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
  62. pSrbToCancel = IsochDescriptorReserved->Srb;
  63. pDevExt = (PDCAM_EXTENSION) pSrbToCancel->HwDeviceExtension;
  64. IsochDescriptorReserved->Flags |= STATE_SRB_IS_COMPLETE;
  65. pSrbToCancel->CommandData.DataBufferArray->DataUsed = 0;
  66. pSrbToCancel->ActualBytesTransferred = 0;
  67. pSrbToCancel->Status = pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_CANCELLED;
  68. DbgMsg2(("DCamCancelOnePacketCR: SRB %x, Status %x, IsochDesc %x, Reserved %x cancelled\n",
  69. pSrbToCancel, pSrbToCancel->Status, IsochDescriptor, IsochDescriptorReserved));
  70. StreamClassStreamNotification(
  71. StreamRequestComplete,
  72. pSrbToCancel->StreamObject,
  73. pSrbToCancel);
  74. ExFreePool(IsochDescriptor);
  75. }
  76. // Allocated locally so free it.
  77. IoFreeIrp(pIrp);
  78. return STATUS_MORE_PROCESSING_REQUIRED;
  79. }
  80. VOID
  81. DCamDetachAndCancelOnePacket(
  82. IN PHW_STREAM_REQUEST_BLOCK pSrbToCancel,
  83. PISOCH_DESCRIPTOR IsochDescriptorToDetach,
  84. HANDLE hResource,
  85. PDEVICE_OBJECT pBusDeviceObject
  86. )
  87. /*++
  88. Routine Description:
  89. Detach an isoch descriptor and then cancel pending SRB in the completion routine.
  90. Arguments:
  91. pSrbToCancel - Pointer to SRB to cancel
  92. IsochDescriptorToDetach - Iosch descriptor to detach
  93. hResource - isoch resource allocated
  94. hBusDeviceObject - bus device object
  95. Return Value:
  96. None.
  97. --*/
  98. {
  99. PDCAM_EXTENSION pDevExt;
  100. PIO_STACK_LOCATION NextIrpStack;
  101. NTSTATUS Status;
  102. PIRB pIrb;
  103. PIRP pIrp;
  104. DbgMsg2(("\'DCamDetachAndCancelOnePacket: pSrbTocancel %x, detaching IsochDescriptorToDetach %x\n", pSrbToCancel, IsochDescriptorToDetach));
  105. pDevExt = (PDCAM_EXTENSION) pSrbToCancel->HwDeviceExtension;
  106. pIrp = IoAllocateIrp(pDevExt->BusDeviceObject->StackSize, FALSE);
  107. ASSERT(pIrp);
  108. if(!pIrp)
  109. return;
  110. pIrb = pSrbToCancel->SRBExtension;
  111. pIrb->Flags = 0;
  112. pIrb->FunctionNumber = REQUEST_ISOCH_DETACH_BUFFERS;
  113. pIrb->u.IsochDetachBuffers.hResource = hResource;
  114. pIrb->u.IsochDetachBuffers.nNumberOfDescriptors = 1;
  115. pIrb->u.IsochDetachBuffers.pIsochDescriptor = IsochDescriptorToDetach;
  116. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  117. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  118. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  119. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  120. IoSetCompletionRoutine(
  121. pIrp,
  122. DCamCancelOnePacketCR,
  123. IsochDescriptorToDetach,
  124. TRUE,
  125. TRUE,
  126. TRUE
  127. );
  128. Status =
  129. IoCallDriver(
  130. pBusDeviceObject,
  131. pIrp
  132. );
  133. ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PENDING);
  134. }
  135. VOID
  136. DCamCancelOnePacket(
  137. IN PHW_STREAM_REQUEST_BLOCK pSrbToCancel
  138. )
  139. /*++
  140. Routine Description:
  141. This routine is called to cancel a pending streaming SRB. This is likely to
  142. happen when transitioning from PAUSE to STOP state.
  143. Note: This routine is called at DISPATCH_LEVEL !!
  144. Arguments:
  145. pSrbToCancel - Pointer to SRB to cancel
  146. Return Value:
  147. None.
  148. --*/
  149. {
  150. PHW_STREAM_REQUEST_BLOCK pSrbInQ;
  151. PISOCH_DESCRIPTOR IsochDescriptorToDetach;
  152. PDCAM_EXTENSION pDevExt;
  153. PSTREAMEX pStrmEx;
  154. PLIST_ENTRY pEntry; // Pointer to an isoch decriptor reserved structure
  155. KIRQL oldIrql;
  156. BOOL Found;
  157. pDevExt = (PDCAM_EXTENSION) pSrbToCancel->HwDeviceExtension;
  158. ASSERT(pDevExt);
  159. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  160. ASSERT(pStrmEx);
  161. // Nothing to cancel
  162. if(pStrmEx == NULL) {
  163. return;
  164. }
  165. //
  166. // We only expect stream SRB, but not device SRB.
  167. //
  168. if ( (pSrbToCancel->Flags & SRB_HW_FLAGS_STREAM_REQUEST) != SRB_HW_FLAGS_STREAM_REQUEST) {
  169. ERROR_LOG(("DCamCancelOnePacket: Cannot cancel Device SRB %x\n", pSrbToCancel));
  170. ASSERT( (pSrbToCancel->Flags & SRB_HW_FLAGS_STREAM_REQUEST) == SRB_HW_FLAGS_STREAM_REQUEST );
  171. return;
  172. }
  173. //
  174. // Loop through the linked list from the beginning to end,
  175. // trying to find the SRB to cancel
  176. //
  177. KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
  178. Found = FALSE;
  179. pEntry = pDevExt->IsochDescriptorList.Flink;
  180. while (pEntry != &pDevExt->IsochDescriptorList) {
  181. pSrbInQ = ((PISOCH_DESCRIPTOR_RESERVED)pEntry)->Srb;
  182. IsochDescriptorToDetach = \
  183. (PISOCH_DESCRIPTOR) ( ((PUCHAR) pEntry) -
  184. FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));
  185. if(pSrbToCancel == pSrbInQ) {
  186. // If we are in RUN state, we could be competing with IsochCallback;
  187. // Whichever grabs and change STATE_DETACHING_BUFFERS will detach.
  188. if(((PISOCH_DESCRIPTOR_RESERVED) pEntry)->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS)) {
  189. Found = FALSE; // IsochCallback are detaching it (we lost our chance).
  190. ERROR_LOG(("DCamCancelOnePacket: pSrbToCancel %x, Descriptor %x, Reserved %x already detaching or completed\n",
  191. pSrbToCancel, IsochDescriptorToDetach, pEntry));
  192. } else {
  193. ((PISOCH_DESCRIPTOR_RESERVED) pEntry)->Flags |= STATE_DETACHING_BUFFERS;
  194. #if DBG
  195. // Should not have been detached.
  196. ASSERT((IsochDescriptorToDetach->DeviceReserved[7] == 0x87654321));
  197. IsochDescriptorToDetach->DeviceReserved[7]++;
  198. #endif
  199. RemoveEntryList(pEntry);
  200. InterlockedDecrement(&pDevExt->PendingReadCount);
  201. Found = TRUE;
  202. }
  203. break;
  204. }
  205. pEntry = pEntry->Flink; // Next
  206. }
  207. KeReleaseSpinLock (&pDevExt->IsochDescriptorLock, oldIrql);
  208. //
  209. // Since we are in DISPATCH level, we cannot do sync operation;
  210. // so we will complete this asynchronously in the completion routine.
  211. //
  212. if (Found) {
  213. DCamDetachAndCancelOnePacket(
  214. pSrbToCancel,
  215. IsochDescriptorToDetach,
  216. pDevExt->hResource,
  217. pDevExt->BusDeviceObject);
  218. } else {
  219. ERROR_LOG(("DCamCancelOnePacket: pSrbToCancel %x is not in our list!\n", pSrbToCancel));
  220. ASSERT(Found);
  221. }
  222. }
  223. VOID
  224. DCamCancelAllPackets(
  225. PHW_STREAM_REQUEST_BLOCK pSrb,
  226. PDCAM_EXTENSION pDevExt,
  227. LONG *plPendingReadCount
  228. )
  229. /*++
  230. Routine Description:
  231. This routine is use to cancel all pending IRP.
  232. Can be called at DISPATCH_LEVEL.
  233. Arguments:
  234. pSrbToCancel - Pointer to SRB to cancel
  235. pDevExt - Device's contect
  236. plPendingReadCount - Number of pending read
  237. Return Value:
  238. None.
  239. --*/
  240. {
  241. PHW_STREAM_REQUEST_BLOCK pSrbToCancel;
  242. PISOCH_DESCRIPTOR IsochDescriptorToDetach;
  243. PLIST_ENTRY pEntry;
  244. KIRQL oldIrql;
  245. PSTREAMEX pStrmEx;
  246. pStrmEx = pDevExt->pStrmEx;
  247. // Nothing to cancel
  248. if(pStrmEx == NULL) {
  249. return;
  250. }
  251. //
  252. // Loop through the linked list from the beginning to end,
  253. // trying to find the SRB to cancel
  254. //
  255. KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
  256. pEntry = pDevExt->IsochDescriptorList.Flink;
  257. while (pEntry != &pDevExt->IsochDescriptorList) {
  258. pSrbToCancel = ((PISOCH_DESCRIPTOR_RESERVED)pEntry)->Srb;
  259. IsochDescriptorToDetach = \
  260. (PISOCH_DESCRIPTOR) ( ((PUCHAR) pEntry) -
  261. FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));
  262. if(((PISOCH_DESCRIPTOR_RESERVED) pEntry)->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS)) {
  263. // Skip this one since it is already in detaching phase or completed.
  264. ERROR_LOG(("DCamCancelAllPacket: pSrbToCancel %x, Descriptor %x, Reserved %x already detaching or completed\n",
  265. pSrbToCancel, IsochDescriptorToDetach, pEntry));
  266. pEntry = pEntry->Flink; // next
  267. } else {
  268. ((PISOCH_DESCRIPTOR_RESERVED) pEntry)->Flags |= STATE_DETACHING_BUFFERS;
  269. #if DBG
  270. // Should not have been detached.
  271. ASSERT((IsochDescriptorToDetach->DeviceReserved[7] == 0x87654321));
  272. IsochDescriptorToDetach->DeviceReserved[7]++;
  273. #endif
  274. RemoveEntryList(pEntry);
  275. InterlockedDecrement(plPendingReadCount);
  276. DbgMsg2(("DCamCancelAllPackets: pSrbToCancel %x, Descriptor %x, Reserved %x\n",
  277. pSrbToCancel, IsochDescriptorToDetach, pEntry));
  278. pEntry = pEntry->Flink; // pEntry is deleted in DCamDetachAndCancelOnePacket(); so get next here.
  279. DCamDetachAndCancelOnePacket(
  280. pSrbToCancel,
  281. IsochDescriptorToDetach,
  282. pDevExt->hResource,
  283. pDevExt->BusDeviceObject);
  284. }
  285. }
  286. KeReleaseSpinLock (&pDevExt->IsochDescriptorLock, oldIrql);
  287. pSrb->Status = STATUS_SUCCESS;
  288. DbgMsg1(("DCamCancelAllPackets: Complete pSrb %x, Status %x\n", pSrb, pSrb->Status));
  289. COMPLETE_SRB(pSrb)
  290. }
  291. VOID
  292. DCamSurpriseRemoval(
  293. IN PHW_STREAM_REQUEST_BLOCK pSrb
  294. )
  295. /*++
  296. Routine Description:
  297. Response to SRB_SURPRISE_REMOVAL.
  298. Arguments:
  299. pSrb - Pointer to the stream request block
  300. Return Value:
  301. None.
  302. --*/
  303. {
  304. PIRP pIrp;
  305. PIRB pIrb;
  306. PDCAM_EXTENSION pDevExt;
  307. PSTREAMEX pStrmEx;
  308. NTSTATUS Status, StatusWait;
  309. PAGED_CODE();
  310. pIrb = (PIRB) pSrb->SRBExtension;
  311. ASSERT(pIrb);
  312. pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
  313. ASSERT(pDevExt);
  314. //
  315. // Set this to stop accepting incoming read.
  316. //
  317. pDevExt->bDevRemoved = TRUE;
  318. //
  319. // Wait for currect read to be attached so we cancel them all.
  320. //
  321. pStrmEx = pDevExt->pStrmEx;
  322. if(pStrmEx) {
  323. // Make sure that this structure is still valid.
  324. if(pStrmEx->pVideoInfoHeader) {
  325. StatusWait = KeWaitForSingleObject( &pStrmEx->hMutex, Executive, KernelMode, FALSE, 0 );
  326. KeReleaseMutex(&pStrmEx->hMutex, FALSE);
  327. }
  328. }
  329. pIrp = IoAllocateIrp(pDevExt->BusDeviceObject->StackSize, FALSE);
  330. if(!pIrp) {
  331. ERROR_LOG(("DCamSurpriseRemovalPacket: faile to get resource; pIrb=%x, pDevExt=%x, pIrp\n", pIrb, pDevExt, pIrp));
  332. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  333. StreamClassDeviceNotification(DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
  334. return;
  335. }
  336. //
  337. // un-register a bus reset callback notification
  338. //
  339. pIrb->FunctionNumber = REQUEST_BUS_RESET_NOTIFICATION;
  340. pIrb->Flags = 0;
  341. pIrb->u.BusResetNotification.fulFlags = DEREGISTER_NOTIFICATION_ROUTINE;
  342. pIrb->u.BusResetNotification.ResetRoutine = (PBUS_BUS_RESET_NOTIFICATION) DCamBusResetNotification;
  343. pIrb->u.BusResetNotification.ResetContext = 0;
  344. Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
  345. if(Status) {
  346. ERROR_LOG(("DCamSurpriseRemoval: Status %x while trying to deregister bus reset notification.\n", Status));
  347. }
  348. //
  349. // Get new generation number
  350. //
  351. pIrb->FunctionNumber = REQUEST_GET_GENERATION_COUNT;
  352. pIrb->Flags = 0;
  353. Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
  354. if(Status) {
  355. ERROR_LOG(("DCamSurpriseRemoval: Status %x while trying to get generation number.\n", Status));
  356. } else {
  357. DbgMsg1(("DCamSurpriseRemoval: pDevExt %x, Generation number from %d to %d\n",
  358. pDevExt, pDevExt->CurrentGeneration, pIrb->u.GetGenerationCount.GenerationCount));
  359. InterlockedExchange(&pDevExt->CurrentGeneration, pIrb->u.GetGenerationCount.GenerationCount);
  360. }
  361. if(pStrmEx) {
  362. //
  363. // Stop isoch transmission so we can detach buffers and cancel pending SRBs
  364. //
  365. pIrb->FunctionNumber = REQUEST_ISOCH_STOP;
  366. pIrb->Flags = 0;
  367. pIrb->u.IsochStop.hResource = pDevExt->hResource;
  368. pIrb->u.IsochStop.fulFlags = 0;
  369. Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
  370. if(Status) {
  371. ERROR_LOG(("DCamSurpriseRemoval: Status %x while trying to ISOCH_STOP.\n", Status));
  372. }
  373. IoFreeIrp(pIrp);
  374. DCamCancelAllPackets(
  375. pSrb,
  376. pDevExt,
  377. &pDevExt->PendingReadCount
  378. );
  379. } else {
  380. IoFreeIrp(pIrp);
  381. StreamClassDeviceNotification(DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
  382. }
  383. }
  384. NTSTATUS
  385. DCamAttachBufferCR(
  386. IN PDEVICE_OBJECT DeviceObject,
  387. IN PIRP pIrp,
  388. IN PISOCH_DESCRIPTOR IsochDescriptor
  389. )
  390. /*++
  391. Routine Description:
  392. This routine is the completion routine from attaching a bufffer to lower driver.
  393. Arguments:
  394. DriverObject - Pointer to driver object created by system.
  395. pIrp - Irp that just completed
  396. pDCamIoContext - A structure that contain the context of this IO completion routine.
  397. Return Value:
  398. None.
  399. --*/
  400. {
  401. PHW_STREAM_REQUEST_BLOCK pSrb;
  402. PDCAM_EXTENSION pDevExt;
  403. PSTREAMEX pStrmEx;
  404. NTSTATUS Status;
  405. PIRB pIrb;
  406. PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
  407. KIRQL oldIrql;
  408. pDevExt = (PDCAM_EXTENSION) IsochDescriptor->Context1;
  409. ASSERT(pDevExt);
  410. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  411. ASSERT(pStrmEx);
  412. IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
  413. ASSERT(IsochDescriptorReserved);
  414. pSrb = IsochDescriptorReserved->Srb;
  415. ASSERT(pSrb);
  416. pIrb = (PIRB) pSrb->SRBExtension;
  417. DbgMsg3(("\'DCamAttachBufferCR: completed KSSTATE=%d; pIrp->IoStatus.Status=%x; pSrb=%x\n",
  418. pStrmEx->KSState, pIrp->IoStatus.Status, pSrb));
  419. //
  420. // Attaching a buffer return with error.
  421. //
  422. if(pIrp->IoStatus.Status) {
  423. ERROR_LOG(("DCamAttachBufferCR: pIrp->IoStatus.Status=%x (STATUS_PENDING=%x); complete SRB with this status.\n",
  424. pIrp->IoStatus.Status, STATUS_PENDING));
  425. ASSERT(pIrp->IoStatus.Status == STATUS_SUCCESS);
  426. if(!(IsochDescriptorReserved->Flags & STATE_SRB_IS_COMPLETE)) {
  427. ASSERT(((IsochDescriptorReserved->Flags & STATE_SRB_IS_COMPLETE) != STATE_SRB_IS_COMPLETE));
  428. IsochDescriptorReserved->Flags |= STATE_SRB_IS_COMPLETE;
  429. pSrb->Status = pIrp->IoStatus.Status; // Read is completed with error status.
  430. KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
  431. RemoveEntryList(&IsochDescriptorReserved->DescriptorList); InterlockedDecrement(&pDevExt->PendingReadCount);
  432. KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);
  433. ExFreePool(IsochDescriptor);
  434. StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
  435. KeAcquireSpinLock(&pDevExt->IsochWaitingLock, &oldIrql);
  436. //
  437. // If we failed to attach (rtn with failed status),
  438. // removed this entry, and
  439. // pull one out of the waiting list if not yet exceeded out limit.
  440. //
  441. if (!IsListEmpty(&pDevExt->IsochWaitingList) && pDevExt->PendingReadCount >= MAX_BUFFERS_SUPPLIED) {
  442. //
  443. // We had someone blocked waiting for us to complete. Pull
  444. // them off the waiting list and get them running
  445. //
  446. DbgMsg3(("\'DCamAttachBufferCR: Dequeueing request - Read Count=%d\n", pDevExt->PendingReadCount));
  447. IsochDescriptorReserved = \
  448. (PISOCH_DESCRIPTOR_RESERVED) RemoveHeadList(
  449. &pDevExt->IsochWaitingList
  450. );
  451. KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);
  452. IsochDescriptor = \
  453. (PISOCH_DESCRIPTOR) (((PUCHAR) IsochDescriptorReserved) -
  454. FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));
  455. DCamReadStreamWorker(IsochDescriptorReserved->Srb, IsochDescriptor);
  456. } else {
  457. KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);
  458. }
  459. } else {
  460. // Race condition ? or a valid error code?
  461. ERROR_LOG(("DCamAttachBufferCR: IsochDescriptorReserved->Flags contain STATE_SRB_IS_COMPLETE\n"));
  462. ASSERT(FALSE);
  463. }
  464. }
  465. //
  466. // Ealier when we set to RUN state, it might have failed with
  467. // STATUS_INSUFFICIENT_RESOURCE due to no buffer attached;
  468. // we have at least one now, ask controll to start listen and
  469. // fill and return our buffer.
  470. //
  471. if(pDevExt->bNeedToListen) {
  472. PIRB pIrb2;
  473. PIRP pIrp2;
  474. PDCAM_IO_CONTEXT pDCamIoContext;
  475. PIO_STACK_LOCATION NextIrpStack;
  476. if(!DCamAllocateIrbIrpAndContext(&pDCamIoContext, &pIrb2, &pIrp2, pDevExt->BusDeviceObject->StackSize)) {
  477. ERROR_LOG(("DCamAttachBufferCR: Want to stat Listening but no resource !!\n"));
  478. return STATUS_MORE_PROCESSING_REQUIRED;
  479. }
  480. pDevExt->bNeedToListen = FALSE;
  481. DbgMsg2(("\'DCamAttachBufferCR: ##### pDevExt->bNeedToListen\n"));
  482. pDCamIoContext->pDevExt = pDevExt;
  483. pDCamIoContext->pIrb = pIrb2;
  484. pIrb2->FunctionNumber = REQUEST_ISOCH_LISTEN;
  485. pIrb2->Flags = 0;
  486. pIrb2->u.IsochListen.hResource = pDevExt->hResource;
  487. pIrb2->u.IsochListen.fulFlags = 0;
  488. NextIrpStack = IoGetNextIrpStackLocation(pIrp2);
  489. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  490. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  491. NextIrpStack->Parameters.Others.Argument1 = pIrb2;
  492. pDevExt->lRetries = RETRY_COUNT;
  493. IoSetCompletionRoutine(
  494. pIrp2,
  495. DCamStartListenCR,
  496. pDCamIoContext,
  497. TRUE,
  498. TRUE,
  499. TRUE
  500. );
  501. Status =
  502. IoCallDriver(
  503. pDevExt->BusDeviceObject,
  504. pIrp2);
  505. }
  506. // No resource to freed.
  507. // Resource (pIrb is from original SRB)
  508. return STATUS_MORE_PROCESSING_REQUIRED;
  509. //
  510. // The attached SRB read will be completed in IoschCallback().
  511. //
  512. }
  513. NTSTATUS
  514. DCamReSubmitPacketCR(
  515. IN PDEVICE_OBJECT DeviceObject,
  516. IN PIRP pIrp,
  517. IN PISOCH_DESCRIPTOR IsochDescriptor
  518. )
  519. /*++
  520. Routine Description:
  521. This routine is called after a packet is detach and
  522. will be attached here to complete the resubmission of
  523. packet after a isoch. resource change.
  524. Arguments:
  525. DriverObject - Pointer to driver object created by system.
  526. pIrp - Irp that just completed
  527. pDCamIoContext - A structure that contain the context of this IO completion routine.
  528. Return Value:
  529. None.
  530. --*/
  531. {
  532. PIRB pIrb;
  533. PIO_STACK_LOCATION NextIrpStack;
  534. PDCAM_EXTENSION pDevExt;
  535. PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
  536. NTSTATUS Status;
  537. pDevExt = IsochDescriptor->Context1;
  538. ASSERT(pDevExt);
  539. pIrb = (PIRB) IsochDescriptor->DeviceReserved[6];
  540. ASSERT(pIrb);
  541. IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
  542. //
  543. // Detached, so unmark it.
  544. //
  545. IsochDescriptorReserved->Flags &= ~STATE_DETACHING_BUFFERS;
  546. DbgMsg2(("\'DCamReSubmitPacketCR: ReSubmit pDevExt %x, pIrb %x, hResource %x, IsochDescriptor %x, IsochDescriptorReserved %x\n",
  547. pDevExt, pIrb, pDevExt->hResource, IsochDescriptor, IsochDescriptorReserved));
  548. #if DBG
  549. //
  550. // Put signatures and use these count to track if the IsochDescriptor
  551. // has been attached or detached unexpectely.
  552. //
  553. // When attach, [4]++ (DCamReadStreamWorker(), DCamReSumbitPacketCR())
  554. // detach, [7]++ (DCamIsochcallback(), DCamCancelPacketCR(), DCamResubmitPacket())
  555. //
  556. IsochDescriptor->DeviceReserved[4] = 0x12345678;
  557. IsochDescriptor->DeviceReserved[7] = 0x87654321;
  558. #endif
  559. //
  560. // Attach descriptor onto our pending descriptor list
  561. //
  562. ExInterlockedInsertTailList(
  563. &pDevExt->IsochDescriptorList,
  564. &IsochDescriptorReserved->DescriptorList,
  565. &pDevExt->IsochDescriptorLock
  566. );
  567. pIrb->FunctionNumber = REQUEST_ISOCH_ATTACH_BUFFERS;
  568. pIrb->Flags = 0;
  569. pIrb->u.IsochAttachBuffers.hResource = pDevExt->hResource;
  570. pIrb->u.IsochAttachBuffers.nNumberOfDescriptors = 1;
  571. pIrb->u.IsochAttachBuffers.pIsochDescriptor = IsochDescriptor;
  572. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  573. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  574. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  575. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  576. IoSetCompletionRoutine(
  577. pIrp,
  578. DCamAttachBufferCR,
  579. IsochDescriptor,
  580. TRUE,
  581. TRUE,
  582. TRUE
  583. );
  584. Status =
  585. IoCallDriver(
  586. pDevExt->BusDeviceObject,
  587. pIrp
  588. );
  589. ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PENDING);
  590. return STATUS_MORE_PROCESSING_REQUIRED; // Complete Asynchronously in DCamAttachBufferCR
  591. }
  592. NTSTATUS
  593. DCamReSubmitPacket(
  594. HANDLE hStaleResource,
  595. PDCAM_EXTENSION pDevExt,
  596. PSTREAMEX pStrmEx,
  597. LONG cntPendingRead
  598. )
  599. /*++
  600. Routine Description:
  601. Due to a bus reset, if a channel number has changed (subsequently, iso resource
  602. change too), we must detach and re-attach pending packet(s).
  603. While this function is executed, incoming SRB_READ is blocked and isoch callback
  604. are returned and not processed (we are resubmiting them).
  605. Arguments:
  606. hStaleResource - staled isoch resource
  607. pDevExt - Device's Extension
  608. pStrmEx - Stremaing extension
  609. cntPendingRead - Number of pending packets
  610. Return Value:
  611. NTSTATUS.
  612. --*/
  613. {
  614. PIRB pIrb;
  615. PIRP pIrp;
  616. PIO_STACK_LOCATION NextIrpStack;
  617. PISOCH_DESCRIPTOR IsochDescriptor;
  618. PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
  619. NTSTATUS Status = STATUS_SUCCESS;
  620. KIRQL oldIrql;
  621. DbgMsg1(("DCamReSubmitPacket: pDevExt %x, pStrmEx %x, PendingCount %d\n", pDevExt, pStrmEx, cntPendingRead));
  622. for(; cntPendingRead > 0; cntPendingRead--) {
  623. if(!IsListEmpty(&pDevExt->IsochDescriptorList)) {
  624. //
  625. // Synchronization note:
  626. //
  627. // We are competing with cancel packet routine in the
  628. // event of device removal or setting to STOP state.
  629. // which ever got the spin lock to set DEATCH_BUFFER
  630. // flag take ownership completing the Irp/IsochDescriptor.
  631. //
  632. KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
  633. IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) RemoveHeadList(&pDevExt->IsochDescriptorList);
  634. if((IsochDescriptorReserved->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS))) {
  635. ERROR_LOG(("DCamReSubmitPacket: Flags %x aleady mark STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS\n", IsochDescriptorReserved->Flags));
  636. ASSERT(( !(IsochDescriptorReserved->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS))));\
  637. //Put it back since it has been detached.
  638. InsertTailList(&pDevExt->IsochDescriptorList, &IsochDescriptorReserved->DescriptorList);
  639. KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);
  640. continue;
  641. }
  642. IsochDescriptorReserved->Flags |= STATE_DETACHING_BUFFERS;
  643. KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);
  644. IsochDescriptor = (PISOCH_DESCRIPTOR) (((PUCHAR) IsochDescriptorReserved) - FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));
  645. pIrp = (PIRP) IsochDescriptor->DeviceReserved[5];
  646. ASSERT(pIrp);
  647. pIrb = (PIRB) IsochDescriptor->DeviceReserved[6];
  648. ASSERT(pIrb);
  649. DbgMsg1(("DCamReSubmitPacket: detaching IsochDescriptor %x IsochDescriptorReserved %x, pSrb %x\n",
  650. IsochDescriptor, IsochDescriptorReserved, IsochDescriptorReserved->Srb));
  651. #if DBG
  652. // Should not have been detached
  653. ASSERT((IsochDescriptor->DeviceReserved[7] == 0x87654321));
  654. IsochDescriptor->DeviceReserved[7]++;
  655. #endif
  656. pIrb->FunctionNumber = REQUEST_ISOCH_DETACH_BUFFERS;
  657. pIrb->Flags = 0;
  658. pIrb->u.IsochDetachBuffers.hResource = hStaleResource;
  659. pIrb->u.IsochDetachBuffers.nNumberOfDescriptors = 1;
  660. pIrb->u.IsochDetachBuffers.pIsochDescriptor = IsochDescriptor;
  661. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  662. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  663. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  664. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  665. IoSetCompletionRoutine(
  666. pIrp,
  667. DCamReSubmitPacketCR,
  668. IsochDescriptor,
  669. TRUE,
  670. TRUE,
  671. TRUE
  672. );
  673. Status =
  674. IoCallDriver(
  675. pDevExt->BusDeviceObject,
  676. pIrp
  677. );
  678. ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PENDING);
  679. } else {
  680. ERROR_LOG(("PendingCount %d, but list is empty!!\n", cntPendingRead));
  681. ASSERT(cntPendingRead == 0);
  682. }
  683. } // for()
  684. return Status;
  685. }
  686. VOID
  687. DCamReadStreamWorker(
  688. IN PHW_STREAM_REQUEST_BLOCK pSrb,
  689. IN PISOCH_DESCRIPTOR IsochDescriptor
  690. )
  691. /*++
  692. Routine Description:
  693. Does most of the work for handling reads via Attach buffers
  694. Arguments:
  695. Srb - Pointer to Stream request block
  696. IsochDescriptor - Pointer to IsochDescriptor to be used
  697. Return Value:
  698. Nothing
  699. --*/
  700. {
  701. PIRB pIrb;
  702. PIRP pIrp;
  703. PIO_STACK_LOCATION NextIrpStack;
  704. PDCAM_EXTENSION pDevExt;
  705. PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
  706. NTSTATUS Status;
  707. pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
  708. pIrp = (PIRP) IsochDescriptor->DeviceReserved[5];
  709. ASSERT(pIrp);
  710. pIrb = (PIRB) IsochDescriptor->DeviceReserved[6];
  711. ASSERT(pIrb);
  712. #if DBG
  713. // track number time the same IsochDescriptor are attaching; should only be one.
  714. IsochDescriptor->DeviceReserved[4]++;
  715. #endif
  716. //
  717. // It is pending and will be completed in isoch callback or cancelled.
  718. //
  719. pSrb->Status = STATUS_PENDING;
  720. IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
  721. DbgMsg3(("\'DCamReadStreamWorker: enter with pSrb = %x, pDevExt=0x%x\n", pSrb, pDevExt));
  722. //
  723. // Attach descriptor onto our pending descriptor list
  724. //
  725. ExInterlockedInsertTailList(
  726. &pDevExt->IsochDescriptorList,
  727. &IsochDescriptorReserved->DescriptorList,
  728. &pDevExt->IsochDescriptorLock
  729. );
  730. pIrb->FunctionNumber = REQUEST_ISOCH_ATTACH_BUFFERS;
  731. pIrb->Flags = 0;
  732. pIrb->u.IsochAttachBuffers.hResource = pDevExt->hResource;
  733. pIrb->u.IsochAttachBuffers.nNumberOfDescriptors = 1;
  734. pIrb->u.IsochAttachBuffers.pIsochDescriptor = IsochDescriptor;
  735. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  736. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  737. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  738. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  739. IoSetCompletionRoutine(
  740. pIrp,
  741. DCamAttachBufferCR,
  742. IsochDescriptor,
  743. TRUE,
  744. TRUE,
  745. TRUE
  746. );
  747. Status =
  748. IoCallDriver(
  749. pDevExt->BusDeviceObject,
  750. pIrp
  751. );
  752. ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PENDING);
  753. return; // Complete Asynchronously in IoCompletionRoutine*
  754. }
  755. VOID
  756. DCamReadStream(
  757. IN PHW_STREAM_REQUEST_BLOCK Srb
  758. )
  759. /*++
  760. Routine Description:
  761. Called when an Read Data Srb request is received
  762. Arguments:
  763. Srb - Pointer to Stream request block
  764. Return Value:
  765. Nothing
  766. --*/
  767. {
  768. PIRB pIrb;
  769. PIRP pIrp;
  770. KIRQL oldIrql;
  771. PDCAM_EXTENSION pDevExt;
  772. PSTREAMEX pStrmEx;
  773. PISOCH_DESCRIPTOR IsochDescriptor;
  774. PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
  775. NTSTATUS StatusWait;
  776. pIrb = (PIRB) Srb->SRBExtension;
  777. pDevExt = (PDCAM_EXTENSION) Srb->HwDeviceExtension;
  778. ASSERT(pDevExt != NULL);
  779. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  780. ASSERT(pStrmEx);
  781. if(pDevExt->bDevRemoved ||
  782. pStrmEx == NULL) {
  783. Srb->Status = pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_UNSUCCESSFUL;
  784. Srb->ActualBytesTransferred = 0;
  785. Srb->CommandData.DataBufferArray->DataUsed = 0;
  786. ERROR_LOG(("DCamReadStream: Failed with Status %x or pStrmEx %x\n", Srb->Status, pStrmEx));
  787. StreamClassStreamNotification(StreamRequestComplete, Srb->StreamObject, Srb);
  788. return;
  789. }
  790. //
  791. // Mutext for either StreamIo (SRB_READ) ControlIo (SRB_SET_STREAM_STATE)
  792. //
  793. // Non-alertable; wait infinite
  794. StatusWait = KeWaitForSingleObject( &pStrmEx->hMutex, Executive, KernelMode, FALSE, 0 );
  795. ASSERT(StatusWait == STATUS_SUCCESS);
  796. DbgMsg3(("\'%d:%s) DCamReadStream: enter with Srb %x, DevExt %x\n",
  797. pDevExt->idxDev, pDevExt->pchVendorName, Srb, pDevExt));
  798. // Rule:
  799. // Only accept read requests when in either the Pause or Run
  800. // States. If Stopped, immediately return the SRB.
  801. if (pStrmEx->KSState == KSSTATE_STOP ||
  802. pStrmEx->KSState == KSSTATE_ACQUIRE) {
  803. DbgMsg2(("\'%d:%s)DCamReadStream: Current KSState(%d) < (%d)=KSSTATE_PAUSE; Srb=0x%x; DevExt=0x%x",
  804. pDevExt->idxDev, pDevExt->pchVendorName, pStrmEx->KSState, KSSTATE_PAUSE, Srb, pDevExt));
  805. DbgMsg2(("\'DCamReadStream: PendingRead=%d, IsochDescriptorList(%s)\n",
  806. pDevExt->PendingReadCount, IsListEmpty(&pDevExt->IsochDescriptorList)?"Empty":"!Empty"));
  807. Srb->Status = STATUS_UNSUCCESSFUL;
  808. Srb->CommandData.DataBufferArray->DataUsed = 0;
  809. StreamClassStreamNotification(StreamRequestComplete, Srb->StreamObject, Srb);
  810. KeReleaseMutex(&pStrmEx->hMutex, FALSE);
  811. return;
  812. }
  813. // Buffer need to be big enough
  814. if (IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize > Srb->CommandData.DataBufferArray->FrameExtent) {
  815. ASSERT(IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize <= Srb->CommandData.DataBufferArray->FrameExtent);
  816. Srb->Status = STATUS_INVALID_PARAMETER;
  817. StreamClassStreamNotification(StreamRequestComplete, Srb->StreamObject, Srb);
  818. KeReleaseMutex(&pStrmEx->hMutex, FALSE);
  819. return;
  820. }
  821. //
  822. // Use our own IRP
  823. //
  824. pIrp = IoAllocateIrp(pDevExt->BusDeviceObject->StackSize, FALSE);
  825. if(!pIrp) {
  826. ASSERT(pIrp);
  827. Srb->Status = STATUS_INSUFFICIENT_RESOURCES;
  828. return;
  829. }
  830. //
  831. // This structure (IsochDescriptor) has (ULONG) DeviceReserved[8];
  832. // Its first 4 ULONGs are used by IsochDescriptorReserved,
  833. // The 6th (index[5]), is used to keep pIrp
  834. // 7th (index[6]), is used to keep pIrb
  835. //
  836. IsochDescriptor = ExAllocatePoolWithTag(NonPagedPool, sizeof(ISOCH_DESCRIPTOR), 'macd');
  837. if (!IsochDescriptor) {
  838. ASSERT(FALSE);
  839. Srb->Status = STATUS_INSUFFICIENT_RESOURCES;
  840. StreamClassStreamNotification(StreamRequestComplete, Srb->StreamObject, Srb);
  841. KeReleaseMutex(&pStrmEx->hMutex, FALSE);
  842. return;
  843. }
  844. DbgMsg3(("\'DCamReadStream: IsochDescriptor = %x\n", IsochDescriptor));
  845. IsochDescriptor->fulFlags = SYNCH_ON_SY;
  846. DbgMsg3(("\'DCamReadStream: Incoming Mdl = %x\n", Srb->Irp->MdlAddress));
  847. IsochDescriptor->Mdl = Srb->Irp->MdlAddress;
  848. // Use size match what we originally requested in AllocateIsoch
  849. IsochDescriptor->ulLength = IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize;
  850. IsochDescriptor->nMaxBytesPerFrame = IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2;
  851. IsochDescriptor->ulSynch = START_OF_PICTURE;
  852. IsochDescriptor->ulTag = 0;
  853. IsochDescriptor->Callback = DCamIsochCallback;
  854. IsochDescriptor->Context1 = pDevExt;
  855. IsochDescriptor->Context2 = IsochDescriptor;
  856. //
  857. // IsochDescriptorReserved is pointed to the DeviceReserved[0];
  858. // The entire, except the links, are kept in the DeviceReserved[]
  859. //
  860. IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
  861. IsochDescriptorReserved->Srb = Srb;
  862. IsochDescriptorReserved->Flags = 0;
  863. IsochDescriptor->DeviceReserved[5] = (ULONG_PTR) pIrp;
  864. IsochDescriptor->DeviceReserved[6] = (ULONG_PTR) pIrb;
  865. #if DBG
  866. //
  867. // Put signatures and use these count to track if the IsochDescriptor
  868. // has been attached or detached unexpectely.
  869. //
  870. // When attach, [4]++ (DCamReadStreamWorker(), DCamReSumbitPacketCR())
  871. // detach, [7]++ (DCamIsochcallback(), DCamCancelPacketCR(), DCamResubmitPacket())
  872. //
  873. IsochDescriptor->DeviceReserved[4] = 0x12345678;
  874. IsochDescriptor->DeviceReserved[7] = 0x87654321;
  875. #endif
  876. //
  877. // Checking here to see if we have enuff resources to put this read
  878. // down right away. Since we only allocated N amount of resources
  879. // from the 1394 stack beneath us, we'll have to stay within that
  880. // limit and do some of the throttling ourself.
  881. //
  882. KeAcquireSpinLock(&pDevExt->IsochWaitingLock, &oldIrql);
  883. if (InterlockedIncrement(&pDevExt->PendingReadCount) > MAX_BUFFERS_SUPPLIED) {
  884. //
  885. // don't have enuff resources to do an attach buffers right now.
  886. // we'll queue this request and pull it off later when another
  887. // read completes.
  888. //
  889. DbgMsg2(("\'DCamReadStream: Queueing request - Read Count = %x\n", pDevExt->PendingReadCount));
  890. InsertTailList(
  891. &pDevExt->IsochWaitingList,
  892. &IsochDescriptorReserved->DescriptorList
  893. );
  894. KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);
  895. KeReleaseMutex(&pStrmEx->hMutex, FALSE);
  896. return;
  897. }
  898. if(pStrmEx->KSState == KSSTATE_PAUSE) {
  899. DbgMsg2(("\'DCamReadStream: Doing Pre-read in _PAUSE state; Srb %x, pDevExt %x, PendingCount %d\n",
  900. Srb, pDevExt, pDevExt->PendingReadCount));
  901. }
  902. //
  903. // Do actual read work here via our Read worker function
  904. //
  905. KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);
  906. DCamReadStreamWorker(Srb, IsochDescriptor);
  907. KeReleaseMutex(&pStrmEx->hMutex, FALSE);
  908. }
  909. VOID
  910. DCamReceiveDataPacket(
  911. IN PHW_STREAM_REQUEST_BLOCK Srb
  912. )
  913. /*++
  914. Routine Description:
  915. Called with video data packet commands
  916. Arguments:
  917. Srb - Pointer to Stream request block
  918. Return Value:
  919. Nothing
  920. --*/
  921. {
  922. PAGED_CODE();
  923. //
  924. // determine the type of packet.
  925. //
  926. switch (Srb->Command) {
  927. case SRB_READ_DATA:
  928. DbgMsg3(("\'DCamReceiveDataPacket: SRB_READ_DATA\n"));
  929. DCamReadStream(Srb);
  930. // This request will be completed asynchronously...
  931. break;
  932. case SRB_WRITE_DATA:
  933. DbgMsg3(("\'DCamReceiveDataPacket: SRB_WRITE_DATA, not used for digital camera.\n"));
  934. ASSERT(FALSE);
  935. default:
  936. //
  937. // invalid / unsupported command. Fail it as such
  938. //
  939. Srb->Status = STATUS_NOT_IMPLEMENTED;
  940. StreamClassStreamNotification(StreamRequestComplete, Srb->StreamObject, Srb);
  941. }
  942. }