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
29 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1999 - 2000
  3. Module Name:
  4. MSTpUppr.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 "MsTpFmt.h"
  22. #include "MsTpDef.h"
  23. #include "MsTpGuts.h" // Function prototypes
  24. #include "MsTpAvc.h"
  25. #include "EDevCtrl.h"
  26. #ifdef TIME_BOMB
  27. #include "..\..\inc\timebomb.c"
  28. #endif
  29. #if DBG
  30. LONG MSDVCRMutextUseCount = 0;
  31. #endif
  32. // global flag for debugging. Inlines are defined in dbg.h. The debug level is set for
  33. // minimal amount of messages.
  34. #if DBG
  35. #define TraceMaskCheckIn TL_PNP_ERROR | TL_STRM_ERROR
  36. #define TraceMaskDefault TL_PNP_ERROR | TL_PNP_WARNING \
  37. | TL_61883_ERROR | TL_61883_WARNING \
  38. | TL_CIP_ERROR \
  39. | TL_FCP_ERROR \
  40. | TL_STRM_ERROR | TL_STRM_WARNING \
  41. | TL_CLK_ERROR
  42. #define TraceMaskDebug TL_PNP_ERROR | TL_PNP_WARNING \
  43. | TL_61883_ERROR| TL_61883_WARNING \
  44. | TL_CIP_ERROR \
  45. | TL_FCP_ERROR | TL_FCP_WARNING \
  46. | TL_STRM_ERROR | TL_STRM_WARNING \
  47. | TL_CLK_ERROR
  48. ULONG TapeTraceMask = TraceMaskCheckIn;
  49. ULONG TapeAssertLevel = 1;
  50. #endif
  51. extern AVCSTRM_FORMAT_INFO AVCStrmFormatInfoTable[];
  52. //
  53. // Function prototypes
  54. //
  55. VOID
  56. DVRcvStreamDevicePacket(
  57. IN PHW_STREAM_REQUEST_BLOCK pSrb
  58. );
  59. VOID
  60. DVSRBRead(
  61. IN PKSSTREAM_HEADER pStrmHeader,
  62. IN ULONG ulFrameSize,
  63. IN PDVCR_EXTENSION pDevExt,
  64. IN PSTREAMEX pStrmExt,
  65. IN PHW_STREAM_REQUEST_BLOCK pSrb // needs Srb->Status
  66. );
  67. BOOL
  68. DVSignalEOStream(
  69. IN PHW_STREAM_REQUEST_BLOCK pSrb,
  70. IN PSTREAMEX pStrmExt,
  71. IN FMT_INDEX ulVideoFormatIndex,
  72. IN ULONG ulOptionFlags
  73. );
  74. NTSTATUS
  75. DVAttachWriteFrame(
  76. IN PSTREAMEX pStrmExt
  77. );
  78. NTSTATUS
  79. DriverEntry(
  80. IN PDRIVER_OBJECT DriverObject,
  81. IN PUNICODE_STRING RegistryPath
  82. );
  83. #if 0 // Enable later
  84. #ifdef ALLOC_PRAGMA
  85. #pragma alloc_text(PAGE, DVRcvStreamDevicePacket)
  86. #pragma alloc_text(PAGE, AVCTapeRcvControlPacket)
  87. #pragma alloc_text(PAGE, AVCTapeRcvDataPacket)
  88. // #pragma alloc_text(INIT, DriverEntry)
  89. #endif
  90. #endif
  91. VOID
  92. DVRcvStreamDevicePacket(
  93. IN PHW_STREAM_REQUEST_BLOCK pSrb
  94. )
  95. /*++
  96. Routine Description:
  97. This is where most of the interesting Stream requests come to us
  98. --*/
  99. {
  100. PDVCR_EXTENSION pDevExt;
  101. PAV_61883_REQUEST pAVReq;
  102. PIO_STACK_LOCATION pIrpStack;
  103. PAGED_CODE();
  104. //
  105. // Get these extensions from a SRB
  106. //
  107. pDevExt = (PDVCR_EXTENSION) pSrb->HwDeviceExtension;
  108. pAVReq = (PAV_61883_REQUEST) pSrb->SRBExtension; // Use in IrpSync is OK,
  109. #if DBG
  110. if(pSrb->Command != SRB_INITIALIZE_DEVICE && // PowerState is initialize in this SRB so ignore it.
  111. pDevExt->PowerState != PowerDeviceD0) {
  112. TRACE(TL_PNP_WARNING,("RcvDevPkt; pSrb:%x; Cmd:%x; Dev is OFF state\n", pSrb, pSrb->Command));
  113. }
  114. #endif
  115. TRACE(TL_PNP_TRACE,("StreamDevicePacket: pSrb %x, Cmd %d, pdevExt %x\n", pSrb, pSrb->Command, pDevExt));
  116. //
  117. // Assume success
  118. //
  119. pSrb->Status = STATUS_SUCCESS;
  120. switch (pSrb->Command) {
  121. case SRB_INITIALIZE_DEVICE:
  122. ASSERT(((PPORT_CONFIGURATION_INFORMATION) pSrb->CommandData.ConfigInfo)->HwDeviceExtension == pDevExt);
  123. pSrb->Status =
  124. AVCTapeInitialize(
  125. (PDVCR_EXTENSION) ((PPORT_CONFIGURATION_INFORMATION)pSrb->CommandData.ConfigInfo)->HwDeviceExtension,
  126. pSrb->CommandData.ConfigInfo,
  127. pAVReq
  128. );
  129. break;
  130. case SRB_INITIALIZATION_COMPLETE:
  131. //
  132. // Stream class has finished initialization.
  133. // Now create DShow Medium interface BLOBs.
  134. // This needs to be done at low priority since it uses the registry, so use a callback
  135. //
  136. pSrb->Status =
  137. AVCTapeInitializeCompleted(
  138. pDevExt
  139. );
  140. break;
  141. case SRB_GET_STREAM_INFO:
  142. //
  143. // this is a request for the driver to enumerate requested streams
  144. //
  145. pSrb->Status =
  146. AVCTapeGetStreamInfo(
  147. pDevExt,
  148. pSrb->NumberOfBytesToTransfer,
  149. &pSrb->CommandData.StreamBuffer->StreamHeader,
  150. &pSrb->CommandData.StreamBuffer->StreamInfo
  151. );
  152. break;
  153. case SRB_GET_DATA_INTERSECTION:
  154. pSrb->Status =
  155. AVCTapeGetDataIntersection(
  156. pDevExt->NumOfPins,
  157. pSrb->CommandData.IntersectInfo->StreamNumber,
  158. pSrb->CommandData.IntersectInfo->DataRange,
  159. pSrb->CommandData.IntersectInfo->DataFormatBuffer,
  160. pSrb->CommandData.IntersectInfo->SizeOfDataFormatBuffer,
  161. AVCStrmFormatInfoTable[pDevExt->VideoFormatIndex].FrameSize,
  162. &pSrb->ActualBytesTransferred,
  163. pDevExt->pStreamInfoObject
  164. #ifdef SUPPORT_NEW_AVC
  165. ,
  166. pDevExt->hPlugLocalOut,
  167. pDevExt->hPlugLocalIn
  168. #endif
  169. );
  170. break;
  171. case SRB_OPEN_STREAM:
  172. //
  173. // Serialize SRB_OPEN_STREAMs
  174. //
  175. KeWaitForMutexObject(&pDevExt->hMutex, Executive, KernelMode, FALSE, NULL);
  176. pSrb->Status =
  177. AVCTapeOpenStream(
  178. pSrb->StreamObject,
  179. pSrb->CommandData.OpenFormat,
  180. pAVReq
  181. );
  182. KeReleaseMutex(&pDevExt->hMutex, FALSE);
  183. break;
  184. case SRB_CLOSE_STREAM:
  185. KeWaitForMutexObject(&pDevExt->hMutex, Executive, KernelMode, FALSE, NULL);
  186. pSrb->Status =
  187. AVCTapeCloseStream(
  188. pSrb->StreamObject,
  189. pSrb->CommandData.OpenFormat,
  190. pAVReq
  191. );
  192. KeReleaseMutex(&pDevExt->hMutex, FALSE);
  193. break;
  194. case SRB_GET_DEVICE_PROPERTY:
  195. pSrb->Status =
  196. AVCTapeGetDeviceProperty(
  197. pDevExt,
  198. pSrb->CommandData.PropertyInfo,
  199. &pSrb->ActualBytesTransferred
  200. );
  201. break;
  202. case SRB_SET_DEVICE_PROPERTY:
  203. pSrb->Status =
  204. AVCTapeSetDeviceProperty(
  205. pDevExt,
  206. pSrb->CommandData.PropertyInfo,
  207. &pSrb->ActualBytesTransferred
  208. );
  209. break;
  210. case SRB_CHANGE_POWER_STATE:
  211. pIrpStack = IoGetCurrentIrpStackLocation(pSrb->Irp);
  212. if(pIrpStack->MinorFunction == IRP_MN_SET_POWER) {
  213. pSrb->Status =
  214. DVChangePower(
  215. (PDVCR_EXTENSION) pSrb->HwDeviceExtension,
  216. pAVReq,
  217. pSrb->CommandData.DeviceState
  218. );
  219. } else
  220. if(pIrpStack->MinorFunction == IRP_MN_QUERY_POWER) {
  221. TRACE(TL_PNP_WARNING,("IRP_MN_QUERY_POWER: PwrSt:%d\n", pDevExt->PowerState));
  222. pSrb->Status = STATUS_SUCCESS;
  223. }
  224. else {
  225. TRACE(TL_PNP_WARNING,("Not Supported POWER_STATE MinorFunc:%d\n", pIrpStack->MinorFunction));
  226. pSrb->Status = STATUS_NOT_IMPLEMENTED; // STATUS_NOT_SUPPORTED;
  227. }
  228. break;
  229. case SRB_UNKNOWN_DEVICE_COMMAND:
  230. //
  231. // We might be interested in unknown commands if they pertain
  232. // to bus resets. Bus resets are important cuz we need to know
  233. // what the current generation count is.
  234. //
  235. pIrpStack = IoGetCurrentIrpStackLocation(pSrb->Irp);
  236. if(pIrpStack->MajorFunction == IRP_MJ_PNP) {
  237. if(pIrpStack->MinorFunction == IRP_MN_BUS_RESET) {
  238. AVCTapeProcessPnPBusReset(
  239. pDevExt
  240. );
  241. // Always success
  242. pSrb->Status = STATUS_SUCCESS;
  243. }
  244. else {
  245. TRACE(TL_PNP_TRACE,("StreamDevicePacket: NOT_IMPL; IRP_MJ_PNP Min:%x\n",
  246. pIrpStack->MinorFunction
  247. ));
  248. pSrb->Status = STATUS_NOT_IMPLEMENTED; // SUPPORTED;
  249. }
  250. }
  251. else
  252. pSrb->Status = STATUS_NOT_IMPLEMENTED; // SUPPORTED;
  253. break;
  254. case SRB_SURPRISE_REMOVAL:
  255. TRACE(TL_PNP_WARNING,("#SURPRISE_REMOVAL# pSrb %x, pDevExt %x\n", pSrb, pDevExt));
  256. pSrb->Status =
  257. AVCTapeSurpriseRemoval(
  258. pDevExt,
  259. pAVReq
  260. );
  261. break;
  262. case SRB_UNINITIALIZE_DEVICE:
  263. TRACE(TL_PNP_WARNING,("#UNINITIALIZE_DEVICE# pSrb %x, pDevExt %x\n", pSrb, pDevExt));
  264. pSrb->Status =
  265. AVCTapeUninitialize(
  266. (PDVCR_EXTENSION) pSrb->HwDeviceExtension
  267. );
  268. break;
  269. default:
  270. TRACE(TL_PNP_WARNING,("StreamDevicePacket: Unknown or unprocessed SRB cmd %x\n", pSrb->Command));
  271. //
  272. // this is a request that we do not understand. Indicate invalid
  273. // command and complete the request
  274. //
  275. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  276. }
  277. //
  278. // NOTE:
  279. //
  280. // all of the commands that we do, or do not understand can all be completed
  281. // synchronously at this point, so we can use a common callback routine here.
  282. // If any of the above commands require asynchronous processing, this will
  283. // have to change
  284. //
  285. #if DBG
  286. if (pSrb->Status != STATUS_SUCCESS &&
  287. pSrb->Status != STATUS_NOT_SUPPORTED &&
  288. pSrb->Status != STATUS_NOT_IMPLEMENTED &&
  289. pSrb->Status != STATUS_BUFFER_TOO_SMALL &&
  290. pSrb->Status != STATUS_BUFFER_OVERFLOW &&
  291. pSrb->Status != STATUS_NO_MATCH
  292. ) {
  293. TRACE(TL_PNP_WARNING,("StreamDevicePacket:pSrb->Command(0x%x) does not return STATUS_SUCCESS or NOT_IMPLEMENTED but 0x%x\n", pSrb->Command, pSrb->Status));
  294. }
  295. #endif
  296. if(STATUS_PENDING != pSrb->Status) {
  297. StreamClassDeviceNotification(
  298. DeviceRequestComplete,
  299. pSrb->HwDeviceExtension,
  300. pSrb
  301. );
  302. }
  303. else {
  304. // Pending pSrb which will be completed asynchronously
  305. TRACE(TL_PNP_WARNING,("ReceiveDevicePacket:Pending pSrb %x\n", pSrb));
  306. }
  307. }
  308. VOID
  309. AVCTapeRcvControlPacket(
  310. IN PHW_STREAM_REQUEST_BLOCK pSrb
  311. )
  312. /*++
  313. Routine Description:
  314. Called with packet commands that control the video stream
  315. --*/
  316. {
  317. PAV_61883_REQUEST pAVReq;
  318. PSTREAMEX pStrmExt;
  319. PDVCR_EXTENSION pDevExt;
  320. PAGED_CODE();
  321. //
  322. // Get these three extension from SRB
  323. //
  324. pAVReq = (PAV_61883_REQUEST) pSrb->SRBExtension; // This is OK to be used us IrpSync operation
  325. pDevExt = (PDVCR_EXTENSION) pSrb->HwDeviceExtension;
  326. pStrmExt = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension; // Only valid in SRB_OPEN/CLOSE_STREAM
  327. ASSERT(pStrmExt && pDevExt && pAVReq);
  328. //
  329. // Default to success
  330. //
  331. pSrb->Status = STATUS_SUCCESS;
  332. switch (pSrb->Command) {
  333. case SRB_GET_STREAM_STATE:
  334. pSrb->Status =
  335. AVCTapeGetStreamState(
  336. pStrmExt,
  337. pDevExt->pBusDeviceObject,
  338. &(pSrb->CommandData.StreamState),
  339. &(pSrb->ActualBytesTransferred)
  340. );
  341. break;
  342. case SRB_SET_STREAM_STATE:
  343. pSrb->Status =
  344. AVCTapeSetStreamState(
  345. pStrmExt,
  346. pDevExt,
  347. pAVReq,
  348. pSrb->CommandData.StreamState // Target KSSTATE
  349. );
  350. break;
  351. case SRB_GET_STREAM_PROPERTY:
  352. pSrb->Status =
  353. DVGetStreamProperty(
  354. pSrb
  355. );
  356. break;
  357. case SRB_SET_STREAM_PROPERTY:
  358. pSrb->Status =
  359. DVSetStreamProperty(
  360. pSrb
  361. );
  362. break;
  363. case SRB_OPEN_MASTER_CLOCK:
  364. case SRB_CLOSE_MASTER_CLOCK:
  365. //
  366. // This stream is being selected to provide a Master clock.
  367. //
  368. pSrb->Status =
  369. AVCTapeOpenCloseMasterClock(
  370. pStrmExt,
  371. pSrb->Command == SRB_OPEN_MASTER_CLOCK ? pSrb->CommandData.MasterClockHandle: NULL);
  372. break;
  373. case SRB_INDICATE_MASTER_CLOCK:
  374. //
  375. // Assigns a clock to a stream.
  376. //
  377. pSrb->Status =
  378. AVCTapeIndicateMasterClock(
  379. pStrmExt,
  380. pSrb->CommandData.MasterClockHandle);
  381. break;
  382. case SRB_PROPOSE_DATA_FORMAT:
  383. //
  384. // The SRB_PROPOSE_DATA_FORMAT command queries the minidriver
  385. // to determine if the minidriver can change the format of a
  386. // particular stream. If the minidriver is able to switch the
  387. // stream to the specified format, STATUS_SUCCESS is returned.
  388. // Note that this function only proposes a new format, but does
  389. // not change it.
  390. //
  391. // The CommandData.OpenFormat passes the format to validate.
  392. // If the minidriver is able to accept the new format, at some
  393. // later time the class driver may send the minidriver a format
  394. // change, which is indicated by an OptionsFlags flag in a
  395. // KSSTREAM_HEADER structure.
  396. //
  397. if(!AVCTapeVerifyDataFormat(
  398. pDevExt->NumOfPins,
  399. pSrb->CommandData.OpenFormat,
  400. pSrb->StreamObject->StreamNumber,
  401. AVCStrmFormatInfoTable[pDevExt->VideoFormatIndex].FrameSize,
  402. pDevExt->pStreamInfoObject
  403. )) {
  404. TRACE(TL_PNP_WARNING,("RcvControlPacket: AdapterVerifyFormat failed.\n"));
  405. pSrb->Status = STATUS_NO_MATCH;
  406. }
  407. break;
  408. default:
  409. //
  410. // invalid / unsupported command. Fail it as such
  411. //
  412. TRACE(TL_PNP_WARNING,("RcvControlPacket: unknown cmd = %x\n",pSrb->Command));
  413. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  414. }
  415. TRACE(TL_PNP_TRACE,("RcvControlPacket: pSrb:%x, Command %x, ->Status %x, ->CommandData %x\n",
  416. pSrb, pSrb->Command, pSrb->Status, &(pSrb->CommandData.StreamState) ));
  417. StreamClassStreamNotification(
  418. StreamRequestComplete,
  419. pSrb->StreamObject,
  420. pSrb);
  421. }
  422. VOID
  423. AVCTapeRcvDataPacket(
  424. IN PHW_STREAM_REQUEST_BLOCK pSrb
  425. )
  426. /*++
  427. Routine Description:
  428. Called with video data packet commands
  429. --*/
  430. {
  431. PSTREAMEX pStrmExt;
  432. PDVCR_EXTENSION pDevExt;
  433. PAVC_STREAM_REQUEST_BLOCK pAVCStrmReq;
  434. PIRP pIrpReq;
  435. PIO_STACK_LOCATION NextIrpStack;
  436. NTSTATUS Status;
  437. PDRIVER_REQUEST pDriverReq;
  438. KIRQL oldIrql;
  439. PAGED_CODE();
  440. pStrmExt = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension;
  441. pDevExt = (PDVCR_EXTENSION) pSrb->HwDeviceExtension;
  442. #if DBG
  443. if(pDevExt->PowerState != PowerDeviceD0) {
  444. TRACE(TL_PNP_WARNING,("SRB_READ/WRITE; PowerSt:OFF; pSrb:%x\n", pSrb));
  445. }
  446. #endif
  447. // The stream has to be open before we can do anything.
  448. if (pStrmExt == NULL) {
  449. TRACE(TL_STRM_TRACE,("RcvDataPacket: stream not opened for SRB %x. kicking out...\n", pSrb->Command));
  450. pSrb->Status = STATUS_UNSUCCESSFUL;
  451. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  452. StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
  453. return;
  454. }
  455. TRACE(TL_PNP_TRACE,("XXX_DATA(%d, %d);Srb:%x;Flg:%x;FExt:%d:%d\n",
  456. (DWORD) pStrmExt->cntSRBReceived,
  457. (DWORD) pSrb->CommandData.DataBufferArray->PresentationTime.Time/10000,
  458. pSrb,
  459. pSrb->CommandData.DataBufferArray->OptionsFlags,
  460. pSrb->CommandData.DataBufferArray->FrameExtent,
  461. AVCStrmFormatInfoTable[pDevExt->VideoFormatIndex].FrameSize
  462. ));
  463. // If we has asked to stopped, we should not receive data request.
  464. ASSERT(pStrmExt->StreamState != KSSTATE_STOP);
  465. //
  466. // determine the type of packet.
  467. //
  468. pSrb->Status = STATUS_SUCCESS;
  469. switch (pSrb->Command) {
  470. case SRB_WRITE_DATA:
  471. // ********************************
  472. // Take care of some special cases:
  473. // ********************************
  474. // Can signal this when the last is transmitted or sigal it immediately like
  475. // what is done here.
  476. if(pSrb->CommandData.DataBufferArray->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_ENDOFSTREAM) {
  477. // Optional, wait a fix time and can be signalled when the last one has returned.
  478. // And then signal the completion.
  479. TRACE(TL_STRM_WARNING,("RcvDataPacket: EndOfStream is signalled!\n"));
  480. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  481. pSrb->Status = STATUS_SUCCESS;
  482. //
  483. // Send this flag down to AVCStrm.sys so it will wait until
  484. // all attach buffers are completed.
  485. //
  486. } else if (pSrb->CommandData.DataBufferArray->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED) {
  487. TRACE(TL_PNP_WARNING,("RcvDataPacket:KSSTREAM_HEADER_OPTIONSF_TYPECHANGED.\n"));
  488. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  489. // May need to compare the data format; instead of return STATUS_SUCCESS??
  490. pSrb->Status = STATUS_SUCCESS; // May need to check the format when dynamic format change is allowed.
  491. break;
  492. }
  493. case SRB_READ_DATA:
  494. //
  495. // If removed, cancel the request with STATUS_DEVICE_REMOVED.
  496. // (apply to both SRB_READ_DATA and SRB_WRITE_DATA)
  497. //
  498. if(pDevExt->bDevRemoved) {
  499. TRACE(TL_STRM_WARNING,("SRB_READ/WRITE; DevRemoved!\n", pSrb));
  500. pSrb->Status = STATUS_DEVICE_REMOVED;
  501. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  502. break;
  503. }
  504. //
  505. // A true data request must has a MdlAddress unless it is a know
  506. // optional flag.
  507. //
  508. if(pSrb->Irp->MdlAddress == NULL) {
  509. if((pSrb->CommandData.DataBufferArray->OptionsFlags &
  510. (KSSTREAM_HEADER_OPTIONSF_ENDOFSTREAM | KSSTREAM_HEADER_OPTIONSF_TYPECHANGED) )) {
  511. //
  512. // Known optional flags
  513. //
  514. } else {
  515. TRACE(TL_STRM_ERROR,("pSrb:%x, unknown OptionsFlags:%x\n",pSrb, pSrb->CommandData.DataBufferArray->OptionsFlags));
  516. ASSERT(pSrb->Irp->MdlAddress);
  517. break;
  518. //
  519. // We do not know how to handle this option flag so we will quit on this data request.
  520. //
  521. }
  522. }
  523. //
  524. // Serialize with setting state
  525. //
  526. EnterAVCStrm(pStrmExt->hMutexReq);
  527. //
  528. // Get a context to send this request down
  529. //
  530. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  531. pStrmExt->cntSRBReceived++;
  532. if(IsListEmpty(&pStrmExt->DataDetachedListHead)) {
  533. TRACE(TL_STRM_ERROR,("**** DataDetachList is empty! ****\n"));
  534. ASSERT(!IsListEmpty(&pStrmExt->DataDetachedListHead));
  535. //
  536. // Note: The alternative to the failure is to expand the pre-allocated list.
  537. //
  538. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  539. LeaveAVCStrm(pStrmExt->hMutexReq);
  540. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  541. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  542. break;
  543. } else {
  544. pDriverReq = (PDRIVER_REQUEST) RemoveHeadList(&pStrmExt->DataDetachedListHead); pStrmExt->cntDataDetached--;
  545. #if DBG
  546. pDriverReq->cntDataRequestReceived = pStrmExt->cntSRBReceived; // For verification
  547. #endif
  548. InsertTailList(&pStrmExt->DataAttachedListHead, &pDriverReq->ListEntry); pStrmExt->cntDataAttached++;
  549. pAVCStrmReq = &pDriverReq->AVCStrmReq;
  550. pIrpReq = pDriverReq->pIrp;
  551. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  552. }
  553. RtlZeroMemory(pAVCStrmReq, sizeof(AVC_STREAM_REQUEST_BLOCK));
  554. INIT_AVCSTRM_HEADER(pAVCStrmReq, (pSrb->Command == SRB_READ_DATA) ? AVCSTRM_READ : AVCSTRM_WRITE);
  555. pAVCStrmReq->AVCStreamContext = pStrmExt->AVCStreamContext;
  556. // Need these context when this IRP is completed.
  557. pDriverReq->Context1 = (PVOID) pSrb;
  558. pDriverReq->Context2 = (PVOID) pStrmExt;
  559. // We are the clock provide if hMasterClock is not NULL.
  560. pAVCStrmReq->CommandData.BufferStruct.ClockProvider = (pStrmExt->hMasterClock != NULL);
  561. pAVCStrmReq->CommandData.BufferStruct.ClockHandle = pStrmExt->hClock; // Used only if !ClockProvider
  562. pAVCStrmReq->CommandData.BufferStruct.StreamHeader = pSrb->CommandData.DataBufferArray;
  563. //
  564. // This could be a data or just flag that need to be processed.
  565. // Get its system address only if there is an MdlAddress.
  566. //
  567. if(pSrb->Irp->MdlAddress) {
  568. pAVCStrmReq->CommandData.BufferStruct.FrameBuffer =
  569. #ifdef USE_WDM110 // Win2000, XP
  570. MmGetSystemAddressForMdlSafe(pSrb->Irp->MdlAddress, NormalPagePriority);
  571. if(!pAVCStrmReq->CommandData.BufferStruct.FrameBuffer) {
  572. //
  573. // Reclaim the data entry from attach (busy) to detach (free)
  574. //
  575. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  576. RemoveEntryList(&pDriverReq->ListEntry); pStrmExt->cntDataAttached--;
  577. InsertHeadList(&pStrmExt->DataAttachedListHead, &pDriverReq->ListEntry); pStrmExt->cntDataAttached++;
  578. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  579. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  580. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  581. ASSERT(pAVCStrmReq->CommandData.BufferStruct.FrameBuffer);
  582. break;
  583. }
  584. #else // Win9x
  585. MmGetSystemAddressForMdl (pSrb->Irp->MdlAddress);
  586. #endif
  587. }
  588. // This is a Async command
  589. NextIrpStack = IoGetNextIrpStackLocation(pIrpReq);
  590. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  591. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_AVCSTRM_CLASS;
  592. NextIrpStack->Parameters.Others.Argument1 = pAVCStrmReq;
  593. // Not cancellable!
  594. IoSetCancelRoutine(
  595. pIrpReq,
  596. NULL
  597. );
  598. IoSetCompletionRoutine(
  599. pIrpReq,
  600. AVCTapeReqReadDataCR,
  601. pDriverReq,
  602. TRUE, // Success
  603. TRUE, // Error
  604. TRUE // or Cancel
  605. );
  606. pSrb->Status = STATUS_PENDING;
  607. pStrmExt->cntDataSubmitted++;
  608. Status =
  609. IoCallDriver(
  610. pDevExt->pBusDeviceObject,
  611. pIrpReq
  612. );
  613. LeaveAVCStrm(pStrmExt->hMutexReq);
  614. if(Status == STATUS_PENDING) {
  615. // Normal case.
  616. return; // Will complete asychronousely (Success, Error, or Cancel)
  617. } else {
  618. //
  619. // Complete the data request synchronousely (no pending)
  620. //
  621. if(pDriverReq->Context1 == NULL || pDriverReq->Context2 == NULL) {
  622. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("pSrb:%x; SRB_READ_DATA/WRITE IRP completed with Status;%x\n", pSrb, Status));
  623. return;
  624. } else {
  625. TRACE(TL_STRM_WARNING,("AVCSTRM_READ/WRITE: pSrb %x; failed or completed with ST:%x; pAVCStrmReq:%x\n", pSrb, Status, pAVCStrmReq));
  626. ASSERT(FALSE);
  627. // Complete the SRB if not pending
  628. pSrb->Status = pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_UNSUCCESSFUL;
  629. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  630. }
  631. }
  632. break;
  633. default:
  634. //
  635. // invalid / unsupported command. Fail it as such
  636. //
  637. pSrb->Status = STATUS_NOT_SUPPORTED;
  638. break;
  639. }
  640. ASSERT(pSrb->Status != STATUS_PENDING);
  641. // Finally, send the srb back up ...
  642. StreamClassStreamNotification(
  643. StreamRequestComplete,
  644. pSrb->StreamObject,
  645. pSrb );
  646. }
  647. NTSTATUS
  648. DriverEntry(
  649. IN PDRIVER_OBJECT DriverObject,
  650. IN PUNICODE_STRING RegistryPath
  651. )
  652. /*++
  653. Routine Description:
  654. This where life begins for a driver. The stream class takes care
  655. of alot of stuff for us, but we still need to fill in an initialization
  656. structure for the stream class and call it.
  657. Arguments:
  658. Context1 - DriverObject
  659. Context2 - RegistryPath
  660. Return Value:
  661. The function value is the final status from the initialization operation.
  662. --*/
  663. {
  664. HW_INITIALIZATION_DATA HwInitData;
  665. TRACE(TL_PNP_ERROR,("<<<<<<< MSTape.sys: %s; %s; %x %x >>>>>>>>\n",
  666. __DATE__, __TIME__, DriverObject, RegistryPath));
  667. #ifdef TIME_BOMB
  668. if (HasEvaluationTimeExpired()) {
  669. TRACE(TL_PNP_ERROR, ("Evaluation period expired!") );
  670. return STATUS_EVALUATION_EXPIRATION;
  671. }
  672. #endif
  673. TRACE(TL_PNP_ERROR,("===================================================================\n"));
  674. TRACE(TL_PNP_ERROR,("TapeTraceMask=0x%.8x = 0x[7][6][5][4][3][2][1][0] where\n", TapeTraceMask));
  675. TRACE(TL_PNP_ERROR,("\n"));
  676. TRACE(TL_PNP_ERROR,("PNP: [0]:Loading, power state, surprise removal, device SRB..etc.\n"));
  677. TRACE(TL_PNP_ERROR,("61883: [1]:Plugs, connection, CMP info and call to 61883.\n"));
  678. TRACE(TL_PNP_ERROR,("CIP: [2]:Isoch data transfer.\n"));
  679. TRACE(TL_PNP_ERROR,("AVC: [3]:AVC commands.\n"));
  680. TRACE(TL_PNP_ERROR,("Stream:[4]:Data intersec, open/close,.state, property etc.\n"));
  681. TRACE(TL_PNP_ERROR,("Clock: [5]:Clock (event and signal)etc.\n"));
  682. TRACE(TL_PNP_ERROR,("===================================================================\n"));
  683. TRACE(TL_PNP_ERROR,("dd mstape!TapeTraceMask L1\n"));
  684. TRACE(TL_PNP_ERROR,("e mstape!TapeTraceMask <new value> <enter>\n"));
  685. TRACE(TL_PNP_ERROR,("<for each nibble: ERROR:8, WARNING:4, TRACE:2, INFO:1, MASK:f>\n"));
  686. TRACE(TL_PNP_ERROR,("===================================================================\n\n"));
  687. //
  688. // Fill in the HwInitData structure
  689. //
  690. RtlZeroMemory( &HwInitData, sizeof(HW_INITIALIZATION_DATA) );
  691. HwInitData.HwInitializationDataSize = sizeof(HwInitData);
  692. HwInitData.HwInterrupt = NULL;
  693. HwInitData.HwReceivePacket = DVRcvStreamDevicePacket;
  694. HwInitData.HwRequestTimeoutHandler = DVTimeoutHandler;
  695. HwInitData.HwCancelPacket = DVCRCancelOnePacket;
  696. HwInitData.DeviceExtensionSize = sizeof(DVCR_EXTENSION) +
  697. sizeof(AVC_DEV_PLUGS) * 2;
  698. //
  699. // The ULONG is used in SRB_WRITE_DATA to keep track of
  700. // number of times the same SRB was attached for transmit.
  701. //
  702. // Data SRB: ULONG is used (< sizeof(AV_61883_REQ)
  703. // DeviceControl or StreamControl Srb: AV_61883_REQ is used.
  704. HwInitData.PerRequestExtensionSize = sizeof(AV_61883_REQUEST); // Per SRB
  705. HwInitData.PerStreamExtensionSize = sizeof(STREAMEX); // Per pin/stream
  706. HwInitData.FilterInstanceExtensionSize = 0;
  707. HwInitData.BusMasterDMA = FALSE;
  708. HwInitData.Dma24BitAddresses = FALSE;
  709. HwInitData.BufferAlignment = sizeof(ULONG) - 1;
  710. HwInitData.TurnOffSynchronization = TRUE;
  711. HwInitData.DmaBufferSize = 0;
  712. return StreamClassRegisterAdapter(DriverObject, RegistryPath, &HwInitData);
  713. }