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.

963 lines
32 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1999 - 2000
  3. Module Name:
  4. MSDVUppr.c
  5. Abstract:
  6. Interface code with stream class driver.
  7. Last changed by:
  8. Author: Yee J. Wu
  9. Environment:
  10. Kernel mode only
  11. Revision History:
  12. $Revision:: $
  13. $Date:: $
  14. --*/
  15. #include "strmini.h"
  16. #include "ksmedia.h"
  17. #include "1394.h"
  18. #include "61883.h"
  19. #include "avc.h"
  20. #include "dbg.h"
  21. #include "msdvfmt.h"
  22. #include "msdvdef.h"
  23. #include "MsdvGuts.h" // Function prototypes
  24. #include "MsdvAvc.h"
  25. #include "MsdvUtil.h"
  26. #include "EDevCtrl.h"
  27. #ifdef TIME_BOMB
  28. #include "..\..\inc\timebomb.c"
  29. #endif
  30. // global flag for debugging. Inlines are defined in dbg.h. The debug level is set for
  31. // minimal amount of messages.
  32. #if DBG
  33. #define DVTraceMaskCheckIn TL_PNP_ERROR | TL_STRM_ERROR | TL_61883_ERROR
  34. #define DVTraceMaskDefault TL_PNP_ERROR | TL_PNP_WARNING \
  35. | TL_61883_ERROR | TL_61883_WARNING \
  36. | TL_CIP_ERROR \
  37. | TL_FCP_ERROR \
  38. | TL_STRM_ERROR | TL_STRM_WARNING \
  39. | TL_CLK_ERROR
  40. #define DVTraceMaskDebug TL_PNP_ERROR | TL_PNP_WARNING \
  41. | TL_61883_ERROR| TL_61883_WARNING \
  42. | TL_CIP_ERROR \
  43. | TL_FCP_ERROR | TL_FCP_WARNING \
  44. | TL_STRM_ERROR | TL_STRM_WARNING \
  45. | TL_CLK_ERROR
  46. #ifdef USE_WDM110 // Win2000 code base
  47. ULONG DVTraceMask = DVTraceMaskCheckIn | TL_FCP_ERROR;
  48. #else
  49. ULONG DVTraceMask = DVTraceMaskCheckIn;
  50. #endif
  51. ULONG DVAssertLevel = 1; // Turn on assert (>0)
  52. ULONG DVDebugXmt = 0; // Debug data transfer flag; (> 0) to turn it on.
  53. #endif
  54. extern DV_FORMAT_INFO DVFormatInfoTable[];
  55. //
  56. // Function prototypes
  57. //
  58. VOID
  59. DVRcvStreamDevicePacket(
  60. IN PHW_STREAM_REQUEST_BLOCK pSrb
  61. );
  62. VOID
  63. DVSRBRead(
  64. IN PKSSTREAM_HEADER pStrmHeader,
  65. IN ULONG ulFrameSize,
  66. IN PDVCR_EXTENSION pDevExt,
  67. IN PSTREAMEX pStrmExt,
  68. IN PHW_STREAM_REQUEST_BLOCK pSrb // needs Srb->Status
  69. );
  70. NTSTATUS
  71. DVAttachWriteFrame(
  72. IN PSTREAMEX pStrmExt
  73. );
  74. NTSTATUS
  75. DriverEntry(
  76. IN PDRIVER_OBJECT DriverObject,
  77. IN PUNICODE_STRING RegistryPath
  78. );
  79. #if 0 // Enable later
  80. #ifdef ALLOC_PRAGMA
  81. #pragma alloc_text(PAGE, DVRcvStreamDevicePacket)
  82. #pragma alloc_text(PAGE, DVRcvControlPacket)
  83. #pragma alloc_text(PAGE, DVRcvDataPacket)
  84. // #pragma alloc_text(INIT, DriverEntry)
  85. #endif
  86. #endif
  87. VOID
  88. DVRcvStreamDevicePacket(
  89. IN PHW_STREAM_REQUEST_BLOCK pSrb
  90. )
  91. /*++
  92. Routine Description:
  93. This is where most of the interesting Stream requests come to us
  94. --*/
  95. {
  96. PDVCR_EXTENSION pDevExt;
  97. PAV_61883_REQUEST pAVReq;
  98. PIO_STACK_LOCATION pIrpStack;
  99. PAGED_CODE();
  100. //
  101. // Get these extensions from a SRB
  102. //
  103. pDevExt = (PDVCR_EXTENSION) pSrb->HwDeviceExtension;
  104. pAVReq = (PAV_61883_REQUEST) pSrb->SRBExtension; // Use in IrpSync is OK,
  105. #if DBG
  106. if(pSrb->Command != SRB_INITIALIZE_DEVICE && // PowerState is initialize in this SRB so ignore it.
  107. pDevExt->PowerState != PowerDeviceD0) {
  108. TRACE(TL_PNP_WARNING,("RcvDevPkt; pSrb:%x; Cmd:%x; Dev is OFF state\n", pSrb, pSrb->Command));
  109. }
  110. #endif
  111. TRACE(TL_PNP_TRACE,("\'DVRcvStreamDevicePacket: pSrb %x, Cmd %d, pdevExt %x\n", pSrb, pSrb->Command, pDevExt));
  112. //
  113. // Assume success
  114. //
  115. pSrb->Status = STATUS_SUCCESS;
  116. switch (pSrb->Command) {
  117. case SRB_INITIALIZE_DEVICE:
  118. ASSERT(((PPORT_CONFIGURATION_INFORMATION) pSrb->CommandData.ConfigInfo)->HwDeviceExtension == pDevExt);
  119. pSrb->Status =
  120. DVInitializeDevice(
  121. (PDVCR_EXTENSION) ((PPORT_CONFIGURATION_INFORMATION)pSrb->CommandData.ConfigInfo)->HwDeviceExtension,
  122. pSrb->CommandData.ConfigInfo,
  123. pAVReq
  124. );
  125. break;
  126. case SRB_INITIALIZATION_COMPLETE:
  127. //
  128. // Stream class has finished initialization. Get device interface registry value/
  129. //
  130. DVInitializeCompleted(
  131. (PDVCR_EXTENSION) pSrb->HwDeviceExtension);
  132. break;
  133. case SRB_GET_STREAM_INFO:
  134. //
  135. // this is a request for the driver to enumerate requested streams
  136. //
  137. pSrb->Status =
  138. DVGetStreamInfo(
  139. pDevExt,
  140. pSrb->NumberOfBytesToTransfer,
  141. &pSrb->CommandData.StreamBuffer->StreamHeader,
  142. &pSrb->CommandData.StreamBuffer->StreamInfo
  143. );
  144. break;
  145. case SRB_GET_DATA_INTERSECTION:
  146. // Since format can dynamically change, we will query new format here.
  147. // Note: during data intersection, we compare FrameSize and that is
  148. // format related.
  149. if((GetSystemTime() - pDevExt->tmLastFormatUpdate) > FORMAT_UPDATE_INTERVAL) {
  150. // Get mode of operation (Camera or VCR)
  151. DVGetDevModeOfOperation(pDevExt);
  152. if(!DVGetDevSignalFormat(pDevExt, KSPIN_DATAFLOW_OUT,0)) {
  153. // If querying its format has failed, we cannot open this stream.
  154. TRACE(TL_STRM_WARNING,("SRB_GET_DATA_INTERSECTION:Failed getting signal format.\n"));
  155. }
  156. // Update system time to reflect last update
  157. pDevExt->tmLastFormatUpdate = GetSystemTime();
  158. }
  159. pSrb->Status =
  160. DVGetDataIntersection(
  161. pSrb->CommandData.IntersectInfo->StreamNumber,
  162. pSrb->CommandData.IntersectInfo->DataRange,
  163. pSrb->CommandData.IntersectInfo->DataFormatBuffer,
  164. pSrb->CommandData.IntersectInfo->SizeOfDataFormatBuffer,
  165. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize,
  166. &pSrb->ActualBytesTransferred,
  167. pDevExt->paCurrentStrmInfo
  168. #ifdef SUPPORT_NEW_AVC
  169. ,pDevExt->paCurrentStrmInfo[pSrb->CommandData.IntersectInfo->StreamNumber].DataFlow == KSPIN_DATAFLOW_OUT ? pDevExt->hOPcrDV : pDevExt->hIPcrDV
  170. #endif
  171. );
  172. break;
  173. case SRB_OPEN_STREAM:
  174. //
  175. // Serialize SRB_OPEN/CLOSE_STREAMs
  176. //
  177. KeWaitForSingleObject( &pDevExt->hMutex, Executive, KernelMode, FALSE, 0 );
  178. pSrb->Status =
  179. DVOpenStream(
  180. pSrb->StreamObject,
  181. pSrb->CommandData.OpenFormat,
  182. pAVReq
  183. );
  184. KeReleaseMutex(&pDevExt->hMutex, FALSE);
  185. break;
  186. case SRB_CLOSE_STREAM:
  187. //
  188. // Serialize SRB_OPEN/CLOSE_STREAMs
  189. //
  190. KeWaitForSingleObject( &pDevExt->hMutex, Executive, KernelMode, FALSE, 0 );
  191. pSrb->Status =
  192. DVCloseStream(
  193. pSrb->StreamObject,
  194. pSrb->CommandData.OpenFormat,
  195. pAVReq
  196. );
  197. KeReleaseMutex(&pDevExt->hMutex, FALSE);
  198. break;
  199. case SRB_GET_DEVICE_PROPERTY:
  200. pSrb->Status =
  201. DVGetDeviceProperty(
  202. pDevExt,
  203. pSrb->CommandData.PropertyInfo,
  204. &pSrb->ActualBytesTransferred
  205. );
  206. break;
  207. case SRB_SET_DEVICE_PROPERTY:
  208. pSrb->Status =
  209. DVSetDeviceProperty(
  210. pDevExt,
  211. pSrb->CommandData.PropertyInfo,
  212. &pSrb->ActualBytesTransferred
  213. );
  214. break;
  215. case SRB_CHANGE_POWER_STATE:
  216. pIrpStack = IoGetCurrentIrpStackLocation(pSrb->Irp);
  217. if(pIrpStack->MinorFunction == IRP_MN_SET_POWER) {
  218. pSrb->Status =
  219. DVChangePower(
  220. (PDVCR_EXTENSION) pSrb->HwDeviceExtension,
  221. pAVReq,
  222. pSrb->CommandData.DeviceState
  223. );
  224. } else
  225. if(pIrpStack->MinorFunction == IRP_MN_QUERY_POWER) {
  226. TRACE(TL_PNP_WARNING,("IRP_MN_QUERY_POWER: PwrSt:%d\n", pDevExt->PowerState));
  227. pSrb->Status = STATUS_SUCCESS;
  228. }
  229. else {
  230. TRACE(TL_PNP_WARNING,("NOT_IMPL POWER_STATE MinorFunc:%d\n", pIrpStack->MinorFunction));
  231. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  232. }
  233. break;
  234. case SRB_UNKNOWN_DEVICE_COMMAND:
  235. //
  236. // We might be interested in unknown commands if they pertain
  237. // to bus resets. Bus resets are important cuz we need to know
  238. // what the current generation count is.
  239. //
  240. pIrpStack = IoGetCurrentIrpStackLocation(pSrb->Irp);
  241. if(pIrpStack->MajorFunction == IRP_MJ_PNP) {
  242. if(pIrpStack->MinorFunction == IRP_MN_BUS_RESET) {
  243. DVProcessPnPBusReset(
  244. pDevExt
  245. );
  246. // Always success
  247. pSrb->Status = STATUS_SUCCESS;
  248. }
  249. else {
  250. /* Known: IRP_MN_QUERY_PNP_DEVICE_STATE */
  251. TRACE(TL_PNP_WARNING,("\'DVRcvStreamDevicePacket: NOT_IMPL; IRP_MJ_PNP IRP_MN_:%x\n",
  252. pIrpStack->MinorFunction
  253. ));
  254. // Canot return STATUS_NOT_SUPPORTED for PNP irp or device will not load.
  255. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  256. }
  257. }
  258. else {
  259. TRACE(TL_PNP_WARNING,("\'DVRcvStreamDevicePacket: NOT_IMPL; IRP_MJ_ %x; IRP_MN_:%x\n",
  260. pIrpStack->MajorFunction,
  261. pIrpStack->MinorFunction
  262. ));
  263. // Canot return STATUS_NOT_SUPPORTED for PNP irp or device will not load.
  264. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  265. }
  266. break;
  267. case SRB_SURPRISE_REMOVAL:
  268. TRACE(TL_PNP_WARNING,("\' #SURPRISE_REMOVAL# pSrb %x, pDevExt %x\n", pSrb, pDevExt));
  269. pSrb->Status =
  270. DVSurpriseRemoval(
  271. pDevExt,
  272. pAVReq
  273. );
  274. break;
  275. case SRB_UNINITIALIZE_DEVICE:
  276. TRACE(TL_PNP_WARNING,("\' #UNINITIALIZE_DEVICE# pSrb %x, pDevExt %x\n", pSrb, pDevExt));
  277. pSrb->Status =
  278. DVUninitializeDevice(
  279. (PDVCR_EXTENSION) pSrb->HwDeviceExtension
  280. );
  281. break;
  282. default:
  283. TRACE(TL_PNP_WARNING,("\'DVRcvStreamDevicePacket: Unknown or unprocessed SRB cmd 0x%x\n", pSrb->Command));
  284. //
  285. // this is a request that we do not understand. Indicate invalid
  286. // command and complete the request
  287. //
  288. pSrb->Status = STATUS_NOT_IMPLEMENTED; // SUPPORTED;
  289. }
  290. //
  291. // NOTE:
  292. //
  293. // all of the commands that we do, or do not understand can all be completed
  294. // synchronously at this point, so we can use a common callback routine here.
  295. // If any of the above commands require asynchronous processing, this will
  296. // have to change
  297. //
  298. #if DBG
  299. if (pSrb->Status != STATUS_SUCCESS &&
  300. pSrb->Status != STATUS_NOT_SUPPORTED &&
  301. pSrb->Status != STATUS_NOT_IMPLEMENTED &&
  302. pSrb->Status != STATUS_BUFFER_TOO_SMALL &&
  303. pSrb->Status != STATUS_BUFFER_OVERFLOW &&
  304. pSrb->Status != STATUS_NO_MATCH
  305. && pSrb->Status != STATUS_TIMEOUT
  306. ) {
  307. TRACE(TL_PNP_WARNING,("\'pSrb->Command (%x) ->Status:%x\n", pSrb->Command, pSrb->Status));
  308. }
  309. #endif
  310. if(STATUS_PENDING != pSrb->Status) {
  311. StreamClassDeviceNotification(
  312. DeviceRequestComplete,
  313. pSrb->HwDeviceExtension,
  314. pSrb
  315. );
  316. }
  317. else {
  318. // Pending pSrb which will be completed asynchronously
  319. // Does StreamClass allow device SRB to be in the pending state?
  320. TRACE(TL_PNP_WARNING,("\'DVReceiveDevicePacket:Pending pSrb %x\n", pSrb));
  321. }
  322. }
  323. VOID
  324. DVRcvControlPacket(
  325. IN PHW_STREAM_REQUEST_BLOCK pSrb
  326. )
  327. /*++
  328. Routine Description:
  329. Called with packet commands that control the video stream
  330. --*/
  331. {
  332. PAV_61883_REQUEST pAVReq;
  333. PSTREAMEX pStrmExt;
  334. PDVCR_EXTENSION pDevExt;
  335. PAGED_CODE();
  336. //
  337. // Get these three extension from SRB
  338. //
  339. pAVReq = (PAV_61883_REQUEST) pSrb->SRBExtension; // This is OK to be used us IrpSync operation
  340. pDevExt = (PDVCR_EXTENSION) pSrb->HwDeviceExtension;
  341. pStrmExt = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension; // Only valid in SRB_OPEN/CLOSE_STREAM
  342. ASSERT(pStrmExt && pDevExt && pAVReq);
  343. //
  344. // Default to success
  345. //
  346. pSrb->Status = STATUS_SUCCESS;
  347. switch (pSrb->Command) {
  348. case SRB_GET_STREAM_STATE:
  349. pSrb->Status =
  350. DVGetStreamState(
  351. pStrmExt,
  352. &(pSrb->CommandData.StreamState),
  353. &(pSrb->ActualBytesTransferred)
  354. );
  355. break;
  356. case SRB_SET_STREAM_STATE:
  357. pSrb->Status =
  358. DVSetStreamState(
  359. pStrmExt,
  360. pDevExt,
  361. pAVReq,
  362. pSrb->CommandData.StreamState // Target KSSTATE
  363. );
  364. break;
  365. case SRB_GET_STREAM_PROPERTY:
  366. pSrb->Status =
  367. DVGetStreamProperty(
  368. pSrb
  369. );
  370. break;
  371. case SRB_SET_STREAM_PROPERTY:
  372. pSrb->Status =
  373. DVSetStreamProperty(
  374. pSrb
  375. );
  376. break;
  377. case SRB_OPEN_MASTER_CLOCK:
  378. case SRB_CLOSE_MASTER_CLOCK:
  379. //
  380. // This stream is being selected to provide a Master clock.
  381. //
  382. pSrb->Status =
  383. DVOpenCloseMasterClock(
  384. pStrmExt,
  385. pSrb->Command == SRB_OPEN_MASTER_CLOCK ? pSrb->CommandData.MasterClockHandle: NULL);
  386. break;
  387. case SRB_INDICATE_MASTER_CLOCK:
  388. //
  389. // Assigns a clock to a stream.
  390. //
  391. pSrb->Status =
  392. DVIndicateMasterClock(
  393. pStrmExt,
  394. pSrb->CommandData.MasterClockHandle);
  395. break;
  396. case SRB_PROPOSE_DATA_FORMAT:
  397. //
  398. // The SRB_PROPOSE_DATA_FORMAT command queries the minidriver
  399. // to determine if the minidriver can change the format of a
  400. // particular stream. If the minidriver is able to switch the
  401. // stream to the specified format, STATUS_SUCCESS is returned.
  402. // Note that this function only proposes a new format, but does
  403. // not change it.
  404. //
  405. // The CommandData.OpenFormat passes the format to validate.
  406. // If the minidriver is able to accept the new format, at some
  407. // later time the class driver may send the minidriver a format
  408. // change, which is indicated by an OptionsFlags flag in a
  409. // KSSTREAM_HEADER structure.
  410. //
  411. TRACE(TL_STRM_INFO,("\'DVRcvControlPacket: SRB_PROPOSE_DATA_FORMAT\n"));
  412. if(!DVVerifyDataFormat(
  413. pSrb->CommandData.OpenFormat,
  414. pSrb->StreamObject->StreamNumber,
  415. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize,
  416. pDevExt->paCurrentStrmInfo
  417. )) {
  418. TRACE(TL_STRM_WARNING,("\'DVRcvControlPacket: AdapterVerifyFormat failed.\n"));
  419. pSrb->Status = STATUS_NO_MATCH;
  420. }
  421. break;
  422. case SRB_PROPOSE_STREAM_RATE:
  423. pSrb->Status = STATUS_NOT_IMPLEMENTED; // if returned STATUS_NOT_SUPPORTED, it will send EOStream.
  424. TRACE(TL_STRM_TRACE,("\'SRB_PROPOSE_STREAM_RATE: NOT_IMPLEMENTED!\n"));
  425. break;
  426. case SRB_BEGIN_FLUSH:
  427. pSrb->Status = STATUS_NOT_SUPPORTED;
  428. TRACE(TL_STRM_TRACE,("\'SRB_BEGIN_FLUSH: NOT_SUPPORTED!\n"));
  429. break;
  430. case SRB_END_FLUSH:
  431. pSrb->Status = STATUS_NOT_SUPPORTED;
  432. TRACE(TL_STRM_TRACE,("\'SRB_END_FLUSH: NOT_SUPPORTED!\n"));
  433. break;
  434. default:
  435. //
  436. // invalid / unsupported command. Fail it as such
  437. //
  438. TRACE(TL_STRM_WARNING,("\'DVRcvControlPacket: unknown cmd = %x\n",pSrb->Command));
  439. pSrb->Status = STATUS_NOT_IMPLEMENTED; // SUPPORTED;
  440. }
  441. TRACE(TL_STRM_TRACE,("\'DVRcvControlPacket: Command %x, ->Status %x, ->CommandData %x\n",
  442. pSrb->Command, pSrb->Status, &(pSrb->CommandData.StreamState) ));
  443. StreamClassStreamNotification(
  444. StreamRequestComplete,
  445. pSrb->StreamObject,
  446. pSrb);
  447. }
  448. VOID
  449. DVRcvDataPacket(
  450. IN PHW_STREAM_REQUEST_BLOCK pSrb
  451. )
  452. /*++
  453. Routine Description:
  454. Called with video data packet commands
  455. --*/
  456. {
  457. PSTREAMEX pStrmExt;
  458. PDVCR_EXTENSION pDevExt;
  459. PAGED_CODE();
  460. pStrmExt = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension;
  461. pDevExt = (PDVCR_EXTENSION) pSrb->HwDeviceExtension;
  462. #if DBG
  463. if(pDevExt->PowerState != PowerDeviceD0) {
  464. TRACE(TL_STRM_WARNING|TL_PNP_WARNING,("\'SRB_READ/WRITE; PowerSt:OFF; pSrb:%x\n", pSrb));
  465. }
  466. #endif
  467. // The stream has to be open before we can do anything.
  468. if (pStrmExt == NULL) {
  469. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("DVRcvDataPacket: stream not opened for SRB %x. kicking out...\n", pSrb->Command));
  470. pSrb->Status = STATUS_UNSUCCESSFUL;
  471. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  472. StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
  473. return;
  474. }
  475. //
  476. // Serialize attach, cancel and state change
  477. //
  478. KeWaitForSingleObject( pStrmExt->hStreamMutex, Executive, KernelMode, FALSE, 0 );
  479. TRACE(TL_CIP_TRACE,("\'XXX_DATA(%d, %d);Srb:%x;Flg:%x;FExt:%d:%d\n",
  480. (DWORD) pStrmExt->cntSRBReceived,
  481. (DWORD) pSrb->CommandData.DataBufferArray->PresentationTime.Time/10000,
  482. pSrb,
  483. pSrb->CommandData.DataBufferArray->OptionsFlags,
  484. pSrb->CommandData.DataBufferArray->FrameExtent,
  485. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize
  486. ));
  487. //
  488. // determine the type of packet.
  489. //
  490. pSrb->Status = STATUS_SUCCESS;
  491. #if DBG
  492. pStrmExt->cntSRBPending++;
  493. #endif
  494. switch (pSrb->Command) {
  495. case SRB_READ_DATA:
  496. // Rule:
  497. // Only accept read requests when in either the Pause or Run
  498. // States. If Stopped, immediately return the SRB.
  499. if (pStrmExt->lCancelStateWorkItem) {
  500. // TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("\'SRB_READ_DATA: Abort while getting SRB_READ_DATA!\n"));
  501. // ASSERT(pStrmExt->lCancelStateWorkItem == 0 && "Encounter SRB_READ_DATA while aborting or aborted.\n");
  502. pSrb->Status = (pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_CANCELLED);
  503. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  504. break;
  505. } else if( pStrmExt->StreamState == KSSTATE_STOP ||
  506. pStrmExt->StreamState == KSSTATE_ACQUIRE ||
  507. pStrmExt->hConnect == NULL ||
  508. pDevExt->bDevRemoved
  509. ) {
  510. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("\'SRB_READ_DATA: (DV->) State %d, bDevRemoved %d\n", pStrmExt->StreamState, pDevExt->bDevRemoved));
  511. pSrb->Status = (pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_CANCELLED);
  512. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  513. break;
  514. } else {
  515. TRACE(TL_STRM_INFO|TL_CIP_INFO,("\'SRB_READ_DATA pSrb %x, pStrmExt %x\n", pSrb, pStrmExt));
  516. pStrmExt->cntSRBReceived++;
  517. // Set state thread in halt while while Read/Write SRB is being processed
  518. DVSRBRead(
  519. pSrb->CommandData.DataBufferArray,
  520. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize,
  521. pDevExt,
  522. pStrmExt,
  523. pSrb
  524. );
  525. KeReleaseMutex(pStrmExt->hStreamMutex, FALSE);
  526. // Note: This SRB will be completed asynchronously.
  527. return;
  528. }
  529. break;
  530. case SRB_WRITE_DATA:
  531. if( pStrmExt->StreamState == KSSTATE_STOP ||
  532. pStrmExt->StreamState == KSSTATE_ACQUIRE ||
  533. #ifdef SUPPORT_NEW_AVC
  534. (pStrmExt->hConnect == NULL && !pStrmExt->bDV2DVConnect) ||
  535. #else
  536. pStrmExt->hConnect == NULL ||
  537. #endif
  538. pDevExt->bDevRemoved
  539. ) {
  540. pSrb->Status = (pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_CANCELLED);
  541. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  542. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\'SRB_WRITE_DATA: (DV->) State %d, bDevRemoved %d; Status:%x\n", pStrmExt->StreamState, pDevExt->bDevRemoved, pSrb->Status));
  543. break; // Complete SRB with error status
  544. } else {
  545. KIRQL oldIrql;
  546. PLONG plSrbUseCount; // When this count is 0, it can be completed.
  547. TRACE(TL_STRM_INFO|TL_CIP_INFO,("\'SRB_WRITE_DATA pSrb %x, pStrmExt %x\n", pSrb, pStrmExt));
  548. //
  549. // Process EOSream frame separately
  550. //
  551. if(pSrb->CommandData.DataBufferArray->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_ENDOFSTREAM) {
  552. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  553. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\'*** EOStream: ST:%d; bIsochIsActive:%d; Wait (cndAttached:%d+cndSRQ:%d) to complete......\n", \
  554. pStrmExt->StreamState, pStrmExt->bIsochIsActive, pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued));
  555. pStrmExt->bEOStream = TRUE;
  556. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  557. pSrb->Status = STATUS_SUCCESS;
  558. break;
  559. } else if(pSrb->CommandData.DataBufferArray->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED) {
  560. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\'DVRcvDataPacket:KSSTREAM_HEADER_OPTIONSF_TYPECHANGED.\n"));
  561. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  562. // May need to compare the data format; instead of return STATUS_SUCCESS??
  563. pSrb->Status = STATUS_SUCCESS; // May need to check the format when dynamic format change is allowed.
  564. break;
  565. #ifdef SUPPORT_NEW_AVC
  566. } else if(pStrmExt->bDV2DVConnect) {
  567. pSrb->Status = STATUS_SUCCESS;
  568. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  569. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\'SRB_WRITE_DATA: [DV2DV] (pStrmExt:%x), pSrb:%x, FrameExt:%d\n",
  570. pStrmExt, pSrb, pSrb->CommandData.DataBufferArray->FrameExtent));
  571. break;
  572. #endif
  573. } else {
  574. PSRB_ENTRY pSrbEntry;
  575. //
  576. // Validation
  577. //
  578. if(pSrb->CommandData.DataBufferArray->FrameExtent < DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize) {
  579. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("\' FrameExt %d < FrameSize %d\n", pSrb->CommandData.DataBufferArray->FrameExtent, DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize));
  580. ASSERT(pSrb->CommandData.DataBufferArray->FrameExtent >= DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize);
  581. pSrb->Status = STATUS_INVALID_PARAMETER;
  582. break; // Complete SRB with error status
  583. }
  584. //
  585. // Dynamically allocate a SRB_ENTRY and append it to SRBQueue
  586. //
  587. if(!(pSrbEntry = ExAllocatePool(NonPagedPool, sizeof(SRB_ENTRY)))) {
  588. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  589. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  590. break; // Complete SRB with error status
  591. }
  592. #if DBG
  593. if(pStrmExt->bEOStream) {
  594. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\'SRB_WRITE_DATA: pSrb:%x after EOStream!\n", pSrb));
  595. }
  596. #endif
  597. //
  598. // For statistics
  599. //
  600. pStrmExt->cntSRBReceived++;
  601. //
  602. // Save SRB and add it to SRB queue
  603. // No need for spin lock since StreamClass will serialize it for us.
  604. //
  605. pSrb->Status = STATUS_PENDING;
  606. pSrbEntry->pSrb = pSrb; pSrbEntry->bStale = FALSE; pSrbEntry->bAudioMute = FALSE;
  607. #if DBG
  608. pSrbEntry->SrbNum = (ULONG) pStrmExt->cntSRBReceived -1;
  609. #endif
  610. //
  611. // Note: plSrbUseCount is initialize to 1
  612. // When it is insert: ++
  613. // When it is removed: --
  614. // when this count is 0; it can be completed.
  615. //
  616. plSrbUseCount = (PLONG) pSrb->SRBExtension; *plSrbUseCount = 1; // Can be completed if this is 0
  617. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  618. InsertTailList(&pStrmExt->SRBQueuedListHead, &pSrbEntry->ListEntry); pStrmExt->cntSRBQueued++;
  619. TRACE(TL_CIP_INFO,("\'%d) Fresh Srb:%x; RefCnt:%d; cntSrbQ:%d\n", (DWORD) pStrmExt->cntSRBReceived, pSrb, *plSrbUseCount, pStrmExt->cntSRBQueued));
  620. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  621. #ifndef SUPPORT_PREROLL_AT_RUN_STATE
  622. //
  623. // Start the thread when it has at least one sample.
  624. //
  625. if(pStrmExt->cntSRBReceived == 1)
  626. KeSetEvent(&pStrmExt->hRunThreadEvent, 0 ,FALSE);
  627. // Will set this event in the preroll state.
  628. #else
  629. //
  630. // This is a special condition (with PREROLL):
  631. // 1. timeout on preroll (and is now in the RUN state), and
  632. // 2. no media sample
  633. // This will cause attach frame in the HALT state; so we will signal
  634. // it upon receiving 1st media sample; then attach frame can run.
  635. //
  636. if( pStrmExt->cntSRBReceived == 1
  637. && pStrmExt->bPrerollCompleted == TRUE
  638. && pStrmExt->bXmtThreadStarted == FALSE)
  639. {
  640. KeSetEvent(&pStrmExt->hRunThreadEvent, 0 ,FALSE);
  641. TRACE(TL_STRM_WARNING, ("Special Cond: RUN, HALT, 1st sample."));
  642. }
  643. #endif
  644. #ifdef SUPPORT_PREROLL_AT_RUN_STATE
  645. // We can operate "smoothly" if we have N media samples.
  646. if(pStrmExt->cntSRBReceived == NUM_BUFFER_BEFORE_TRANSMIT_BEGIN) {
  647. KeSetEvent(&pStrmExt->hPreRollEvent, 0, FALSE);
  648. }
  649. #endif
  650. if(pStrmExt->pAttachFrameThreadObject) {
  651. // Signal that a new frame has arrived.
  652. KeSetEvent(&pStrmExt->hSrbArriveEvent, 0, FALSE);
  653. }
  654. else {
  655. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("\'No thread to attach frame ?\n"));
  656. }
  657. }
  658. KeReleaseMutex(pStrmExt->hStreamMutex, FALSE);
  659. return; // Note: This SRB will be completed asynchronously.
  660. }
  661. break; // Complete SRB with error status
  662. default:
  663. //
  664. // invalid / unsupported command. Fail it as such
  665. //
  666. pSrb->Status = STATUS_NOT_SUPPORTED;
  667. break;
  668. }
  669. KeReleaseMutex(pStrmExt->hStreamMutex, FALSE);
  670. ASSERT(pSrb->Status != STATUS_PENDING);
  671. // Finally, send the srb back up ...
  672. StreamClassStreamNotification(
  673. StreamRequestComplete,
  674. pSrb->StreamObject,
  675. pSrb );
  676. #if DBG
  677. pStrmExt->cntSRBPending--;
  678. #endif
  679. }
  680. NTSTATUS
  681. DriverEntry(
  682. IN PDRIVER_OBJECT DriverObject,
  683. IN PUNICODE_STRING RegistryPath
  684. )
  685. /*++
  686. Routine Description:
  687. This where life begins for a driver. The stream class takes care
  688. of alot of stuff for us, but we still need to fill in an initialization
  689. structure for the stream class and call it.
  690. Arguments:
  691. Context1 - DriverObject
  692. Context2 - RegistryPath
  693. Return Value:
  694. The function value is the final status from the initialization operation.
  695. --*/
  696. {
  697. HW_INITIALIZATION_DATA HwInitData;
  698. TRACE(TL_PNP_ERROR,("<<<<<<< MSDV.sys: %s; %s; %x %x >>>>>>>>\n",
  699. __DATE__, __TIME__, DriverObject, RegistryPath));
  700. #ifdef TIME_BOMB
  701. if (HasEvaluationTimeExpired()) {
  702. TRACE(TL_PNP_ERROR, ("Evaluation period expired!") );
  703. return STATUS_EVALUATION_EXPIRATION;
  704. }
  705. #endif
  706. TRACE(TL_PNP_ERROR,("===================================================================\n"));
  707. TRACE(TL_PNP_ERROR,("DVTraceMask=0x%.8x = 0x[7][6][5][4][3][2][1][0] where\n", DVTraceMask));
  708. TRACE(TL_PNP_ERROR,("\n"));
  709. TRACE(TL_PNP_ERROR,("PNP: [0]:Loading, power state, surprise removal, device SRB..etc.\n"));
  710. TRACE(TL_PNP_ERROR,("61883: [1]:Plugs, connection, CMP info and call to 61883.\n"));
  711. TRACE(TL_PNP_ERROR,("CIP: [2]:Isoch data transfer.\n"));
  712. TRACE(TL_PNP_ERROR,("AVC: [3]:AVC commands.\n"));
  713. TRACE(TL_PNP_ERROR,("Stream:[4]:Data intersec, open/close,.state, property etc.\n"));
  714. TRACE(TL_PNP_ERROR,("Clock: [5]:Clock (event and signal)etc.\n"));
  715. TRACE(TL_PNP_ERROR,("===================================================================\n"));
  716. TRACE(TL_PNP_ERROR,("dd msdv!DVTraceMask L1\n"));
  717. TRACE(TL_PNP_ERROR,("e msdv!DVTraceMask <new value> <enter>\n"));
  718. TRACE(TL_PNP_ERROR,("<for each nibble: ERROR:8, WARNING:4, TRACE:2, INFO:1, MASK:f>\n"));
  719. TRACE(TL_PNP_ERROR,("===================================================================\n\n"));
  720. //
  721. // Fill in the HwInitData structure
  722. //
  723. RtlZeroMemory( &HwInitData, sizeof(HW_INITIALIZATION_DATA) );
  724. HwInitData.HwInitializationDataSize = sizeof(HwInitData);
  725. HwInitData.HwInterrupt = NULL;
  726. HwInitData.HwReceivePacket = DVRcvStreamDevicePacket;
  727. HwInitData.HwRequestTimeoutHandler = DVTimeoutHandler;
  728. HwInitData.HwCancelPacket = DVCancelOnePacket;
  729. HwInitData.DeviceExtensionSize = sizeof(DVCR_EXTENSION); // Per device
  730. //
  731. // The ULONG is used in SRB_WRITE_DATA to keep track of
  732. // number of times the same SRB was attached for transmit.
  733. //
  734. // Data SRB: ULONG is used (< sizeof(AV_61883_REQ)
  735. // DeviceControl or StreamControl Srb: AV_61883_REQ is used.
  736. HwInitData.PerRequestExtensionSize = sizeof(AV_61883_REQUEST); // Per SRB
  737. HwInitData.PerStreamExtensionSize = sizeof(STREAMEX); // Per pin/stream
  738. HwInitData.FilterInstanceExtensionSize = 0;
  739. HwInitData.BusMasterDMA = FALSE;
  740. HwInitData.Dma24BitAddresses = FALSE;
  741. HwInitData.BufferAlignment = sizeof(ULONG) - 1;
  742. HwInitData.TurnOffSynchronization = TRUE;
  743. HwInitData.DmaBufferSize = 0;
  744. return StreamClassRegisterAdapter(DriverObject, RegistryPath, &HwInitData);
  745. }