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.

609 lines
13 KiB

  1. //***************************************************************************
  2. // Closed Caption process
  3. //
  4. //***************************************************************************
  5. #include "common.h"
  6. #include "que.h"
  7. #include "regs.h"
  8. void USCC_on( PHW_DEVICE_EXTENSION pHwDevExt );
  9. void USCC_off( PHW_DEVICE_EXTENSION pHwDevExt );
  10. void USCC_get( PHW_DEVICE_EXTENSION pHwDevExt );
  11. void USCC_put( PHW_DEVICE_EXTENSION pHwDevExt );
  12. static BOOL USCC_Wait( PHW_DEVICE_EXTENSION pHwDevExt );
  13. //--- for Debug
  14. //static void USCC_Test( void );
  15. //
  16. //--- End.
  17. void USCC_discont( PHW_DEVICE_EXTENSION pHwDevExt );
  18. extern ULONGLONG ConvertPTStoStrm(ULONG pts);
  19. #define USCC_BuffSize 0x200
  20. static UCHAR USCCF[USCC_BuffSize];
  21. static UCHAR USCC1[USCC_BuffSize];
  22. static UCHAR USCC2[USCC_BuffSize];
  23. WORD wUsccSize = 0;
  24. WORD wUsccWptr = 0;
  25. WORD wUsccRptr = 0;
  26. void USCC_on( PHW_DEVICE_EXTENSION pHwDevExt )
  27. {
  28. // User Data Interrupt Enable
  29. pHwDevExt->VDec.VIDEO_UDSC_INT_ON();
  30. // Set Read Mode (from GOP Layer, channel 0)
  31. WRITE_PORT_UCHAR( pHwDevExt->ioBaseLocal + TC812_DATA1, 0x08 );
  32. WRITE_PORT_UCHAR( pHwDevExt->ioBaseLocal + TC812_CMDR1, V_SET_UDATA );
  33. pHwDevExt->VPro.VPRO_CC_ON();
  34. pHwDevExt->CPgd.CPGD_CC_ON();
  35. wUsccSize = 0;
  36. wUsccRptr = 0;
  37. wUsccWptr = 0;
  38. //--- for Debug
  39. // USCC_Test();
  40. //--- End.
  41. }
  42. void USCC_off( PHW_DEVICE_EXTENSION pHwDevExt )
  43. {
  44. pHwDevExt->VDec.VIDEO_UDSC_INT_OFF();
  45. pHwDevExt->VPro.VPRO_CC_OFF();
  46. pHwDevExt->CPgd.CPGD_CC_OFF();
  47. }
  48. void USCC_get( PHW_DEVICE_EXTENSION pHwDevExt )
  49. {
  50. static UCHAR ccbuff[USCC_BuffSize];
  51. LONG cp;
  52. UCHAR channels;
  53. UCHAR cnumber;
  54. UCHAR fieldFlg;
  55. UCHAR fieldNum;
  56. UCHAR field;
  57. UCHAR marker;
  58. UCHAR fswitch;
  59. UCHAR cc1, cc2;
  60. UCHAR uscc_or, uscc_and;
  61. LONG i;
  62. cp = 0;
  63. uscc_or = 0x00;
  64. uscc_and = 0xFF;
  65. // Sometimes bad Data Come, chip bug ?
  66. do {
  67. // Check ready to read next CC data
  68. if( USCC_Wait( pHwDevExt )==FALSE ) {
  69. }
  70. channels = READ_PORT_UCHAR( pHwDevExt->ioBaseLocal + TC812_UDAT );
  71. // DebugPrint(( DebugLevelTrace, "TOSDVD: CC channels = 0x%x\r\n", channels ) );
  72. } while( channels==0x43 );
  73. ccbuff[cp++] = 0x43; // 0x43 ?
  74. ccbuff[cp++] = 0x43; // 0x43 ?
  75. ccbuff[cp++] = channels;
  76. // Check ready to read next CC data
  77. if( USCC_Wait( pHwDevExt )==FALSE ) {
  78. }
  79. cnumber = READ_PORT_UCHAR( pHwDevExt->ioBaseLocal + TC812_UDAT );
  80. // DebugPrint(( DebugLevelTrace, "TOSDVD: CC cnumber = 0x%x\r\n", cnumber ) );
  81. ccbuff[cp++] = (UCHAR)(cnumber | 0xF8);
  82. // Check ready to read next CC data
  83. if( USCC_Wait( pHwDevExt )==FALSE ) {
  84. }
  85. fieldFlg = fieldNum = field = READ_PORT_UCHAR( pHwDevExt->ioBaseLocal + TC812_UDAT );
  86. // DebugPrint(( DebugLevelTrace, "TOSDVD: CC field = 0x%x\r\n", field ) );
  87. ccbuff[cp++] = field;
  88. fieldFlg &= 0x80;
  89. fieldNum &= 0x3F;
  90. for( i=0; i<fieldNum; i++ ) {
  91. // Check ready to read next CC data
  92. if( USCC_Wait( pHwDevExt )==FALSE ) {
  93. }
  94. marker = fswitch = READ_PORT_UCHAR( pHwDevExt->ioBaseLocal + TC812_UDAT );
  95. // DebugPrint(( DebugLevelTrace, "TOSDVD: CC mk & sw = 0x%x", marker ) );
  96. ccbuff[cp++] = marker;
  97. marker &= 0xFE;
  98. if( marker != 0xFE ) {
  99. // DebugPrint(( DebugLevelTrace, "TOSDVD: CC marker is Bad = 0x%x\r\n", marker ) );
  100. }
  101. fswitch &= 0x01;
  102. // Check ready to read next CC data
  103. if( USCC_Wait( pHwDevExt )==FALSE ) {
  104. }
  105. cc1 = READ_PORT_UCHAR( pHwDevExt->ioBaseLocal + TC812_UDAT );
  106. ccbuff[cp++] = cc1;
  107. // Check ready to read next CC data
  108. if( USCC_Wait( pHwDevExt )==FALSE ) {
  109. }
  110. cc2 = READ_PORT_UCHAR( pHwDevExt->ioBaseLocal + TC812_UDAT );
  111. ccbuff[cp++] = cc2;
  112. if( fswitch==0x01 ) {
  113. USCCF[wUsccWptr] = fieldFlg;
  114. USCC1[wUsccWptr] = cc1;
  115. USCC2[wUsccWptr] = cc2;
  116. wUsccWptr++;
  117. if( wUsccWptr>=USCC_BuffSize )
  118. wUsccWptr = 0;
  119. wUsccSize++;
  120. }
  121. // DebugPrint(( DebugLevelTrace, " 0x%02x 0x%02x", cc1, cc2 ) );
  122. if( fswitch==0x01 ) {
  123. uscc_or |= (cc1 | cc2);
  124. uscc_and &= (cc1 & cc2);
  125. }
  126. // DebugPrint(( DebugLevelTrace, " \r\n" ) );
  127. }
  128. // DebugPrint(( DebugLevelTrace, " \r\n" ) );
  129. do {
  130. if( (READ_PORT_UCHAR( pHwDevExt->ioBaseLocal + TC812_STT1 ) & 0x08)==0x00 )
  131. break;
  132. // Check ready to read next CC data
  133. if( USCC_Wait( pHwDevExt )==FALSE ) {
  134. }
  135. READ_PORT_UCHAR( pHwDevExt->ioBaseLocal + TC812_UDAT );
  136. } while( 1 );
  137. //------------------------------------------------
  138. PHW_STREAM_REQUEST_BLOCK pSrb;
  139. PUCHAR pDest;
  140. if (pHwDevExt->bStopCC)
  141. {
  142. return;
  143. }
  144. pSrb = pHwDevExt->CCQue.get();
  145. // DebugPrint(( DebugLevelTrace, "TOSDVD: get queue CC pSrb = 0x%x\r\n", pSrb ));
  146. cp = 0;
  147. if( pSrb != NULL ) {
  148. if (pSrb->CommandData.DataBufferArray->FrameExtent < sizeof(KSGOP_USERDATA))
  149. {
  150. TRAP
  151. pSrb->Status = STATUS_INVALID_BUFFER_SIZE;
  152. pSrb->ActualBytesTransferred = 0;
  153. StreamClassStreamNotification(StreamRequestComplete,
  154. pSrb->StreamObject,
  155. pSrb);
  156. return;
  157. }
  158. pDest = (PUCHAR)(pSrb->CommandData.DataBufferArray->Data);
  159. *(PULONG)pDest = 0xB2010000;
  160. pDest += 4;
  161. *pDest++ = ccbuff[cp++];
  162. *pDest++ = ccbuff[cp++];
  163. *pDest++ = ccbuff[cp++];
  164. *pDest++ = ccbuff[cp++];
  165. field = *pDest++= ccbuff[cp++];
  166. DebugPrint(( DebugLevelTrace, "TOSDVD:CC field %d\r\n", field ));
  167. field &= 0x3F;
  168. if (pSrb->CommandData.DataBufferArray->FrameExtent <
  169. (field -1) * 3 + sizeof (KSGOP_USERDATA))
  170. {
  171. TRAP
  172. pSrb->Status = STATUS_INVALID_BUFFER_SIZE;
  173. pSrb->ActualBytesTransferred = 0;
  174. StreamClassStreamNotification(StreamRequestComplete,
  175. pSrb->StreamObject,
  176. pSrb);
  177. return;
  178. }
  179. pSrb->CommandData.DataBufferArray->DataUsed =
  180. pSrb->ActualBytesTransferred =
  181. (field -1 ) * 3 + sizeof (KSGOP_USERDATA);
  182. //
  183. // copy the bits
  184. //
  185. for( ;field; field-- ) {
  186. *pDest++ = ccbuff[cp++];
  187. *pDest++ = ccbuff[cp++];
  188. *pDest++ = ccbuff[cp++];
  189. }
  190. pSrb->Status = STATUS_SUCCESS;
  191. PKSSTREAM_HEADER pPacket;
  192. pPacket = pSrb->CommandData.DataBufferArray;
  193. pPacket->OptionsFlags = KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  194. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
  195. pSrb->NumberOfBuffers = 1;
  196. DWORD dwSTC = pHwDevExt->VDec.VIDEO_GET_STCA();
  197. pPacket->PresentationTime.Time = ConvertPTStoStrm( dwSTC );
  198. pPacket->Duration = 1000;
  199. DebugPrint(( DebugLevelTrace, "TOSDVD:CC Notify 0x%x(0x%x(90kHz))\r\n", (DWORD)(pPacket->PresentationTime.Time), dwSTC ));
  200. StreamClassStreamNotification(StreamRequestComplete,
  201. pSrb->StreamObject,
  202. pSrb);
  203. return;
  204. }
  205. else {
  206. // DebugPrint(( DebugLevelTrace, "TOSDVD:CCQue.get() == NULL\r\n" ));
  207. // TRAP
  208. }
  209. //------------------------------------------------
  210. }
  211. void USCC_put( PHW_DEVICE_EXTENSION pHwDevExt )
  212. {
  213. UCHAR var;
  214. static LONG debCounter = 0;
  215. // Using later VPRO, possibly you have to add codes ( ex. subp command register )
  216. if( wUsccSize==0 ) {
  217. //--- for Debug
  218. // USCC_Test();
  219. //--- End.
  220. return;
  221. }
  222. // debCounter++;
  223. // if( debCounter==100 ) {
  224. // debCounter = 0;
  225. // DebugPrint(( DebugLevelTrace, "TOSDVD: USCC_put\r\n" ) );
  226. // }
  227. // Top field ; output to register CC1
  228. if( USCCF[wUsccRptr] == 0x80 ) {
  229. var = USCC1[wUsccRptr];
  230. // DebugPrint(( DebugLevelTrace, "TOSDVD: TOP USCC1 = %x\r\n", var ) );
  231. WRITE_PORT_UCHAR( pHwDevExt->ioBaseLocal + SUBP_CC1, var );
  232. var = USCC2[wUsccRptr];
  233. // DebugPrint(( DebugLevelTrace, "TOSDVD: TOP USCC2 = %x\r\n", var ) );
  234. WRITE_PORT_UCHAR( pHwDevExt->ioBaseLocal + SUBP_CC1, var );
  235. }
  236. // Bottom field ; output to register CC2
  237. else {
  238. var = USCC1[wUsccRptr];
  239. // DebugPrint(( DebugLevelTrace, "TOSDVD: BTM USCC1 = %x\r\n", var ) );
  240. WRITE_PORT_UCHAR( pHwDevExt->ioBaseLocal + SUBP_CC2, var );
  241. var = USCC2[wUsccRptr];
  242. // DebugPrint(( DebugLevelTrace, "TOSDVD: BTM USCC2 = %x\r\n", var ) );
  243. WRITE_PORT_UCHAR( pHwDevExt->ioBaseLocal + SUBP_CC2, var );
  244. wUsccRptr++;
  245. if( wUsccRptr>=USCC_BuffSize )
  246. wUsccRptr = 0;
  247. wUsccSize--;
  248. }
  249. #if 0
  250. WRITE_PORT_UCHAR( pHwDevExt->ioBaseLocal + SUBP_CC1, 0x2C );
  251. WRITE_PORT_UCHAR( pHwDevExt->ioBaseLocal + SUBP_CC1, 0x94 );
  252. #endif
  253. }
  254. static BOOL USCC_Wait( PHW_DEVICE_EXTENSION pHwDevExt )
  255. {
  256. UCHAR val;
  257. LONG i;
  258. for( i=0; i<10; i++ ) {
  259. val = READ_PORT_UCHAR( pHwDevExt->ioBaseLocal + TC812_STT1 );
  260. if( val & 0x08 )
  261. return( TRUE );
  262. }
  263. return( FALSE );
  264. }
  265. //--- for Debug
  266. //static void USCC_Test( void )
  267. //{
  268. // wUsccSize = 0;
  269. // wUsccWptr = 0;
  270. // wUsccRptr = 0;
  271. //
  272. // USCC1[wUsccWptr] = 0x94;
  273. // USCC2[wUsccWptr] = 0x20;
  274. // wUsccWptr++;
  275. // wUsccSize++;
  276. //
  277. // USCC1[wUsccWptr] = 0x94;
  278. // USCC2[wUsccWptr] = 0x20;
  279. // wUsccWptr++;
  280. // wUsccSize++;
  281. //
  282. // USCC1[wUsccWptr] = 0x94;
  283. // USCC2[wUsccWptr] = 0x54;
  284. // wUsccWptr++;
  285. // wUsccSize++;
  286. //
  287. // USCC1[wUsccWptr] = 0x94;
  288. // USCC2[wUsccWptr] = 0x54;
  289. // wUsccWptr++;
  290. // wUsccSize++;
  291. //
  292. // USCC1[wUsccWptr] = 0x94;
  293. // USCC2[wUsccWptr] = 0x20;
  294. // wUsccWptr++;
  295. // wUsccSize++;
  296. //
  297. // USCC1[wUsccWptr] = 0x94;
  298. // USCC2[wUsccWptr] = 0x20;
  299. // wUsccWptr++;
  300. // wUsccSize++;
  301. //
  302. // wUsccWptr++;
  303. //
  304. // USCC1[wUsccWptr] = 0x5B;
  305. // USCC2[wUsccWptr] = 0xD0;
  306. // wUsccWptr++;
  307. // wUsccSize++;
  308. //
  309. // wUsccWptr++;
  310. //
  311. // USCC1[wUsccWptr] = 0x4F;
  312. // USCC2[wUsccWptr] = 0x4C;
  313. // wUsccWptr++;
  314. // wUsccSize++;
  315. //
  316. // USCC1[wUsccWptr] = 0x49;
  317. // USCC2[wUsccWptr] = 0x43;
  318. // wUsccWptr++;
  319. // wUsccSize++;
  320. //
  321. // USCC1[wUsccWptr] = 0x45;
  322. // USCC2[wUsccWptr] = 0x20;
  323. // wUsccWptr++;
  324. // wUsccSize++;
  325. //
  326. // USCC1[wUsccWptr] = 0x4F;
  327. // USCC2[wUsccWptr] = 0x46;
  328. // wUsccWptr++;
  329. // wUsccSize++;
  330. //
  331. // USCC1[wUsccWptr] = 0x46;
  332. // USCC2[wUsccWptr] = 0x49;
  333. // wUsccWptr++;
  334. // wUsccSize++;
  335. //
  336. // USCC1[wUsccWptr] = 0x43;
  337. // USCC2[wUsccWptr] = 0x45;
  338. // wUsccWptr++;
  339. // wUsccSize++;
  340. //
  341. // USCC1[wUsccWptr] = 0x52;
  342. // USCC2[wUsccWptr] = 0x5D;
  343. // wUsccWptr++;
  344. // wUsccSize++;
  345. //
  346. // USCC1[wUsccWptr] = 0x97;
  347. // USCC2[wUsccWptr] = 0x76;
  348. // wUsccWptr++;
  349. // wUsccSize++;
  350. //
  351. // USCC1[wUsccWptr] = 0x94;
  352. // USCC2[wUsccWptr] = 0x76;
  353. // wUsccWptr++;
  354. // wUsccSize++;
  355. //
  356. // USCC1[wUsccWptr] = 0x94;
  357. // USCC2[wUsccWptr] = 0x76;
  358. // wUsccWptr++;
  359. // wUsccSize++;
  360. //
  361. // USCC1[wUsccWptr] = 0xC2;
  362. // USCC2[wUsccWptr] = 0xC1;
  363. // wUsccWptr++;
  364. // wUsccSize++;
  365. //
  366. // USCC1[wUsccWptr] = 0x43;
  367. // USCC2[wUsccWptr] = 0xCB;
  368. // wUsccWptr++;
  369. // wUsccSize++;
  370. //
  371. // USCC1[wUsccWptr] = 0xD0;
  372. // USCC2[wUsccWptr] = 0xA1;
  373. // wUsccWptr++;
  374. // wUsccSize++;
  375. //
  376. // USCC1[wUsccWptr] = 0x94;
  377. // USCC2[wUsccWptr] = 0x2C;
  378. // wUsccWptr++;
  379. // wUsccSize++;
  380. //
  381. // USCC1[wUsccWptr] = 0x94;
  382. // USCC2[wUsccWptr] = 0x2C;
  383. // wUsccWptr++;
  384. // wUsccSize++;
  385. //
  386. // USCC1[wUsccWptr] = 0x94;
  387. // USCC2[wUsccWptr] = 0x2F;
  388. // wUsccWptr++;
  389. // wUsccSize++;
  390. //
  391. // USCC1[wUsccWptr] = 0x94;
  392. // USCC2[wUsccWptr] = 0x2F;
  393. // wUsccWptr++;
  394. // wUsccSize++;
  395. //
  396. //}
  397. //--- End.
  398. void USCC_discont( PHW_DEVICE_EXTENSION pHwDevExt )
  399. {
  400. PHW_STREAM_REQUEST_BLOCK pSrb;
  401. PKSSTREAM_HEADER pPacket;
  402. DebugPrint(( DebugLevelTrace, "TOSDVD:USCC_discont()\r\n" ));
  403. if( pHwDevExt->pstroCC && ((PSTREAMEX)(pHwDevExt->pstroCC->HwStreamExtension))->state == KSSTATE_RUN ) {
  404. pSrb = pHwDevExt->CCQue.get();
  405. if( pSrb ) {
  406. //
  407. // we have a request, send a discontinuity
  408. //
  409. // DebugPrint(( DebugLevelTrace, "TOSDVD: get queue CC pSrb = 0x%x\r\n", pSrb ));
  410. pSrb->Status = STATUS_SUCCESS;
  411. pPacket = pSrb->CommandData.DataBufferArray;
  412. pPacket->OptionsFlags = KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY |
  413. KSSTREAM_HEADER_OPTIONSF_TIMEVALID | KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
  414. pPacket->DataUsed = 0;
  415. pSrb->NumberOfBuffers = 0;
  416. // BUG!
  417. // it must set PTS of packet ?
  418. pPacket->PresentationTime.Time = ConvertPTStoStrm( pHwDevExt->VDec.VIDEO_GET_STCA() );
  419. pPacket->Duration = 1000;
  420. DebugPrint(( DebugLevelTrace, "TOSDVD: CC Notify %d\r\n", (DWORD)pPacket->PresentationTime.Time ));
  421. StreamClassStreamNotification(StreamRequestComplete,
  422. pSrb->StreamObject,
  423. pSrb);
  424. }
  425. else
  426. {
  427. TRAP;
  428. }
  429. }
  430. else {
  431. DebugPrint(( DebugLevelTrace, "TOSDVD: CC stream not RUN\r\n" ));
  432. }
  433. }
  434. // CCQueue
  435. void CCQueue::init( void )
  436. {
  437. count = 0;
  438. top = bottom = NULL;
  439. }
  440. void CCQueue::put( PHW_STREAM_REQUEST_BLOCK pSrb )
  441. {
  442. pSrb->NextSRB = NULL;
  443. if ( top == NULL ) {
  444. top = bottom = pSrb;
  445. count++;
  446. return;
  447. }
  448. bottom->NextSRB = pSrb;
  449. bottom = pSrb;
  450. count++;
  451. return;
  452. }
  453. PHW_STREAM_REQUEST_BLOCK CCQueue::get( void )
  454. {
  455. PHW_STREAM_REQUEST_BLOCK srb;
  456. if ( top == NULL )
  457. return NULL;
  458. srb = top;
  459. top = top->NextSRB;
  460. count--;
  461. if ( count == 0 )
  462. top = bottom = NULL;
  463. return srb;
  464. }
  465. void CCQueue::remove( PHW_STREAM_REQUEST_BLOCK pSrb )
  466. {
  467. if ( top == NULL )
  468. return;
  469. if( top == pSrb ) {
  470. top = top->NextSRB;
  471. count--;
  472. if ( count == 0 )
  473. top = bottom = NULL;
  474. DebugPrint(( DebugLevelTrace, "TOSDVD:CCQueue::remove srb = 0x%x\r\n", pSrb ));
  475. return;
  476. }
  477. PHW_STREAM_REQUEST_BLOCK srbPrev;
  478. PHW_STREAM_REQUEST_BLOCK srb;
  479. srbPrev = top;
  480. srb = srbPrev->NextSRB;
  481. while ( srb != NULL ) {
  482. if( srb == pSrb ) {
  483. srbPrev->NextSRB = srb->NextSRB;
  484. if( srbPrev->NextSRB == bottom )
  485. bottom = srbPrev;
  486. count--;
  487. DebugPrint(( DebugLevelTrace, "TOSDVD:CCQueue::remove srb = 0x%x\r\n", pSrb ));
  488. break;
  489. }
  490. srbPrev = srb;
  491. srb = srbPrev->NextSRB;
  492. }
  493. }
  494. BOOL CCQueue::isEmpty( void )
  495. {
  496. if( top == NULL )
  497. return TRUE;
  498. else
  499. return FALSE;
  500. }
  501.