www.pudn.com > 6027_HD65.rar > cdvdcmd.c


/***************    MTK CONFIDENTIAL & COPYRIGHTED     ****************/ 
/***************                                       ****************/ 
/***************  $Modtime:: 04/07/25 12:26p   $       ****************/ 
/***************  $Revision:: 6                $       ****************/ 
/***************                                       ****************/ 
/*************** Description : commands used for       ****************/ 
/***************               Channel decoder         ****************/ 
/***************                                       ****************/ 
/***************     Company : MediaTek Inc.           ****************/ 
/***************  Programmer : Joseph Lin              ****************/ 
/**********************************************************************/ 
 
#define _C_CDVDCMD_ 
 
#include "general.h" 
 
#pragma NOAREGS 
 
/*************************************************************************** 
     Function : void CMDReadDVD(void) 
  Dsecription : return ONLY 2048 bytes USER DATA of a sector 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDReadDVD(void) 
{ 
  if (!_fgDiskIsDVD) 
  { 
    _bErrCode = ERR_DATA_MODE; 
    return; 
  } 
 
  _wPauseTimer = 0; 
  // Setup Starting LBA and Length 
  bHiByte(wHiWord(_dStartAddr)) = _pbCmdBlk[2]; 
  bLoByte(wHiWord(_dStartAddr)) = _pbCmdBlk[3]; 
  bHiByte(wLoWord(_dStartAddr)) = _pbCmdBlk[4]; 
  bLoByte(wLoWord(_dStartAddr)) = _pbCmdBlk[5]; 
 
    // Add 0x30000 for DVD 
#ifdef SUPPORT_DVDRAM_FAMILY 
  _dStartAddr += (_fgDiskIsDVDRAM ? 0x031000L : 0x30000L); 
#else 
  /* Jacob: get the data area offset from the RISC setting */ 
  _dStartAddr += 0x030000L + _dwDataAreaOfst; 
#endif 
 
  // add protection if the LBA is extra large 
  if (_dStartAddr > _dMaxLBA) 
  { 
    _bErrCode = ERR_DATA_MODE; 
    return; 
  } 
 
  bHiByte(wHiWord(_dXferBlkLen)) = _pbCmdBlk[6]; 
  bLoByte(wHiWord(_dXferBlkLen)) = _pbCmdBlk[7]; 
  bHiByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[8]; 
  bLoByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[9]; 
 
  if (_dXferBlkLen)              // DO ONLY IF LENGTH NOT ZERO 
  { 
    // Check sector range and layer 
    _pbCmdBlk[11] = bDIChkLayerType(); 
 
    // Target is Data 
    if (_pbCmdBlk[11] < LEADOUT_LEADIN) 
    { 
      ClrCmdBusy(); 
#ifdef SUPPORT_DVDRAM_FAMILY 
      // DVDRAM 
      if (_fgDiskIsDVDRAM) 
      { 
        ReadDVDRAMData(); 
      } 
      else 
      { 
        ReadDVDData(); 
      } 
#else 
      ReadDVDData(); 
#endif 
    } 
    else    // Target is Audio or Cross Region or Lead-in or Lead-out 
    { 
      _bErrCode = ERR_DATA_MODE;  // Illegal Mode for This Track 
    } 
  } 
} 
 
