📄 tdm.c
字号:
* * This is an escape clause. */ /* * CDDA's copy_cdda is at the same location as STOP_STATE, * but we'll not get TDM interrupt for CDDA. However, we do * have to check XPORT_active since we may have stopped, then * we get an extra TDM interrupt. */ stopit = XPORT_active; } if (!TDM_expectBreak) { /* * If disk is seriously scratched, currCDtime after a jump is * not reliable. We shouldn't turn off CD accidentally by * that value! We'll let the next sector to make the judgement. */ if ((currCDtime >= endCDtime) || (currCDtime > second_endCDtime)) { stopit = 1; } } quit_tdm: if (stopit) { TDM_stop(TDM_off); }#endif TDM_expectBreak = 0; /* Next currCDtime should be sequential */ /* Return if there is nothing left in the FIFO */ if (!argcnt || !XPORT_active) return;#ifdef XPORT11 /* * For 1.1 players, if the current sector is INFO.VCD, then the * transport microcode will send us: * 1) 2B of VCD version number * 2) 4B of PSD size * 3) 2B of maximum segment number * 4) 2B for the first 2 segment play item bytes */ if (currCDtime == 0x000400) { if (argcnt == 5) { /* If number of item is not right, don't even process it! */ unsigned int szPsd; unsigned short szSeg; unsigned short dataPSD; unsigned char seg1; vcdVersion = *pfifo++; vcdVersion += 0x3030; /* From BCD to character */ szPsd = ((unsigned int) (*pfifo++)) << 16; szPsd |= ((unsigned int) (*pfifo++)); szSeg = *pfifo++; dataPSD = *pfifo++; seg1 = dataPSD >> 8; if ((vcdVersion == 0x3131) || (szPsd == 0)) { /* If PSD size is 0, then then is 1.1 disc */ vcdVersion = 0x3131; if (vcx_digest || skipTk1) TDM_send_skip = 1; } foundVCDversion = 1; /* Found a new VCD version */ tmp = 0x1e1; if (szSeg) { /* * If there are segments, we'll look at bits [4:2] by * masking other bits off. If the first segment play item * contents byte is 0x8 or 0x18, then we have high * resolution still (E2). Otherwise, assume low resolution * still (E1) */ if ((seg1 == (unsigned char) 0x8) || (seg1 == (unsigned char) 0x18)) tmp = 0x1e2; } /* Reload PID to reflect E1/E2 requirement */ XPORT_loadstill(tmp); #if (P1O || P2O || P3O || P4O) keepStillType = tmp & 0xff;#endif } return; } /* If we get here, then we have file number! */ filenumber = *pfifo++; argcnt--;#endif subheader = *pfifo++; argcnt--; /* * If there is no packid, then we don't look at subheader info. * In addition, if there is only 1 entry left, then it is CD * time of the next sector. Don't read it!! */ if (argcnt < 2) {#ifdef XPORT11 /* * When using XPORT11, we need to look at the filenumber here * because sometimes we are not getting 1Ex/1C0 yet we still * need to find the track number. */ if ((filenumber & 0xff00) == 0x200) { /* Mode byte has to be 2; otherwise, we ignore filenumber */ TDM_tracknumber = filenumber & 0xff; if (TDM_most_recent_video & 0xf) { /* * We were playing still pictures. If we believe that * we have finished all the data, then skip to the next * track. */ if (skipTk1) { register unsigned int codeinfo = subheader & 0xff; if ((codeinfo != 0) && /* Empty */ (codeinfo != 0xf) && /* E0 */ (codeinfo != 0x1f) && /* E1/padding */ (codeinfo != 0x3f) && /* E2 */ (codeinfo != 0x7f)) { /* Audio */ TDM_send_skip = !TDM_skip_sent; } } } }#endif return; } tmp = subheader & 0x4eff; if ((tmp != 0x420f) && (tmp != 0x447f)) { /* * If subheader looks suspecious, then clear trigger bit and EOF. * This prevents false autopause. * * 620F is the usual submode/coding_info for video * 647f is the usual submode/coding_info for audio */ subheader &= (~(CDSUBMODE_T | CDSUBMODE_EOF)); } packid = *pfifo++; error_recovery: argcnt --; if ((packid & 0xff00) == 0) { /* This is NOT pack ID!! To be on the safe side, just return */ return; }#if (XPORT11 || XPORT20) tmp = packid & 0xfff0; if ((tmp == 0x1c0) || (tmp == 0x1e0)) {#ifdef DSC_ENABLE_C2PO if (C2PO_interrupt) { /* * If we have found a C2PO error since the last TDM interrupt, * then make a note if the data is audio so we can flush * ABV later. */ C2PO_audio_error = (tmp == 0x1c0); if (tmp == 0x1e0) C2PO_video_error++; }#endif /* * We only process subheader if packid checked OK (i.e. subheader * must be right) */#ifdef WATCHDOG if (XPORT_start) { /* * When we just start, there is a short period of time that * data starts to come in, but no huffman has completed. * If timer hit, the current longjmp algorithm will yank * us out. This is dangeous because we will miss the first * still picture. So I fake VBV_huffman_xfer_count to prevent * this long jump. */ VBV_ABV_xport_xfer_count = VBV_ABV_huffman_xfer_count = 1; XPORT_start = 0; }#endif#ifdef PLAY20 /* * If XPORT sees 000001b7, it'll do a CAM look up. Here, we check * the last matched CAM entry, if it is XPORT_PID_B7, then we know * that a 1b7 is found! */ if ((mvd[xport_read_cam_channel] & 0x1f) == XPORT_PID_B7) end_of_sequence = currCDtime; if (subheader & CDSUBMODE_EOR) { if ((tmp == 0x1e0) && ((packid & 0xf) != 0)) { end_of_still = 2; } } /* * After seeing trigger bit, we always get one more video * sector before stopping so hopefully all the data we need * has been flushed out of various FIFO's. */#ifndef CUST3 if ((tmp == 0x1e0) && TDM_trigger) {#ifndef DVD_VCD TDM_stop(1); /* Stop taking in data. Save * * currCDtime+1 in stopCDtime */#endif TDM_stop_time = glbTimer; TDM_trigger = 3; /* Inform decoder that all the * * data is in. */ }#endif /* * Usually when CDSUBMODE_T appears, it appears in consecutive CD * sectors. Therefore, we need to set another flag such that once * we set the "trigger" bit, we'll not set it again within these * consecutive sectors. In other words, we'll only stop once for * a consecutive bunch of CDSUBMODE_T. */ if (set_trigger && PBC_on #ifdef CUST4 /* CUST4 has some modes that shouldn't have auto-pause enabled */ && !PLAY_no_autopause#endif ) { if (subheader & CDSUBMODE_T) { TDM_trigger = 4; /* Will be cleared when handled */ set_trigger = 0; /* Don't set trigger again til * * we are done with the * * consecutive CDSUBMODE_T's */ trigger_time = glbTimer + FIVE_SECOND; } } else if (glbTimer > trigger_time) set_trigger = 1; /* Ignore other triggers for 5 seconds */ /* * Save the last VBV_wrptr before trigger bit so we know when * to stop decoding. */ if ((tmp == 0x1e0) && !TDM_trigger) VBV_trigger = VBV_wrptr;#endif#if (P1O || P2O || P3O || P4O) TDM_tracknumber = filenumber & 0xff; /* Assign file number */ /* * Record the last video type, so we can compare it with * keepStillType. */ if (tmp == 0x1e0) TDM_most_recent_video = packid & 0xff; if (vcx_digest) { if (TDM_most_recent_video & 0xf) { /* * No still picture inside digest. */ TDM_send_skip = !TDM_skip_sent; } } if (subheader & CDSUBMODE_EOR) { if ((TDM_most_recent_video == keepStillType) && !vcx_digest) { /* * For 3208/3210, vcx_user_video_stream is set to * E2 during digest. However, we don't want to pause * and see 'SELECT' inside INTRO screen. */ if ((tmp == 0x1e0) && ((packid & 0xf) != 0)) { end_of_still = 2; } osdSelect = pbcON; /* Show "select" + pause */ } else /* For E0, this means end of track in some disc */ end_of_track++; } else if (subheader & CDSUBMODE_EOF) end_of_track++;#endif }#endif /* XPORT11 || XPORT20 */ /* * argcnt can only be 1 (no PTS) or 3 (with PTS). No other value * is expected. */ if (argcnt == 3) TDM_getPTS(pfifo, packid);}/* * Get Stream ID, PTS from the RISC fifo. * * Stream ID is always present (otherwise, this routine shouldn't be * called.) * * PTS is optionsl, so there are 3 possibilities: * 1) Neither PTS nor DTS: * <junk:0xf> * 2) PTS only: * <junk:PTS[4]> <PTS[3]:PTS[2]> <PTS[1]:PTS[0]> * 3) PTS + DTS, but XPORT sends in PTS only: * <junk:PTS[4]> <PTS[3]:PTS[2]> <PTS[1]:PTS[0]> * Only case 2 and 3 will call this routine. * * Input: * pfifo: Pointer to the FIFO array * packid: Pack ID * * Return: * None. */PRIVATE void TDM_getPTS(pfifo, packid)unsigned short *pfifo;unsigned short packid;{ unsigned short d1, d2, d3; unsigned int pts; static unsigned last_pts = 0; /* PTS or PTS portion of PTS/DTS */ d1 = *pfifo++; d2 = *pfifo++ & 0xfffe; d3 = *pfifo++; /* Drop 1 least significant bits so our clock is 45000 Hz */ pts = (d1 & 0xe) << 28; pts |= (d2 << 13); pts |= (d3 >> 2); /* Drop 1 bit !! */ if (pts != last_pts) { last_pts = pts; /* We only care about e0 and c0. */ if (packid == 0x1e0) { PTS_vid = pts; } else if (packid == 0x1c0) { PTS_aud = pts; } else return; /* When the type of PTS change we take notice */ if (packid != PTS_last) { PTS_xsit++; PTS_last = packid; } }}#ifdef CUST4/* get_a_byte() and put_a_dword() needs to be in cachable region to * generate fast enough clock. */void get_a_byte(unsigned int *dataptr) { int i; volatile unsigned int* ptr = (int *) 0x1c060000; /* ROM address */#ifdef CUST4_NEW_BOARD volatile unsigned int* ptr1 = (int *) 0x14000000; /* For CS1 enable */ for (i = 0; i < BYTE_SIZE; i++) { (void) *ptr1; *dataptr <<= 1; asm("nop"); *dataptr |= READ_HOST_DATA; /* read a bit..MSB first */ (void) *ptr; (void) *ptr; (void) *ptr; }#else /* Old Board */ for (i = 0; i < BYTE_SIZE; i++) { LOWER_XMT_CLK; *dataptr <<= 1; (void) *ptr; /* 360nsec per read from ROM */ (void) *ptr; (void) *ptr; RAISE_XMT_CLK; *dataptr |= READ_HOST_DATA; /* read a bit..MSB first */ (void) *ptr; (void) *ptr; (void) *ptr; }#endif /* CUST4_NEW_BOARD */}void put_a_dword(unsigned data){ int i,j; volatile unsigned int* ptr = (int *) 0x1c060000; #ifdef CUST4_NEW_BOARD volatile unsigned int* ptr1 = (int *) 0x14000000; /* For CS1 enable */ for (i = 0; i < COMMAND_SIZE; i++) { if (data & 0x80000000) { /* need to send MSB first */ WRITE_HI_TO_HOST; } else { WRITE_LOW_TO_HOST; } (void) *ptr1; data <<= 1; (void) *ptr; (void) *ptr; (void) *ptr; }#else /* Old Board */ for (i = 0; i < COMMAND_SIZE; i++) { LOWER_XMT_CLK; if (data & 0x80000000) { /* need to send MSB first */ WRITE_HI_TO_HOST; } else { WRITE_LOW_TO_HOST; } (void) *ptr; /* 360nsec per read from ROM */ (void) *ptr; RAISE_XMT_CLK; data <<= 1; (void) *ptr; (void) *ptr; (void) *ptr; }#endif /* CUST4_NEW_BOARD */}#endif /*CUST4*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -