diff -r 578be2adaf3e -r 307f4279f433 Adaptation/GUID-2344B900-5EC5-4467-BEAD-AB55C88CE63E.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adaptation/GUID-2344B900-5EC5-4467-BEAD-AB55C88CE63E.dita Fri Oct 15 14:32:18 2010 +0100 @@ -0,0 +1,134 @@ + + + + + +Stack +Implementation GuideHow to implement the platform-specific class for an SDIO stack +of an SDIO-based hardware component. +

The stack is provided by the DSDIOStack class. The developers +porting the SDIO Controller must derive the DSDIOStack class +and implement three platform-specific functions: IssueMMCCommandSM(), EnableSDIOInterrupt() and MaxBlockSize().

+

The following sections describe how to implement these functions in the DMySdioStack class +derived from DSIOStack.

+
Hardware registers

The DMySdioStack class +needs to have access to the values and offsets of the SDIO configuration registers. +Refer to the platform documentation and declare appropriate constants in the +header file of the stack class.

+
IssueMMCCommandSM()

If +you have not declared it already, declare the following function in the definition +of DMySdioStack:TMMCErr IssueMMCCommandSM();

DSDIOStack::IssueMMCCommandSM() handles the commands to the bus and must be extended to support the SDIO +protocol. See also DSDStack::IssueMMCCommandsSM().

Rely on the platform documentation to perform the operations and +update appropriate hardware registers when you intercept the following commands:

    +
  • IO_OP_COND (CMD5)

  • +
  • IO_RW_DIRECT (CMD52)

  • +
  • IO_RW_EXTENDED (CMD53)

  • +

You should also handle the additional IO_SEND_OP_COND (R4) +and IO_RW_DIRECT (R5) responses.

In the following example, +the hypothetical hardware platform has two requirements, which are implemented +by the IssueMMCCommandSM() function. The function disables +the CRC7 check when receiving an R4 response to an CMD5 command, and disables +the SDIO interrupt before issuing a CMD52 command.void DMySdioStack::IssueMMCCommandSM() + { + TMMCCommandDesc& cmd = Command(); + ... + // CMD5 + // Disable the CRC7 check for R4 responses + if (cmd.iCommand == ECmd5) + { + // Clear the MMC_CRC7_R4_ENABLE bit + // MMC_SDIO_REG_SLOT0 is a 32-bit hardware register for SDIO in slot 0 + AsspRegister::Modify32(MMC_SDIO_REG_SLOT0, MMC_CRC7_R4_ENABLE, 0); + } + else + { + // Set the MMC_CRC7_R4_ENABLE bit + AsspRegister::Modify32(MMC_SDIO_REG_SLOT0, 0, MMC_CRC7_R4_ENABLE); + } + + // CMD52 + // Disable SDIO interrupts for CMD 52 + if (cmd.iCommand == ECmd52) + { + EnableSDIOInterrupt(EFalse); + } + ... + } +

As the SDIO Controller is instantiated at run-time, the +memory used to support the SDIO transfer mechanisms must be allocated dynamically. +Therefore, you can use two different types of memory and of data transfer:

    +
  • Programmatic input/output using virtual memory

  • +
  • DMA using physically-allocated DChunk objects.

  • +

The KMMCCmdFlagDMARamValid flag of the TMMCCommandDesc object +indicates which kind of memory transfer to use.

If you use the Programmatic I/O method, you need to queue pending data transfers +while you handle hardware interrupts. Your platform's documentation specifies +which interrupts may be received during transfers.

+
EnableSDIOInterrupt()

Declare +the following function in the definition of DMySdioStack:virtual void EnableSDIOInterrupt(TBool aEnable);

DSDIOStack::EnableSDIOInterrupt() enables or disables +the SDIO interrupt.

The following example is a typical implementation +of EnableSDIOInterrupt():void DMySdioStack::EnableSDIOInterrupt(TBool aEnable) + { + if (aEnable) + { + // Set the Interrupt Enable Master Bit + // MMC_SDIO_REG_SLOT0 is a 32-bit hardware register for SDIO in slot 0 + AsspRegister:: Modify32(MMC_SDIO_REG_SLOT0, SDIO_IENM, 0); + } + else + { + // Set the Interrupt Enable Master Bit + AsspRegister:: Modify32(MMC_SDIO_REG_SLOT0, 0, SDIO_IENM); + } + } +

You must also ensure that your interrupt handler checks +the SDIO interrupt register and the card slot before forwarding the interrupt +to the stack. If checking the card slot is likely to take too long, +use a DFC (Delayed Function Call) for the interrupt handler to preserve real-time +performance.

The following example illustrates how to implement +this aspect of the interrupt handler:void DMySdioInterrupt::Service(TAny* aSelf) + { + ... + // Get access to the stack + DPlatMMCStack* stack = (reinterpret_cast<DMySdioInterrupt*>(aSelf))->Stack(); + + // MMC_SDIO_REG_SLOT0 is a 32-bit hardware register for SDIO in slot 0 + TInt32 sdioReg = AsspRegister::Read32(MMC_SDIO_REG_SLOT0); + // Test for the SDIO interrupt + if (sdioReg & KMMC_SDIO_IntPending) + { + // Trigger the PIL’s interrupt handler for slot 0 + stack->HandleSDIOInterrupt(0); + return; + } + + // MMC_SDIO_REG_SLOT1 is a 32-bit hardware register for SDIO in slot 1 + sdioReg = AsspRegister::Read32(MMC_SDIO_REG_SLOT1); + // Test for the SDIO interrupt + if (sdioReg & KMMC_SDIO_IntPending) + { + // Trigger the PIL’s interrupt handler for slot 1 + stack->HandleSDIOInterrupt(1); + return; + } + + ... + } +
+
MaxBlockSize()

Declare +the following function in the definition of DMySdioStack:virtual TUint32 MaxBlockSize() const;

DSDIOStack::MaxBlockSize() returns the maximum block size in bytes +that can be transferred on the SDIO bus. Extended read/write commands require +this information.

In the SD protocol, the block size must be a power +of two. SDIO does not have the same constraint and the block size can be anything +between 1 and 2048.

The following example is a typical implementation +of MaxBlockSize():TUint32 DMySdioStack::MaxBlockSize() const + { + return(512); + } +

+
\ No newline at end of file