#ifdef SUPPORT_SACD 
/*************************************************************************** 
     Function : void CMDReadDVDLeadIn(void) 
  Dsecription : return ONLY 2048 bytes USER DATA of a sector 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDReadDVDLeadIn(void) 
{ 
  if (!_fgDiskIsDVD) 
  { 
    _bErrCode = ERR_DATA_MODE; 
    return; 
  } 
 
  // Setup Starting LBA and Length 
  bHiByte(wHiWord(_dStartAddr)) = _pbCmdBlk[2]; 
  bLoByte(wHiWord(_dStartAddr)) = _pbCmdBlk[3]; 
  bHiByte(wLoWord(_dStartAddr)) = _pbCmdBlk[4]; 
  bLoByte(wLoWord(_dStartAddr)) = _pbCmdBlk[5]; 
 
  if (_pbCmdBlk[6])              // DO ONLY IF LENGTH NOT ZERO 
  { 
    ClrCmdBusy(); 
    if (!fgReadLTData(AREA_LEADIN, _pbCmdBlk[6])) 
    { 
      _bErrCode = ERR_CMD_FAIL;  // Illegal Mode for This Track 
    } 
  } 
} 
#endif  //SUPPORT_SACD 
 
/*************************************************************************** 
     Function : void CMDReadCD(BOOL fgMSF) 
  Dsecription : return 2352+16 bytes Data 
    Parameter : fgMSF - READ CD MSF command or not 
       Return : None 
***************************************************************************/ 
void CMDReadCD(BOOL fgMSF) 
{ 
  // _pbCmdBlk[11] is used as tmp variable 
 
  if (!_fgDiskIsDVD)    // CD only 
  { 
    if (fgMSF) 
    { 
      // Setup Starting  M, S, F  Field 
      bHiByte(wHiWord(_dStartAddr)) = 0; 
      bLoByte(wHiWord(_dStartAddr)) = _pbCmdBlk[3]; // Starting  M 
      bHiByte(wLoWord(_dStartAddr)) = _pbCmdBlk[4]; // Starting  S 
      bLoByte(wLoWord(_dStartAddr)) = _pbCmdBlk[5]; // Starting  F 
      _dStartAddr = dMSFToLBA(_dStartAddr);     // Xfer To Start LBA 
    } 
    else 
    { 
      // Setup Starting LBA and Length 
      bHiByte(wHiWord(_dStartAddr)) = _pbCmdBlk[2]; 
      bLoByte(wHiWord(_dStartAddr)) = _pbCmdBlk[3]; 
      bHiByte(wLoWord(_dStartAddr)) = _pbCmdBlk[4]; 
      bLoByte(wLoWord(_dStartAddr)) = _pbCmdBlk[5]; 
      _dStartAddr += 150;               // Add 150 First 
    } 
 
    // Setup Transfer Lenght in Blocks 
    bHiByte(wHiWord(_dXferBlkLen)) = _pbCmdBlk[6]; 
    bLoByte(wHiWord(_dXferBlkLen)) = _pbCmdBlk[7]; 
    bHiByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[8]; 
    bLoByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[9]; 
 
    if (_dStartAddr < 50)             // Possible 0xFFFFFFXX + 0x96 
    { 
      _bErrCode = ERR_CMD_FAIL;       // INVALID FIELD IN COMMAND PACKET 
      return; 
    } 
 
    // Else Transfer Length > 0, READCD !! 
    // ELSE Transfer Length = 0, NO ACTION but NO ERROR 
    if (_dXferBlkLen)                 // DO ONLY IF LENGTH NOT ZERO 
    { 
      // Check Sector Type, use logical address 
      _pbCmdBlk[11] = bDIChkSectorType(fgMSF ? PHYSICAL : LOGICAL); 
 
      if (_pbCmdBlk[11] == AUDIO_TRACK) // target is audio 
      { 
        if ((_pbCmdBlk[1] == HOST_ANY_TYPE) ||  // Any Sector Type 
            (_pbCmdBlk[1] == HOST_CDDA))        // Expect CDDA Sectors 
        { 
          ClrCmdBusy(); 
          ReadCDDA();                           // Read CDDA Data 
        } 
        else 
        { 
          _bErrCode = ERR_DATA_MODE;  // Illegal Mode for This Track 
        } 
      } 
      else if (_pbCmdBlk[11] < LEADOUT_LEADIN)  // Target is Data 
      { 
        if (_pbCmdBlk[1] == HOST_CDDA)  // Expected Sector Type is CDDA 
        { 
          _bErrCode = ERR_DATA_MODE;    // Illegal Mode for This Track 
        } 
#ifndef SUPPORT_PKT_TYPE 
        else if ((_pbCmdBlk[11] == DATA_TRACK_FIXED_PKT) || (_pbCmdBlk[11] == DATA_TRACK_VAR_PKT)) 
        { 
          _bErrCode = ERR_DATA_MODE;    // Illegal Mode for This Track 
        } 
#endif 
        else 
        { 
          ClrCmdBusy(); 
          ReadCDData();                 // Read CD Loop 
        } 
      } 
      else 
      { 
        _bErrCode = ERR_DATA_MODE;      // Illegal Mode for This Track 
      } 
    } 
  } 
  else 
  { 
    _bErrCode = ERR_DATA_MODE;    // Illegal Mode for This Track 
  } 
} 
 
