⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdhcslot.cpp

📁 S3C2450BSP开发包,里面有很多资料。可以提供大家参考下。有什么需要解决问题。可以联系我QQ:314661
💻 CPP
📖 第 1 页 / 共 5 页
字号:
          status = SD_API_STATUS_DEVICE_REMOVED;
        }
      }
      if (status == SD_API_STATUS_SUCCESS) {
        status = SD_API_STATUS_FAST_PATH_SUCCESS;
      }

      ASSERT(m_fCurrentRequestFastPath);
      m_pCurrentRequest = NULL;
    }
    else  
      status = SubmitBusRequestHandler( pRequest );

    if (status!=SD_API_STATUS_PENDING) { // This one has been finished.
      m_pCurrentRequest = NULL;
    }
    WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,wIntSignals);
  }
  return status;
}

SD_API_STATUS
CSDHCSlotBase::SubmitBusRequestHandler(
    PSD_BUS_REQUEST pRequest
    )
{
  SETFNAME();

  PREFAST_DEBUGCHK(pRequest);
  Validate();

  WORD            wRegCommand;
  SD_API_STATUS   status;
  WORD            wIntStatusEn;
  WORD			wIntSignalEn;	// KYS
  BOOL            fSuccess;

  DEBUGCHK(m_dwReadyInts == 0);
  DEBUGCHK(!m_fCommandCompleteOccurred);

  DEBUGMSG(SDHC_SEND_ZONE, (TEXT("%s CMD:%d\n"), pszFname, pRequest->CommandCode));

  // bypass CMD12 if AutoCMD12 was done by hardware
  if (pRequest->CommandCode == 12) {
    if (m_fAutoCMD12Success) {
      DEBUGMSG(SDHC_SEND_ZONE, 
          (TEXT("%s AutoCMD12 Succeeded, bypass CMD12.\n"), pszFname));
      // The response for Auto CMD12 is in a special area
      UNALIGNED DWORD *pdwResponseBuffer = 
        (PDWORD) (pRequest->CommandResponse.ResponseBuffer + 1); // Skip CRC
      *pdwResponseBuffer = ReadDword(SDHC_R6);
      IndicateBusRequestComplete(pRequest, SD_API_STATUS_SUCCESS);
      status = SD_API_STATUS_SUCCESS;
      goto EXIT;
    }
  }

  m_fAutoCMD12Success = FALSE;

  // initialize command register with command code
  wRegCommand = (pRequest->CommandCode << CMD_INDEX_SHIFT) & CMD_INDEX_MASK;

  // check for a response
  switch (pRequest->CommandResponse.ResponseType) {
    case NoResponse:
      break;

    case ResponseR2:
      wRegCommand |= CMD_RESPONSE_R2;
      break;

    case ResponseR3:
    case ResponseR4:
      wRegCommand |= CMD_RESPONSE_R3_R4;
      break;

    case ResponseR1:
    case ResponseR5:
    case ResponseR6:
    case ResponseR7:
      wRegCommand |= CMD_RESPONSE_R1_R5_R6_R7;
      break;

    case ResponseR1b:
      wRegCommand |= CMD_RESPONSE_R1B_R5B;   
      break;

    default:
      status = SD_API_STATUS_INVALID_PARAMETER;
      goto EXIT;
  }

  // Set up variable for the new interrupt sources. Note that we must
  // enable DMA and read/write interrupts in this routine (not in
  // HandleCommandComplete) or they will be missed.
  wIntStatusEn = ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE);
  wIntStatusEn |= NORMAL_INT_ENABLE_CMD_COMPLETE | NORMAL_INT_ENABLE_TRX_COMPLETE;

  wIntSignalEn = ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE);	// KYS
  wIntSignalEn |= NORMAL_INT_ENABLE_CMD_COMPLETE | NORMAL_INT_ENABLE_TRX_COMPLETE;	// KYS

  // check command inhibit, wait until OK
  fSuccess = WaitForReg<DWORD>(ReadDword, SDHC_PRESENT_STATE, STATE_CMD_INHIBIT, 0);
  if (!fSuccess) {
    DEBUGMSG(SDCARD_ZONE_ERROR, (_T("%s Timeout waiting for CMD Inhibit\r\n"),
          pszFname));
    status = SD_API_STATUS_DEVICE_NOT_RESPONDING;
    goto EXIT;
  }

  // programming registers
  if (!TRANSFER_IS_COMMAND_ONLY(pRequest)) {
    WORD wRegTxnMode = 0;
#ifdef _MMC_SPEC_42_
    // Date : 07.05.14
    // Developer : HS.JANG
    // Description : to support MMCMicro this code was added
    if ( (ReadByte(SDHC_TIMEOUT_CONTROL) != m_dwTimeoutControl) && 
        (pRequest->CommandCode != MMC_CMD_SEND_EXT_CSD) ) {
      WriteByte(SDHC_TIMEOUT_CONTROL, (BYTE) m_dwTimeoutControl);
    } else if ( (ReadByte(SDHC_TIMEOUT_CONTROL) == m_dwTimeoutControl) &&
        (pRequest->CommandCode == MMC_CMD_SEND_EXT_CSD) ) {
      WriteByte(SDHC_TIMEOUT_CONTROL, (BYTE)0x3);
    }
#endif

    wRegCommand |= CMD_DATA_PRESENT;

    if (UseDmaForRequest(pRequest)) {
      wIntStatusEn |= NORMAL_INT_ENABLE_DMA;
      wIntSignalEn |= NORMAL_INT_SIGNAL_DMA;	// KYS

      BOOL fNoException;
      DEBUGCHK(TRANSFER_SIZE(pRequest) <= CB_DMA_BUFFER);

      if (TRANSFER_IS_WRITE(pRequest)) {
        DWORD cbToTransfer = TRANSFER_SIZE(pRequest);

        SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {
          fNoException = SDPerformSafeCopy(m_pbDmaBuffer,
              pRequest->pBlockBuffer, cbToTransfer);
        } SD_RESTORE_PROC_PERMISSIONS();

        if (fNoException == FALSE) {
          status = SD_API_STATUS_ACCESS_VIOLATION;
          goto EXIT;
        }
      }

      WriteDword(SDHC_SYSTEMADDRESS_LO, m_paDmaBuffer);
      wRegTxnMode |= TXN_MODE_DMA;
    }
    else {
      if (TRANSFER_IS_WRITE(pRequest)) {
        wIntStatusEn |= NORMAL_INT_ENABLE_BUF_WRITE_RDY;
      }
      else {
        wIntStatusEn |= NORMAL_INT_ENABLE_BUF_READ_RDY;
      }
    }

    // BlockSize
    // Note that for DMA we are programming the buffer boundary for 4k
    DEBUGMSG(SDHC_SEND_ZONE,(TEXT("Sending command block size 0x%04X\r\n"), (WORD) pRequest->BlockSize));
    //WriteWord(SDHC_BLOCKSIZE, (WORD) pRequest->BlockSize);
    WriteWord(SDHC_BLOCKSIZE, (WORD)( (0x7<<12) | pRequest->BlockSize ));  // KYS

    // We always go into block mode even if there is only 1 block. 
    // Otherwise the Pegasus will occaissionally hang when
    // writing a single block with DMA.
    wRegTxnMode |= (TXN_MODE_MULTI_BLOCK | TXN_MODE_BLOCK_COUNT_ENABLE);

    // BlockCount
    DEBUGMSG(SDHC_SEND_ZONE,(TEXT("Sending command block count 0x%04X\r\n"), 
          (WORD) pRequest->NumBlocks));            
    WriteWord(SDHC_BLOCKCOUNT, (WORD) pRequest->NumBlocks);

    if (pRequest->Flags & SD_AUTO_ISSUE_CMD12) {
      wRegTxnMode |= TXN_MODE_AUTO_CMD12;
    }

    if (TRANSFER_IS_READ(pRequest)) {
      wRegTxnMode |= TXN_MODE_DATA_DIRECTION_READ;     
    }

    // check dat inhibit, wait until okay
    fSuccess = WaitForReg<DWORD>(ReadDword, SDHC_PRESENT_STATE, STATE_DAT_INHIBIT, 0); 
    if (!fSuccess) {
      DEBUGMSG(SDCARD_ZONE_ERROR, (_T("%s Timeout waiting for DAT Inhibit\r\n"),
            pszFname));
      status = SD_API_STATUS_DEVICE_NOT_RESPONDING;
      goto EXIT;
    }

    DEBUGMSG(SDHC_SEND_ZONE,(TEXT("Sending Transfer Mode 0x%04X\r\n"),wRegTxnMode));
    WriteWord(SDHC_TRANSFERMODE, wRegTxnMode);
  }
  else {
    // Command-only
    if (pRequest->CommandCode == SD_CMD_STOP_TRANSMISSION) {
      wRegCommand |= CMD_TYPE_ABORT;
    }
    else if (TransferIsSDIOAbort(pRequest)) {
      // Use R5b For CMD52, Function 0, I/O Abort
      DEBUGMSG(SDHC_SEND_ZONE, (TEXT("Sending Abort command \r\n")));
      wRegCommand |= CMD_TYPE_ABORT | CMD_RESPONSE_R1B_R5B;
    }

    // The following is required for the Pegasus. If it is not present,
    // command-only transfers will sometimes fail (especially R1B and R5B).
    //WriteDword(SDHC_SYSTEMADDRESS_LO, 0);
    //WriteWord(SDHC_BLOCKSIZE, 0);
    //WriteWord(SDHC_BLOCKCOUNT, 0);
  }

  DEBUGMSG(SDHC_SEND_ZONE,(TEXT("Sending command register 0x%04X\r\n"),wRegCommand));
  DEBUGMSG(SDHC_SEND_ZONE,(TEXT("Sending command Argument 0x%08X\r\n"),pRequest->CommandArgument));

  WriteDword(SDHC_ARGUMENT_0, pRequest->CommandArgument);

  // Enable transfer interrupt sources.
  WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE, wIntStatusEn);
  WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, wIntSignalEn);	// KYS

  // Turn the clock on. It is turned off in IndicateBusRequestComplete().
  SDClockOn();

  // Turn the LED on.
  EnableLED(TRUE);

  // Writing the upper byte of the command register starts the command.
  // All register initialization must already be complete by this point.
  WriteWord(SDHC_COMMAND, wRegCommand);

  status = SD_API_STATUS_PENDING;