#ifndef MT1389_512K 
/*************************************************************************** 
     Function : void CMDSetSpeed(void) 
  Dsecription : SET SPEED COMMAND 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDSetSpeed(void) 
{ 
  if (!_fgDiskIsDVD) 
  { 
    bHiByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[2]; 
    bLoByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[3]; 
 
    if (wLoWord(_dXferBlkLen) == 0xFFFF)  // MAX Speed Selected 
    { 
      _bMaxSpeed = MAX_CD_SPEED;          // Set Max Speed 
    } 
    else                                  // Check for Selected Speed ?x 
    { 
      _bMaxSpeed = bLoByte(wLoWord(_dXferBlkLen)); 
 
      if (_bMaxSpeed == 0) 
      { 
        _bMaxSpeed = 1;                   // 0 : Set 1x Speed 
      } 
      else if (_bMaxSpeed > MAX_CD_SPEED) 
      { 
        _bMaxSpeed = MAX_CD_SPEED;        // Set Nx Speed 
      } 
    } 
 
  } 
  else //DVD 
  { 
    bHiByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[2]; 
    bLoByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[3]; 
 
    if (wLoWord(_dXferBlkLen) == 0xFFFF)  // MAX Speed Selected 
    { 
      _bMaxSpeed = MAX_DVD_SPEED;         // Set Max Speed 
    } 
    else                                  // Check for Selected Speed ?x 
    { 
      // Ref to ATAPI R2.5 P.117 : Base Speed is 176 KB/S, NOT 150 KB/S !! 
      _bMaxSpeed = bLoByte(wLoWord(_dXferBlkLen)); 
 
      if (_bMaxSpeed == 0) 
      { 
        _bMaxSpeed = 1;                   // 0 : Set 1x Speed 
      } 
      else if (_bMaxSpeed > MAX_DVD_SPEED) 
      { 
        _bMaxSpeed = MAX_DVD_SPEED;       // Set Nx Speed 
      } 
    } 
  } 
 
  _bOptimumSpeed = _bMaxSpeed;        // Limit Optimum Speed For Servo 
  SRVSetSpeed(_bMaxSpeed);            // Set To Selected Max Speed 
  MSRVTobePaused0();                  // To Be Paused 
} 
#endif 
 
/*************************************************************************** 
     Function : void CMDStartUp(void) 
  Dsecription : start to read TOC if TOC was not read 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDStartUp(void) 
{ 
  BOOL fgReadDisc = FALSE; 
 
#ifdef THOMSON_TRAY 
  if (_bTrayStatus != TRAY_ST_IN) 
#else 
  if (!fgTrayIsIn())        // Is Tray Out ? 
#endif 
  { 
    TrayIn();               // Do Tray In 
 
#ifdef THOMSON_TRAY 
    if (_bTrayStatus == TRAY_ST_IN) 
#else 
    if (fgTrayIsIn()) 
#endif 
    { 
      fgReadDisc = TRUE; 
    } 
    else 
    { 
      _bErrCode = ERR_READ_TOC; 
    } 
  } 
  else if (!_bTotalSen)                 // If Tray is In, Try to read again 
  { 
    fgReadDisc = TRUE; 
  } 
 
  if (fgReadDisc) 
  { 
    ClrCmdBusy(); 
    if (fgDIReadDiscInfo())             // Read TOC/Lead In 
    { 
      // read successfully, no interruption 
      InvalidBuffer();                  // Invalidate Buffer Content 
#ifdef AUDIO_IN_EN 
      if (_bDiscLoadSt == DISC_LOAD_STARTUP) 
      { 
        _bDiscLoadSt = DISC_LOAD_TOC; 
      } 
#endif 
    } 
  } 
} 
 
/*************************************************************************** 
     Function : void CMDProcTray(void) 
  Dsecription : open tray or close tray 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDProcTray(void) 
{ 
  if (_pbCmdBlk[0] == CMD_OPEN_TRAY) 
  { 
#if (defined(TOP_LOADER) || defined(THOMSON_TRAY)) 
    if (_bTrayStatus != TRAY_ST_OUT) 
#else 
    if (!fgTrayIsOut())        // Do when Tray is not Out 
#endif 
    { 
      ClrCmdBusy(); 
      StopDecoder(); 
      TrayOut();                  // Set Tray Out 
    } 
  } 
  else  // close tray 
  { 
#if (defined(TOP_LOADER) || defined(THOMSON_TRAY)) 
    if (_bTrayStatus != TRAY_ST_IN) 
#else 
    if (!fgTrayIsIn())        // Is Tray Out ? 
#endif 
    { 
      ClrCmdBusy(); 
      TrayIn();               // Do Tray In 
    } 
  } 
} 
 
/*************************************************************************** 
     Function : void CMDSetPower(BYTE bMode) 
  Dsecription : set CDVD power mode 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDSetPower(BYTE bMode) 
{ 
  switch (bMode & 0x0F) 
  { 
    case SV_PWR_ACTIVE: 
      // Place device into Idle State, Standby Timer is reloaded 
      ChangePWRMode(SV_PWR_ACTIVE); 
      break; 
 
#ifndef REDUCE_POWER_MODE 
    case SV_PWR_IDLE_PAUSE:   // Place device into idle State 
      ChangePWRMode(SV_PWR_IDLE_PAUSE); 
      break; 
 
    case SV_PWR_IDLE_STOP:    // Place device into idle State 
      ChangePWRMode(SV_PWR_IDLE_STOP); 
      break; 
#endif 
 
    case SV_PWR_STANDBY:      // Place device into Standby/Sleep State 
#ifdef POWERDOWN_KEY_SCAN 
    ChangePWRMode(SV_PWR_STANDBY); 
#else 
    ChangePWRMode(SV_PWR_SLEEP); 
#endif 
      break; 
  } 
} 
 
/*************************************************************************** 
     Function : void CMDGetStatus(void) 
  Dsecription : get the channel decoder status 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDGetStatus(void) 
{ 
  WriteBIM(BIM_TRA2, _bTrayStatus); 
} 
 
/*************************************************************************** 
     Function : void CMDSetParam(void) 
  Dsecription : set parameters 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDSetParam(void) 
{ 
  if ((_pbCmdBlk[1] == 1) && (_pbCmdBlk[2] == 0) && (_pbCmdBlk[3] == 0)) 
  { 
    // treat the disc as CDDA disc. 
    // some CDDA disc record wrong TOC information bits, to overcome this wrong 
    // info we pretend this disc as a CDDA disc 
    _fgHaveAudio = TRUE; 
    bHiByte(wHiWord(_dDiscMap)) = AUDIO_TRACK; 
  } 
} 
 
#ifdef DISC_UPDATE_CODE 
/*************************************************************************** 
     Function : void CMDUpgrade(void) 
  Dsecription : upgrade firmware, the firmware code was put in the address 
                of _pbCmdBlk[2] - _pbCmdBlk[5] 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDUpgrade(void) 
{ 
  bLoByte(wLoWord(_dStartAddr)) = _pbCmdBlk[2]; 
  bHiByte(wLoWord(_dStartAddr)) = _pbCmdBlk[3]; 
  bLoByte(wHiWord(_dStartAddr)) = _pbCmdBlk[4]; 
  bHiByte(wHiWord(_dStartAddr)) = _pbCmdBlk[5]; 
 
  bLoByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[6]; 
  bHiByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[7]; 
  bLoByte(wHiWord(_dXferBlkLen)) = _pbCmdBlk[8]; 
  bHiByte(wHiWord(_dXferBlkLen)) = _pbCmdBlk[9]; 
 
  StopDecoder(); 
 
  vEepromQueueFlush(); 
 
#ifndef UPG_FINISH_TRAY_OUT 
  TrayOut(); 
#endif 
 
  FlashWriteCode(); 
} 
#endif //DISC_UPDATE_CODE 
 
#ifdef SUPPORT_CAPTURE_LOGO 
/*************************************************************************** 
     Function : void CMDWriteLogo(void) 
  Dsecription : 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDWriteLogo(void) 
{ 
  bLoByte(wLoWord(_dStartAddr)) = _pbCmdBlk[2]; 
  bHiByte(wLoWord(_dStartAddr)) = _pbCmdBlk[3]; 
  bLoByte(wHiWord(_dStartAddr)) = _pbCmdBlk[4]; 
  bHiByte(wHiWord(_dStartAddr)) = _pbCmdBlk[5]; 
 
  bLoByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[6]; 
  bHiByte(wLoWord(_dXferBlkLen)) = _pbCmdBlk[7]; 
  bLoByte(wHiWord(_dXferBlkLen)) = _pbCmdBlk[8]; 
  bHiByte(wHiWord(_dXferBlkLen)) = _pbCmdBlk[9]; 
 
  _dXferBlkLen -= 1; 
 
  StopDecoder(); 
 
  MSRVFree(); 
 
  while (_rUI.bState != UI_LOGO_CAPTURE) 
  { 
    // wait UI state change 
  } 
 
  FlashWriteLogo(); 
} 
#endif // SUPPORT_CAPTURE_LOGO 
 
/*************************************************************************** 
     Function : void CMDRISCWakeup(void) 
  Dsecription : RISC is waking up 
    Parameter : None 
       Return : None 
***************************************************************************/ 
#pragma disable 
void CMDRISCWakeup(void) 
{ 
#if (!defined(INTERNAL_TEST) || defined(RISC_ICE_MODE)) 
  if (_rUI.fgRiscReady == TRUE) 
  { 
    /* for RISC reset only */ 
  #ifdef DELAY_UI_STARTUP 
    _bRISCWakeupCnt = 0; 
  #endif 
    _rUI.bState = UI_WAIT_RISC_START; 
  } 
  else 
#endif /* RISC_ICE_MODE */ 
  { 
    _fgNotify = TRUE; 
    _rUI.fgRiscReady = TRUE; 
  } 
} 
 
#ifndef MT1389_512K 
/*************************************************************************** 
     Function : void CMDRISCWakeup(void) 
  Dsecription : RISC is waking up 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDSetSclk(BYTE bMode) 
{ 
  ChangeSysClk(bMode); 
} 
#endif 
 
#ifndef MT1389_512K 
/*************************************************************************** 
     Function : void CMDDebug(void) 
  Dsecription : debug command 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDDebug(void) 
{ 
  WORD wTmp; 
 
  _bErrCode = ERR_NOERR; 
  _bCDVDStatus = ST_BUSY; 
 
  switch (_pbCmdBlk[0]) 
  { 
    case CMD_READ_REG: // read xdata 
      bHiByte(wTmp) = _pbCmdBlk[5]; 
      bLoByte(wTmp) = _pbCmdBlk[4]; 
      WriteBIM(BIM_TRA3, XBYTE[wTmp]); 
      break; 
 
    case CMD_WRITE_REG: // write xdata 
      bHiByte(wTmp) = _pbCmdBlk[5]; 
      bLoByte(wTmp) = _pbCmdBlk[4]; 
      XBYTE[wTmp] = _pbCmdBlk[8]; 
      break; 
 
    default: 
      _bErrCode = ERR_CMD_FAIL;   // invalid field in command packet 
      break; 
  } 
 
  _bCDVDStatus = ST_READY; 
} 
#endif 
 
#ifdef REBOOT_TEST 
/*************************************************************************** 
     Function : void CMDReboot(void) 
  Dsecription : reboot the system 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDReboot(void) 
{ 
  StopDecoder(); 
  MSRVStop(); 
  Restart8032(FALSE); 
} 
#endif //REBOOT_TEST 
 
#ifdef SUPPORT_SACD 
/*************************************************************************** 
     Function : void CMDPspKeyDect(void) 
  Dsecription : SACD PSP key detection 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDPspKeyDect(void) 
{ 
  PspKeyDetect(); 
} 
#endif  //SUPPORT_SACD 
 
#ifdef DEBUG_RS232_C1C2 
/*************************************************************************** 
     Function : void CMDSeekCDVD(void) 
  Dsecription : SEEK COMMAND used by RS232 interface for turnning SERVO 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDSeekCDVD(void) 
{ 
  bHiByte(wHiWord(_dStartAddr)) = 0; 
  bLoByte(wHiWord(_dStartAddr)) = _pbCmdBlk[3]; 
  bHiByte(wLoWord(_dStartAddr)) = _pbCmdBlk[4]; 
  bLoByte(wLoWord(_dStartAddr)) = _pbCmdBlk[5]; 
 
  _dXferBlkLen = 1;                 // Initial for check_sector_type() 
  if (_fgDiskIsDVD) 
  { 
    _dStartAddr += 0x030000L;       // Add 0x30000 for DVD 
    _pbCmdBlk[11] = bDIChkLayerType(); 
  } 
  else 
  { 
    _dStartAddr += 150;             // Add 150 First 
    _pbCmdBlk[11] = bDIChkSectorType(LOGICAL); 
  } 
  if (_fgDiskIsDVD) 
  { 
    if (_bSeekLayer == SEEK_LAYER1) 
    { 
      // Mapping address at Layer 1 
      _dStartAddr = dMapLayer1Addr(_dStartAddr); 
    } 
 
    // SEEK to Desired LBA 
    MDVDRdSeek(bLoByte(wHiWord(_dStartAddr)), 
               bHiByte(wLoWord(_dStartAddr)), 
               bLoByte(wLoWord(_dStartAddr))); 
  } 
  else 
  { 
    if (_pbCmdBlk[11] == DATA_TRACK_FIXED_PKT)  // use method 2 addressing? 
    { 
      _dStartAddr = dLBAToMSF16(dLBAToPBA(_dStartAddr) - 3); 
    } 
    else 
    { 
      _dStartAddr = dLBAToMSF16(_dStartAddr - 3); 
    } 
 
    // SEEK to Desired MSF 
    MCDRdSeek(bLoByte(wHiWord(_dStartAddr)), 
            bHiByte(wLoWord(_dStartAddr)), 
            bLoByte(wLoWord(_dStartAddr))); 
  } 
 
  _pbTBuf[0] = 1; 
  _pbTBuf[1] = _bPlayerStatus; 
  _bTNum = 2; 
  _bTCnt = 0; 
 
  if ((_bTNum) && (bReadAUD(AUD_RSSTA) & WALLOW)) 
  { 
    _bTNum--; 
    WriteAUD(AUD_RSDATA, _pbTBuf[_bTCnt++]); 
  } 
  _wPauseTimer = 0; 
 
} 
 
/************************************************************************ 
     Function : void GetQCode(BYTE bMode) 
  Description : Read sub-channel data 
    Parameter : bMode - 1, 2, or 3 
    Return    : None 
************************************************************************/ 
void GetQCode(BYTE bMode) 
{ 
  if (bMode == 1)                   //  Format 1 : Current Position 
  { 
    // Do Read Qcode Only When Servo On and Not In Pause State 
    if (!_fgPauseStatus) 
    { 
      SRVReadQID(1); 
 
      // Track Number. 00-99 (BCD), or AA (Lead Out) 
      if (_rQCode.bTrkNo <= 0x99) 
      { 
        _rQCode.bTrkNo = bBCDToHEX(_rQCode.bTrkNo); 
      } 
 
      // X(subdivision) or POINT(for TOC) 
      if (_rQCode.bIdx <= 0x99) 
      { 
        _rQCode.bIdx = bBCDToHEX(_rQCode.bIdx); 
      } 
 
      _rQCode.bMin  = bBCDToHEX(_rQCode.bMin);     // Relative Minute 
      _rQCode.bSec  = bBCDToHEX(_rQCode.bSec);     // Relative Second 
      _rQCode.bBlk  = bBCDToHEX(_rQCode.bBlk);     // Relative Frame 
      _rQCode.bAMin = bBCDToHEX(_rQCode.bAMin);    // Absolute Minute 
      _rQCode.bASec = bBCDToHEX(_rQCode.bASec);    // Absolute Second 
      _rQCode.bABlk = bBCDToHEX(_rQCode.bABlk);    // Absolute Frame 
    } 
  #ifdef QCODE_STOP_CACHED 
    // Servo Stopped Or In Pause Status ==> Q-Code Must Be Previously Cached 
    else 
    { 
      _rQCode.bCtrlAddr = _rXQCode.bCtrlAddr; // Control/Adr 
      _rQCode.bTrkNo    = _rXQCode.bTrkNo;    // TNO 
      _rQCode.bIdx      = _rXQCode.bIdx;      // Index 
      _rQCode.bMin      = _rXQCode.bMin;      // Relative Minute 
      _rQCode.bSec      = _rXQCode.bSec;      // Relative Second 
      _rQCode.bBlk      = _rXQCode.bBlk;      // Relative Frame 
      _rQCode.bAMin     = _rXQCode.bAMin;     // Absolute Minute 
      _rQCode.bASec     = _rXQCode.bASec;     // Absolute Second 
      _rQCode.bABlk     = _rXQCode.bABlk;     // Absolute Frame 
 
      _bPlayerStatus = PLAYER_READY; 
    } 
  #endif 
  } 
  else 
  { 
    SRVReadQID(bMode); 
  } 
} 
/*************************************************************************** 
     Function : void SRVReadQID(void) 
  Description : Get Current Address COMMAND used by RS232 interface 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void SRVReadQID(BYTE mode) 
{ 
  BYTE   bCount=200; 
 
  _bPlayerStatus = PLAYER_READY; 
 
  if (_fgDiskIsDVD) 
  { 
    do 
    { 
      if ((_bPlayerStatus=bReadSectID()) != PLAYER_READY) 
      { 
        goto exit_ReadQID; 
      } 
      if (mode == 0)                // mode=0, don't care mode 
      { 
        return; 
      } 
      else 
      { 
        return; 
      } 
    }while (--bCount); 
  } 
  else 
  { 
    do 
    { 
      if ((_bPlayerStatus = bReadQInfo()) != PLAYER_READY) 
      { 
        goto exit_ReadQID; 
      } 
      if (mode == 0)                // mode=0, don't care mode 
      { 
        return; 
      } 
      else 
      { 
        if ((_rQCode.bCtrlAddr & 0x0F) == mode) 
        { 
          return; 
        } 
      } 
    }while (--bCount); 
  } 
exit_ReadQID: 
  _bPlayerStatus = READ_ERROR; 
  return; 
} 
 
/*************************************************************************** 
     Function : void CMDGetPIPOC1C2(void) 
  Description : Get PIPOC1C2 COMMAND used by RS232 interface 
    Parameter : None 
       Return : None 
***************************************************************************/ 
void CMDGetPIPOC1C2(void) 
{ 
  DWRD dTmp; 
  BYTE bTmp; 
 
  #ifndef READ_PIERR_ONLY 
  DWRD dSeekAddr; 
  BYTE bErrCnt; 
  #endif 
 
  SRVPauseOff();                            // Disable Pause 
 
  SRVSetSpeed(_bOptimumSpeed); 
 
  if (_fgDiskIsDVD) 
  { 
  #ifdef SUPPORT_DVDRAM_FAMILY 
    if (_fgDiskIsDVDRAM) 
    { 
      ReadRAMPIPO(); 
      return; 
    } 
  #endif 
  #ifdef READ_PIERR_ONLY 
 
    #ifdef READ_PIPO_1ECCBLK 
    WriteDEC(RW_CIRCCTL, DVDERRCNT_01 + PI_FRMERR); // 16 sectors 
    #else 
    WriteDEC(RW_CIRCCTL, DVDERRCNT_42 + PI_FRMERR); // 42 ECC sectors 
    #endif 
    WriteDEC(RW_REGCTRL, DVD_PIPO);         // PI/PO  Frame Error 
 
    InvalidBuffer();                        // Invalid Buffer 
 
    WriteDEC(RW_TRIG, READTRG); 
 
    SRVReadQID(1); 
    bHiByte(wHiWord(_dSectorID)) = 0; 
    _dStartAddr = _dSectorID; 
    while(1) 
    { 
      SRVReadQID(1); 
 
      bHiByte(wHiWord(_dSectorID)) = 0; 
 
      if (_dSectorID > _dStartAddr)       // avoid smaller than start address 
      { 
    #ifdef READ_PIPO_1ECCBLK 
        if ((_dSectorID - _dStartAddr) > 0x10)       // 1 ECC BLK 
    #else 
        if ((_dSectorID - _dStartAddr) > 0x2A0)      // 42 ECC BLKS 
    #endif 
        { 
          break; 
        } 
      } 
    } 
 
    WriteDEC(RW_TRIG, STOPRTRG); 
 
    if (_bSeekLayer == SEEK_LAYER1) 
    { 
      if (_fgPTP) 
      { 
        dTmp = _dSectorID - 0x2ffff + _dEndPSN0; 
      } 
      else 
      { 
        dTmp = _dSectorID - ~_dEndPSN0 + _dEndPSN0 + 1; 
      } 
    } 
    else 
    { 
      dTmp = _dSectorID; 
    } 
 
    bLoByte(wHiWord(dTmp)) = bLoByte(wHiWord(dTmp)) - 0x03; 
    bLoByte(wLoWord(dTmp)) = bLoByte(wLoWord(dTmp)) & 0xF0; 
    _dStartAddr = _dSectorID; 
 
  #else 
    #ifdef READ_PIPO_1ECCBLK 
    WriteDEC(RW_CIRCCTL, PIECCALIGN + DVDERRCNT_01 + PI_FRMERR);// 16 sectors 
    #else 
    WriteDEC(RW_CIRCCTL, PIECCALIGN + DVDERRCNT_42 + PI_FRMERR);// 42 ECC sectors 
    #endif 
 
    WriteDEC(RW_REGCTRL, DVD_PIPO_FRM);     // PI/PO  Frame Error 
 
    StopDecoder(); 
    _fgBufErr = FALSE;                      // Clear Buffer Error // Modify BC2Err 
 
    WriteBLKC(RW_EBLK, 0x00);             // Reset Decode ECC Block 
    WriteBLKC(RW_DBLK, 0x00);             // Reset Decode Block 
    InvalidBuffer();                      // Invalid Buffer 
    WriteDEC(RW_BMT, CPDBLK);             // BBLK = DBLK 
 
    // one ECC block has 16 sectors, align to DWRD 
    bLoByte(wLoWord(_dStartAddr)) &= 0xF0; 
    WriteDEC(RW_TARR, _bSeekLayer); 
    WriteDEC(RW_TARH, bLoByte(wHiWord(_dStartAddr))); 
    WriteDEC(RW_TARM, bHiByte(wLoWord(_dStartAddr))); 
    WriteDEC(RW_TARL, bLoByte(wLoWord(_dStartAddr))); 
 
    WriteDEC(RW_EID0, AREA_DATA + _bSeekLayer); 
    WriteDEC(RW_EID1, bLoByte(wHiWord(_dStartAddr))); 
    WriteDEC(RW_EID2, bHiByte(wLoWord(_dStartAddr))); 
    WriteDEC(RW_EID3, bLoByte(wLoWord(_dStartAddr))); 
 
    bTmp = IDNMIEN + NOEFMEN + TFIEN + TNFIEN 
    #ifdef ENABLE_BUF_C2PO 
           + IHCEN 
    #endif 
    #ifdef ENABLE_FIFOTH 
           + FIFOTH 
    #endif 
           ; 
    WriteDEC(RW_MCIER, bTmp); 
 
    WriteDEC(RW_DCTRL1, DVD_RLIMIT);        // Disable Auto Stop Buffering 
    WriteDEC(RW_DENEN, 0x00);               // Disable Decoding Error Int 
    WriteDEC(RW_DIEN, DEIEN + MCIEN ); 
    if (_bSeekLayer == SEEK_LAYER1) // Translate to LSN 
    { 
      if (_fgPTP) 
      { 
        dTmp = _dStartAddr - 0x2ffff + _dEndPSN0; 
      } 
      else 
      { 
        dTmp = _dStartAddr - ~_dEndPSN0 + _dEndPSN0 + 1; 
      } 
    } 
    else 
    { 
      dTmp = _dStartAddr; 
    } 
    bLoByte(wHiWord(dTmp)) -= 0x03; 
    bErrCnt = 0; 
 
lbErrCntTarget: 
    StopBuffering(); 
    bErrCnt++; 
 
    // RE-SEEK to Next Uncached Block - Offset 
    dSeekAddr = _dStartAddr + _cSeekOffset; 
    _bSeekLayer = bReadDEC(RW_TARR) & 0x01; 
    MDVDRdSeek2(bLoByte(wHiWord(dSeekAddr)), 
                bHiByte(wLoWord(dSeekAddr)), 
                bLoByte(wLoWord(dSeekAddr))); 
 
    if (_bPlayerStatus == PLAYER_READY) 
    { 
      WriteDEC(RW_TRIG, READTRG + TARGETTRG); 
    } 
    else 
    { 
      _fgBufErr = TRUE; 
    } 
// 
//    while (!(bReadDEC(RD_ISR) & DVDDB)) 
//    { 
//      if (_testbit_(_fgBufErr)) 
//      { 
//        goto lbErrCntTarget; 
//      } 
//    } 
 
    bHiByte(wHiWord(_dStartAddr)) = 0; 
    bHiByte(wHiWord(_dBufStartBlk)) = 0; 
    do 
    { 
      bLoByte(wHiWord(_dBufStartBlk)) = bReadDEC(RW_EID1); 
      bHiByte(wLoWord(_dBufStartBlk)) = bReadDEC(RW_EID2); 
      bLoByte(wLoWord(_dBufStartBlk)) = bReadDEC(RW_EID3); 
      if (_fgBufErr)      // IDNM error 
      { 
        goto lbErrCntTarget; 
      } 
    } 
  #ifdef READ_PIPO_1ECCBLK 
    while ((_dBufStartBlk - _dStartAddr) <= 0x10);      // 1 ECC BLKS 
  #else 
    while ((_dBufStartBlk - _dStartAddr) <= 0x2A0);     // 42 ECC BLKS 
  #endif 
 
    bHiByte(wHiWord(dSeekAddr)) = bReadDEC(RD_DECMONSTA0); 
    bLoByte(wHiWord(dSeekAddr)) = bReadDEC(RD_DECMONSTA1); 
    bHiByte(wLoWord(dSeekAddr)) = bReadDEC(RD_DECMONSTA2); 
    bLoByte(wLoWord(dSeekAddr)) = bReadDEC(RD_DECMONSTA3); 
    if (bHiByte(wLoWord(dSeekAddr))) 
    { 
      StopDecoder(); 
      _nop_(); 
    } 
 
    // Update Start Addr 
    #ifdef READ_PIPO_1ECCBLK 
    _dStartAddr += 0x10; 
    #else 
    _dStartAddr += 0x2A0; 
    #endif 
  #endif 
  } 
  else 
  { 
    // 75 sectors and C1/C2 no solution error 
    WriteDEC(RW_CIRCCTL, CDROM_AUTO_CIRC + CDERRCNT_75 + C1C2_NOSFRMERR); 
    WriteSRV(RW_DEMOCTL, CDROM_ENA_CIRC);         // Enable CIRC decoding 
    WriteSRV(RW_AUCT, CDDA_DIS_INTP);             // Disable Audio Output Interpolate 
 
    WriteDEC(RW_REGCTRL, CD_C1C2);                // C1/C2 
 
    GetQCode(0x01); 
 
//    if (_bPlayerStatus != PLAYER_READY) 
//    { 
//      BuildSense(0x03, 0x09, 0x00); 
//      return; 
//    } 
 
    bHiByte(wHiWord(dTmp)) = 0; 
    bLoByte(wHiWord(dTmp)) = _rQCode.bAMin; 
    bHiByte(wLoWord(dTmp)) = _rQCode.bASec; 
    bLoByte(wLoWord(dTmp)) = _rQCode.bABlk; 
 
    while(1) 
    { 
      GetQCode(0x01); 
      if (_rQCode.bASec != bHiByte(wLoWord(dTmp))) 
      { 
        break; 
      } 
    } 
  } 
 
  _bTCnt = 0; 
  _pbTBuf[_bTCnt++] = 8; 
  _pbTBuf[_bTCnt++] = 0x00; 
  _pbTBuf[_bTCnt++] = bLoByte(wHiWord(dTmp)); 
  _pbTBuf[_bTCnt++] = bHiByte(wLoWord(dTmp)); 
  _pbTBuf[_bTCnt++] = bLoByte(wLoWord(dTmp)); 
#ifdef READ_PIERR_ONLY 
  _pbTBuf[_bTCnt++] = bReadDEC(RD_DECMONSTA0); 
  _pbTBuf[_bTCnt++] = bReadDEC(RD_DECMONSTA1); 
  if (_fgDiskIsDVD) 
  { 
    WriteDEC(RW_REGCTRL, DVD_PIPO_FRM);           // PI/PO  Frame Error 
    _pbTBuf[_bTCnt++] = bReadDEC(RD_DECMONSTA0); 
    _pbTBuf[_bTCnt++] = bReadDEC(RD_DECMONSTA1); 
  } 
  else 
  { 
    _pbTBuf[_bTCnt++] = bReadDEC(RD_DECMONSTA2); 
    _pbTBuf[_bTCnt++] = bReadDEC(RD_DECMONSTA3); 
  } 
#else 
  if (_fgDiskIsDVD) 
  { 
    _pbTBuf[_bTCnt++] = bHiByte(wHiWord(dSeekAddr)); 
    _pbTBuf[_bTCnt++] = bLoByte(wHiWord(dSeekAddr)); 
    _pbTBuf[_bTCnt++] = bHiByte(wLoWord(dSeekAddr)); 
    _pbTBuf[_bTCnt++] = bLoByte(wLoWord(dSeekAddr)); 
  } 
  else 
  { 
    _pbTBuf[_bTCnt++] = bReadDEC(RD_DECMONSTA0); 
    _pbTBuf[_bTCnt++] = bReadDEC(RD_DECMONSTA1); 
    _pbTBuf[_bTCnt++] = bReadDEC(RD_DECMONSTA2); 
    _pbTBuf[_bTCnt++] = bReadDEC(RD_DECMONSTA3); 
  } 
#endif 
/* 
  _bTNum = 9; 
  _bTCnt = 0; 
  _bTCnt = 0; 
  _pbTBuf[_bTCnt++] = 8; 
  _pbTBuf[_bTCnt++] = 0x00; 
  _pbTBuf[_bTCnt++] = bLoByte(wHiWord(dTmp)); 
  _pbTBuf[_bTCnt++] = bHiByte(wLoWord(dTmp)); 
  _pbTBuf[_bTCnt++] = bLoByte(wLoWord(dTmp)); 
  _pbTBuf[_bTCnt++] = 0x00; 
  _pbTBuf[_bTCnt++] = 0x00; 
  _pbTBuf[_bTCnt++] = 0x00; 
  _pbTBuf[_bTCnt++] = 0x00; 
*/ 
  _bTNum = 9; 
  _bTCnt = 0; 
 
    if ((_bTNum) && (bReadAUD(AUD_RSSTA) & WALLOW)) 
    { 
      _bTNum--; 
      WriteAUD(AUD_RSDATA, _pbTBuf[_bTCnt++]); 
    } 
    else 
    { 
      _bTCnt = 0; 
    } 
    _wPauseTimer = 0; 
 
  MSRVTobePaused0();                         // To Be Paused 
} 
#endif