EXIT:
  return status;
}


VOID 
CSDHCSlotBase::EnableSDIOInterrupts(
    BOOL fEnable
    )
{
  Validate();

  if (fEnable) {
    m_fSDIOInterruptsEnabled = TRUE;
    DoEnableSDIOInterrupts(fEnable);
  }
  else {
    DoEnableSDIOInterrupts(fEnable);
    m_fSDIOInterruptsEnabled = FALSE;
  }
}


VOID 
CSDHCSlotBase::HandleInterrupt(
    )
{
  Validate();

  WORD wIntStatus = ReadWord(SDHC_NORMAL_INT_STATUS);
  if(g_initialInsertion != 1) {
    while(( wIntStatus=ReadWord(SDHC_NORMAL_INT_STATUS)) == 0);
  }

  if (m_fFakeCardRemoval && m_fCardPresent) {
    m_fFakeCardRemoval = FALSE;
    HandleRemoval(TRUE);
  }

  if (wIntStatus != 0) {
    DEBUGMSG(SDHC_INTERRUPT_ZONE, 
        (TEXT("HandleInterrupt (%u) - Normal Interrupt_Status=0x%02x\n"),
         m_dwSlot, wIntStatus));
    RETAILMSG(0, 
        (TEXT("HandleInterrupt (%u) - Normal Interrupt_Status=0x%02x\n"),
         m_dwSlot, wIntStatus));

    // Error handling. Make sure to handle errors first. 
    if ( wIntStatus & NORMAL_INT_STATUS_ERROR_INT ) {
      HandleErrors();
    }

    // Command Complete handling.
    if ( wIntStatus & NORMAL_INT_STATUS_CMD_COMPLETE ) {
      // Clear status
      m_fCommandCompleteOccurred = TRUE;
      WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,(ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) & ~(NORMAL_INT_STATUS_CMD_COMPLETE)));
      WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) & ~(NORMAL_INT_STATUS_CMD_COMPLETE)));
      do {
        WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_CMD_COMPLETE);
      }while(ReadWord(SDHC_NORMAL_INT_STATUS) & (NORMAL_INT_STATUS_CMD_COMPLETE));
      WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) | NORMAL_INT_STATUS_CMD_COMPLETE));
      WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,(ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) | NORMAL_INT_STATUS_CMD_COMPLETE));

      if ( HandleCommandComplete() ) {
        wIntStatus &= ~NORMAL_INT_STATUS_TRX_COMPLETE; // this is command-only request. 
      }
    }

    // Sometimes at the lowest clock rate, the Read/WriteBufferReady
    // interrupt actually occurs before the CommandComplete interrupt.
    // This confuses our debug validation code and could potentially
    // cause problems. This is why we will verify that the CommandComplete
    // occurred before processing any data transfer interrupts.
    if (m_fCommandCompleteOccurred) {
      if (wIntStatus & NORMAL_INT_STATUS_DMA) {
        WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,(ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) & ~(NORMAL_INT_STATUS_DMA)));
        WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) & ~(NORMAL_INT_STATUS_DMA)));
        do {
          WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_DMA);
        }while(ReadWord(SDHC_NORMAL_INT_STATUS) & NORMAL_INT_STATUS_DMA);
        WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) | NORMAL_INT_STATUS_DMA));
        WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,(ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) | NORMAL_INT_STATUS_DMA));

        HandleDma();
        // do not break here. Continue to check TransferComplete. 
      }

      // Buffer Read Ready handling
      if (wIntStatus & NORMAL_INT_STATUS_BUF_READ_RDY ) {
        // Clear status
        WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,(ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) & ~(NORMAL_INT_STATUS_BUF_READ_RDY)));
        WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) & ~(NORMAL_INT_STATUS_BUF_READ_RDY)));
        do {
          WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_BUF_READ_RDY);
        }while((ReadWord(SDHC_NORMAL_INT_STATUS) & NORMAL_INT_STATUS_BUF_READ_RDY));
        WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) | NORMAL_INT_STATUS_BUF_READ_RDY));
        WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, (ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) | NORMAL_INT_STATUS_BUF_READ_RDY));

        HandleReadReady();
        // do not break here. Continue to check TransferComplete. 
      }

      // Buffer Write Ready handling
      if (wIntStatus & NORMAL_INT_STATUS_BUF_WRITE_RDY ) {
        // Clear status
        WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,(ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) & ~(NORMAL_INT_STATUS_BUF_WRITE_RDY)));
        WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) & ~(NORMAL_INT_STATUS_BUF_WRITE_RDY)));
        do {
          WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_BUF_WRITE_RDY);
        }while((ReadWord(SDHC_NORMAL_INT_STATUS) & NORMAL_INT_STATUS_BUF_WRITE_RDY));
        WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) | NORMAL_INT_STATUS_BUF_WRITE_RDY));
        WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,(ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) | NORMAL_INT_STATUS_BUF_WRITE_RDY));

        HandleWriteReady();
        // do not break here. Continue to check TransferComplete. 
      }
    }
    else {
      // We received data transfer interrupt before command 
      // complete interrupt. Wait for the command complete before
      // processing the data interrupt.
    }

    // Transfer Complete handling
    if ( wIntStatus & NORMAL_INT_STATUS_TRX_COMPLETE ) {
      // Clear status
      WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,(ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) & ~(NORMAL_INT_STATUS_TRX_COMPLETE)));
      WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) & ~(NORMAL_INT_STATUS_TRX_COMPLETE)));
      do {
        WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_TRX_COMPLETE | NORMAL_INT_STATUS_DMA);
      }while(ReadWord(SDHC_NORMAL_INT_STATUS) & (NORMAL_INT_STATUS_TRX_COMPLETE|NORMAL_INT_STATUS_DMA));
      WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) | NORMAL_INT_STATUS_TRX_COMPLETE));
      WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,(ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) | NORMAL_INT_STATUS_TRX_COMPLETE));


      HandleTransferDone();
    }

    // SDIO Interrupt Handling
    if ( wIntStatus & NORMAL_INT_STATUS_CARD_INT ) {
      DEBUGCHK(m_fSDIOInterruptsEnabled);
      DEBUGMSG(SDHC_INTERRUPT_ZONE, (_T("SDHCControllerIst: Card interrupt!\n")));

      // Because SDIO Interrupt is level triggered, we are not able to clear
      // the status. The status should be cleared by the card
      // we just disable the interrupt from Interrupt Signal Register
      // and Interrupt Status Enable register, and indicate that 
      // the card is interrupting
      EnableSDIOInterrupts(FALSE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -