1e41f4b71Sopenharmony_ci# MMC 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Overview 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci### Function 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciA multimedia card (MMC) is a small-sized and large-capacity flash memory card used for solid-state non-volatile storage. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciNowadays, MMC refers to a standard driver interface to solid-state storage cards. Memory devices that comply with this standard can be called MMCs. An MMC consists of the MMC controller, MMC bus, and memory card, which can be an MMC, Secure Digital (SD) card, Secure Digital Input Output (SDIO) card, or TransFlash (TF) card. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ciThe MMC, SD, and SDIO buses have similar bus specifications, which have evolved from the MMC bus specifications. The MMC features multimedia storage; the SD focuses on security and data protection; the SDIO, evolving from the SD, provides the interface regardless of the specific form of the peer end (Wi-Fi, Bluetooth, or GPS device). 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci### Basic Concepts 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci- SD card 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci Introduced as an improvement over the MMC, the SD cards can protect their contents from erasure or modification, prevent unauthorized access, and protect copyrighted content using digital rights management. The size of a standard SD card is 24 mm x 32 mm x 2.1 mm, which is a little thicker than an MMC card. The SD cards are forward compatible with MMC cards, that is, all devices that support SD cards also support MMC cards. 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci- SDIO 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci SDIO is an interface designed as an extension for the SD card standard. It introduces the low-speed transfer standard, which supports low-speed I/O with the minimum hardware overhead. The SDIO interface is compatible with the SD cards. 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci### Working Principles 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ciIn the Hardware Driver Foundation (HDF), the MMC uses the independent service mode (see Figure 1) for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device, which increases memory usage. 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ciIn the independent service mode, the core layer does not publish a service for the upper layer. Therefore, a service must be published for each controller. To achieve this purpose: 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci- You need to implement the **Bind()** function in **HdfDriverEntry** to bind services. 30e41f4b71Sopenharmony_ci- The **policy** field of **deviceNode** in the **device_info.hcs** file must be **1** or **2**, but not **0**. 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ciThe MMC module is divided into the following layers: 33e41f4b71Sopenharmony_ci 34e41f4b71Sopenharmony_ci- Interface layer: provides APIs for opening an MMC device, checking whether the MMC controller has devices, and closing an MMC device. 35e41f4b71Sopenharmony_ci- Core layer: provides the capabilities of adding or removing an MMC controller, performing device management, and providing common controller services. The core layer interacts with the adaptation layer through hook functions. 36e41f4b71Sopenharmony_ci- Adaptation layer: instantiates the hook functions to implement specific features. 37e41f4b71Sopenharmony_ci 38e41f4b71Sopenharmony_ci**Figure 1** Independent service mode 39e41f4b71Sopenharmony_ci 40e41f4b71Sopenharmony_ci 41e41f4b71Sopenharmony_ci 42e41f4b71Sopenharmony_ci## Development Guidelines 43e41f4b71Sopenharmony_ci 44e41f4b71Sopenharmony_ci### When to Use 45e41f4b71Sopenharmony_ci 46e41f4b71Sopenharmony_ciThe MMC is used to store multimedia files. Before using your MMC device with OpenHarmony, you need to perform MMC driver adaptation. 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ci### Available APIs 49e41f4b71Sopenharmony_ci 50e41f4b71Sopenharmony_ciTo enable the upper layer to successfully operate the MMC controller by calling the MMC APIs, hook functions are defined in **//drivers/hdf_core/framework/model/storage/include/mmc/mmc_corex.h** for the core layer. You need to implement these hook functions at the adaptation layer and hook them to implement the interaction between the interface layer and the core layer. 51e41f4b71Sopenharmony_ci 52e41f4b71Sopenharmony_ci**MmcCntlrOps**: 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ci```c 55e41f4b71Sopenharmony_cistruct MmcCntlrOps { 56e41f4b71Sopenharmony_ci int32_t (*request)(struct MmcCntlr *cntlr, struct MmcCmd *cmd); 57e41f4b71Sopenharmony_ci int32_t (*setClock)(struct MmcCntlr *cntlr, uint32_t clock); 58e41f4b71Sopenharmony_ci int32_t (*setPowerMode)(struct MmcCntlr *cntlr, enum MmcPowerMode mode); 59e41f4b71Sopenharmony_ci int32_t (*setBusWidth)(struct MmcCntlr *cntlr, enum MmcBusWidth width); 60e41f4b71Sopenharmony_ci int32_t (*setBusTiming)(struct MmcCntlr *cntlr, enum MmcBusTiming timing); 61e41f4b71Sopenharmony_ci int32_t (*setSdioIrq)(struct MmcCntlr *cntlr, bool enable); 62e41f4b71Sopenharmony_ci int32_t (*hardwareReset)(struct MmcCntlr *cntlr); 63e41f4b71Sopenharmony_ci int32_t (*systemInit)(struct MmcCntlr *cntlr); 64e41f4b71Sopenharmony_ci int32_t (*setEnhanceStrobe)(struct MmcCntlr *cntlr, bool enable); 65e41f4b71Sopenharmony_ci int32_t (*switchVoltage)(struct MmcCntlr *cntlr, enum MmcVolt volt); 66e41f4b71Sopenharmony_ci bool (*devReadOnly)(struct MmcCntlr *cntlr); 67e41f4b71Sopenharmony_ci bool (*devPlugged)(struct MmcCntlr *cntlr); 68e41f4b71Sopenharmony_ci bool (*devBusy)(struct MmcCntlr *cntlr); 69e41f4b71Sopenharmony_ci int32_t (*tune)(struct MmcCntlr *cntlr, uint32_t cmdCode); 70e41f4b71Sopenharmony_ci int32_t (*rescanSdioDev)(struct MmcCntlr *cntlr); 71e41f4b71Sopenharmony_ci}; 72e41f4b71Sopenharmony_ci``` 73e41f4b71Sopenharmony_ci 74e41f4b71Sopenharmony_ci**Table 1** Hook functions in **MmcCntlrOps** 75e41f4b71Sopenharmony_ci 76e41f4b71Sopenharmony_ci| Function| Input Parameter| Return Value| Description| 77e41f4b71Sopenharmony_ci| -------- | -------- | -------- | -------- | 78e41f4b71Sopenharmony_ci| doRequest | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**cmd**: structure pointer to the command to execute.| HDF_STATUS| Processes the request.| 79e41f4b71Sopenharmony_ci| setClock | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**clock**: clock frequency to set.| HDF_STATUS| Sets the clock frequency.| 80e41f4b71Sopenharmony_ci| setPowerMode | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**mode**: power consumption mode. For details, see **MmcPowerMode**.| HDF_STATUS| Sets the power consumption mode.| 81e41f4b71Sopenharmony_ci| setBusWidth | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**width**: bus width. For details, see **MmcBusWidth**.| HDF_STATUS| Sets the bus width.| 82e41f4b71Sopenharmony_ci| setBusTiming | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**timing**: bus timing. For details, see **MmcBusTiming**.| HDF_STATUS| Sets the bus timing.| 83e41f4b71Sopenharmony_ci| setSdioIrq | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**enable**: whether to enable SDIO interrupts.| HDF_STATUS| Enables or disables SDIO interrupts.| 84e41f4b71Sopenharmony_ci| hardwareReset | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Resets hardware.| 85e41f4b71Sopenharmony_ci| systemInit | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Performs system initialization.| 86e41f4b71Sopenharmony_ci| setEnhanceStrobe | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**enable**: whether to enable the enhanced strobe feature.| HDF_STATUS| Sets the enhanced strobe feature.| 87e41f4b71Sopenharmony_ci| switchVoltage | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**volt**: voltage to set, which can be 3.3 V, 1.8 V, or 1.2 V.| HDF_STATUS| Sets the voltage.| 88e41f4b71Sopenharmony_ci| devReadOnly | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is read-only.| 89e41f4b71Sopenharmony_ci| cardPlugged | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is removed.| 90e41f4b71Sopenharmony_ci| devBusy | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is being used.| 91e41f4b71Sopenharmony_ci| tune | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**cmdCode**: command code, which is of the uint32_t type.| HDF_STATUS| Tunes the oscillator circuit frequency.| 92e41f4b71Sopenharmony_ci| rescanSdioDev | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Scans and adds an SDIO device.| 93e41f4b71Sopenharmony_ci 94e41f4b71Sopenharmony_ci### How to Develop 95e41f4b71Sopenharmony_ci 96e41f4b71Sopenharmony_ciThe MMC module adaptation procedure is as follows: 97e41f4b71Sopenharmony_ci 98e41f4b71Sopenharmony_ci1. Instantiate the driver entry. 99e41f4b71Sopenharmony_ci2. Configure attribute files. 100e41f4b71Sopenharmony_ci3. Instantiate the MMC controller object. 101e41f4b71Sopenharmony_ci4. Debug the driver. 102e41f4b71Sopenharmony_ci 103e41f4b71Sopenharmony_ci### Example 104e41f4b71Sopenharmony_ci 105e41f4b71Sopenharmony_ciThe following uses the **//device_soc_hisilicon/common/platform/mmc/himci_v200/himci.c** driver of the Hi3516D V300 development board as an example to describe the driver adaptation. 106e41f4b71Sopenharmony_ci 107e41f4b71Sopenharmony_ci1. Instantiate the driver entry. 108e41f4b71Sopenharmony_ci 109e41f4b71Sopenharmony_ci The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. 110e41f4b71Sopenharmony_ci Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit. 111e41f4b71Sopenharmony_ci 112e41f4b71Sopenharmony_ci MMC driver entry example: 113e41f4b71Sopenharmony_ci 114e41f4b71Sopenharmony_ci ```c 115e41f4b71Sopenharmony_ci struct HdfDriverEntry g_mmcDriverEntry = { 116e41f4b71Sopenharmony_ci .moduleVersion = 1, 117e41f4b71Sopenharmony_ci .Bind = HimciMmcBind, // See the Bind function. 118e41f4b71Sopenharmony_ci .Init = HimciMmcInit, // See the Init function. 119e41f4b71Sopenharmony_ci .Release = HimciMmcRelease, // See the Release function. 120e41f4b71Sopenharmony_ci .moduleName = "hi3516_mmc_driver", // (Mandatory) The value must be the same as that of moduleName in the .hcs file. 121e41f4b71Sopenharmony_ci }; 122e41f4b71Sopenharmony_ci HDF_INIT(g_mmcDriverEntry); // Call HDF_INIT to register the driver entry with the HDF. 123e41f4b71Sopenharmony_ci ``` 124e41f4b71Sopenharmony_ci 125e41f4b71Sopenharmony_ci2. Configure attribute files. 126e41f4b71Sopenharmony_ci 127e41f4b71Sopenharmony_ci Add the deviceNode information to the **device_info.hcs** file. The deviceNode information is related to the driver entry registration. The following example uses three MMC controllers as an example. If there are more MMC controllers, add the deviceNode information to the **device_info.hcs** file for each controller. The device attribute values configured in **mmc_config.hcs** are closely related to the default values or value ranges of the **MmcCntlr** members at the core layer. 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci - **device_info.hcs** example: 130e41f4b71Sopenharmony_ci 131e41f4b71Sopenharmony_ci Add the deviceNode information to the **//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file. 132e41f4b71Sopenharmony_ci 133e41f4b71Sopenharmony_ci ```c 134e41f4b71Sopenharmony_ci root { 135e41f4b71Sopenharmony_ci device_info { 136e41f4b71Sopenharmony_ci match_attr = "hdf_manager"; 137e41f4b71Sopenharmony_ci platform :: host { 138e41f4b71Sopenharmony_ci hostName = "platform_host"; 139e41f4b71Sopenharmony_ci priority = 50; 140e41f4b71Sopenharmony_ci device_mmc:: device { 141e41f4b71Sopenharmony_ci device0 :: deviceNode { // DeviceNode of the driver. 142e41f4b71Sopenharmony_ci policy = 2; // The value 2 means to publish services for both kernel- and user-mode processes. 143e41f4b71Sopenharmony_ci priority = 10; // Driver startup priority. 144e41f4b71Sopenharmony_ci permission = 0644; // Permission for the device node created. 145e41f4b71Sopenharmony_ci moduleName = "hi3516_mmc_driver"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry. 146e41f4b71Sopenharmony_ci serviceName = "HDF_PLATFORM_MMC_0"; // (Mandatory) Unique name of the service published by the driver. 147e41f4b71Sopenharmony_ci deviceMatchAttr = "hi3516_mmc_emmc"; // (Mandatory) Private data of the controller. The value must be the same as the controller information in mmc_config.hcs. 148e41f4b71Sopenharmony_ci } 149e41f4b71Sopenharmony_ci device1 :: deviceNode { 150e41f4b71Sopenharmony_ci policy = 1; 151e41f4b71Sopenharmony_ci priority = 20; 152e41f4b71Sopenharmony_ci permission = 0644; 153e41f4b71Sopenharmony_ci moduleName = "hi3516_mmc_driver"; 154e41f4b71Sopenharmony_ci serviceName = "HDF_PLATFORM_MMC_1"; 155e41f4b71Sopenharmony_ci deviceMatchAttr = "hi3516_mmc_sd"; // The MMC is an SD card. 156e41f4b71Sopenharmony_ci } 157e41f4b71Sopenharmony_ci device2 :: deviceNode { 158e41f4b71Sopenharmony_ci policy = 1; 159e41f4b71Sopenharmony_ci priority = 30; 160e41f4b71Sopenharmony_ci permission = 0644; 161e41f4b71Sopenharmony_ci moduleName = "hi3516_mmc_driver"; 162e41f4b71Sopenharmony_ci serviceName = "HDF_PLATFORM_MMC_2"; 163e41f4b71Sopenharmony_ci deviceMatchAttr = "hi3516_mmc_sdio"; // The MMC is an SDIO card. 164e41f4b71Sopenharmony_ci } 165e41f4b71Sopenharmony_ci ... 166e41f4b71Sopenharmony_ci } 167e41f4b71Sopenharmony_ci } 168e41f4b71Sopenharmony_ci } 169e41f4b71Sopenharmony_ci } 170e41f4b71Sopenharmony_ci ``` 171e41f4b71Sopenharmony_ci 172e41f4b71Sopenharmony_ci - **mmc_config.hcs** example 173e41f4b71Sopenharmony_ci 174e41f4b71Sopenharmony_ci Configure the device attributes in the **//device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/mmc/mmc_config.hcs** file. The parameters are as follows: 175e41f4b71Sopenharmony_ci 176e41f4b71Sopenharmony_ci ```c 177e41f4b71Sopenharmony_ci root { 178e41f4b71Sopenharmony_ci platform { 179e41f4b71Sopenharmony_ci mmc_config { 180e41f4b71Sopenharmony_ci template mmc_controller { // Template configuration. If the template is used to configure device node information, the default values in the template will be used for the fields that are not declared for the node. 181e41f4b71Sopenharmony_ci match_attr = ""; 182e41f4b71Sopenharmony_ci voltDef = 0; // MMC default voltage. The value 0 stands for 3.3 V, 1 for 1.8 V, and 2 for 1.2 V. 183e41f4b71Sopenharmony_ci freqMin = 50000; // (Mandatory) Minimum frequency. 184e41f4b71Sopenharmony_ci freqMax = 100000000; // (Mandatory) Maximum frequency. 185e41f4b71Sopenharmony_ci freqDef = 400000; // (Mandatory) Default frequency. 186e41f4b71Sopenharmony_ci maxBlkNum = 2048; // (Mandatory) Maximum block number. 187e41f4b71Sopenharmony_ci maxBlkSize = 512; // (Mandatory) Maximum block size. 188e41f4b71Sopenharmony_ci ocrDef = 0x300000; // (Mandatory) working voltage. 189e41f4b71Sopenharmony_ci caps2 = 0; // (Mandatory) Attribute register. For details, see MmcCaps2 in mmc_caps.h. 190e41f4b71Sopenharmony_ci regSize = 0x118; // (Mandatory) Register size. 191e41f4b71Sopenharmony_ci hostId = 0; // (Mandatory) Host number. 192e41f4b71Sopenharmony_ci regBasePhy = 0x10020000; // (Mandatory) Physical base address of the register. 193e41f4b71Sopenharmony_ci irqNum = 63; // (Mandatory) IRQ number. 194e41f4b71Sopenharmony_ci devType = 2; // (Mandatory) Device type, which can be eMMC, SD, SDIO, or COMBO. 195e41f4b71Sopenharmony_ci caps = 0x0001e045; // (Mandatory) Attribute register. For details, see MmcCaps in mmc_caps.h. 196e41f4b71Sopenharmony_ci } 197e41f4b71Sopenharmony_ci controller_0x10100000 :: mmc_controller { 198e41f4b71Sopenharmony_ci match_attr = "hi3516_mmc_emmc"; // (Mandatory) The value must be the same as deviceMatchAttr in device_info.hcs. 199e41f4b71Sopenharmony_ci hostId = 0; 200e41f4b71Sopenharmony_ci regBasePhy = 0x10100000; 201e41f4b71Sopenharmony_ci irqNum = 96; 202e41f4b71Sopenharmony_ci devType = 0; // The device is an eMMC card. 203e41f4b71Sopenharmony_ci caps = 0xd001e045; 204e41f4b71Sopenharmony_ci caps2 = 0x60; 205e41f4b71Sopenharmony_ci } 206e41f4b71Sopenharmony_ci controller_0x100f0000 :: mmc_controller { 207e41f4b71Sopenharmony_ci match_attr = "hi3516_mmc_sd"; 208e41f4b71Sopenharmony_ci hostId = 1; 209e41f4b71Sopenharmony_ci regBasePhy = 0x100f0000; 210e41f4b71Sopenharmony_ci irqNum = 62; 211e41f4b71Sopenharmony_ci devType = 1; // The device is an SD card. 212e41f4b71Sopenharmony_ci caps = 0xd001e005; 213e41f4b71Sopenharmony_ci } 214e41f4b71Sopenharmony_ci controller_0x10020000 :: mmc_controller { 215e41f4b71Sopenharmony_ci match_attr = "hi3516_mmc_sdio"; 216e41f4b71Sopenharmony_ci hostId = 2; 217e41f4b71Sopenharmony_ci regBasePhy = 0x10020000; 218e41f4b71Sopenharmony_ci irqNum = 63; 219e41f4b71Sopenharmony_ci devType = 2; // The device is an SDIO card. 220e41f4b71Sopenharmony_ci caps = 0x0001e04d; 221e41f4b71Sopenharmony_ci } 222e41f4b71Sopenharmony_ci } 223e41f4b71Sopenharmony_ci } 224e41f4b71Sopenharmony_ci } 225e41f4b71Sopenharmony_ci ``` 226e41f4b71Sopenharmony_ci 227e41f4b71Sopenharmony_ci After the **mmc_config.hcs** file is configured, include the file in the **hdf.hcs** file. Otherwise, the configuration file cannot take effect. 228e41f4b71Sopenharmony_ci 229e41f4b71Sopenharmony_ci ```c 230e41f4b71Sopenharmony_ci #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/mmc/mmc_config.hcs" // Relative path of the file. 231e41f4b71Sopenharmony_ci ``` 232e41f4b71Sopenharmony_ci 233e41f4b71Sopenharmony_ci3. Instantiate the MMC controller object. 234e41f4b71Sopenharmony_ci 235e41f4b71Sopenharmony_ci Initialize the **MmcCntlr** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init** and **Release**) to instantiate **MmcCntlrOps** in **MmcCntlr** (so that the underlying driver functions can be called). 236e41f4b71Sopenharmony_ci 237e41f4b71Sopenharmony_ci - Define a custom structure. 238e41f4b71Sopenharmony_ci 239e41f4b71Sopenharmony_ci To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **mmc_config.hcs** file to initialize the members in the custom structure and passes important parameters to the **MmcCntlr** object at the core layer. 240e41f4b71Sopenharmony_ci 241e41f4b71Sopenharmony_ci ```c 242e41f4b71Sopenharmony_ci struct HimciHost { 243e41f4b71Sopenharmony_ci struct MmcCntlr *mmc; // (Mandatory) Core layer control object. 244e41f4b71Sopenharmony_ci struct MmcCmd *cmd // (Mandatory) Core layer structure used to pass commands. For details about related commands, see MmcCmdCode. 245e41f4b71Sopenharmony_ci void *base; // Register base address used for address mapping. 246e41f4b71Sopenharmony_ci enum HimciPowerStatus powerStatus; 247e41f4b71Sopenharmony_ci uint8_t *alignedBuff; 248e41f4b71Sopenharmony_ci uint32_t buffLen; 249e41f4b71Sopenharmony_ci struct scatterlist dmaSg; 250e41f4b71Sopenharmony_ci struct scatterlist *sg; 251e41f4b71Sopenharmony_ci uint32_t dmaSgNum; 252e41f4b71Sopenharmony_ci DMA_ADDR_T dmaPaddr; 253e41f4b71Sopenharmony_ci uint32_t *dmaVaddr; 254e41f4b71Sopenharmony_ci uint32_t irqNum; 255e41f4b71Sopenharmony_ci bool isTuning; 256e41f4b71Sopenharmony_ci uint32_t id; 257e41f4b71Sopenharmony_ci struct OsalMutex mutex; 258e41f4b71Sopenharmony_ci bool waitForEvent; 259e41f4b71Sopenharmony_ci HIMCI_EVENT himciEvent; 260e41f4b71Sopenharmony_ci }; 261e41f4b71Sopenharmony_ci // MmcCntlr is the core layer controller structure. The Bind function assigns values to the members of MmcCntlr. 262e41f4b71Sopenharmony_ci struct MmcCntlr { 263e41f4b71Sopenharmony_ci struct IDeviceIoService service; 264e41f4b71Sopenharmony_ci struct HdfDeviceObject *hdfDevObj; 265e41f4b71Sopenharmony_ci struct PlatformDevice device; 266e41f4b71Sopenharmony_ci struct OsalMutex mutex; 267e41f4b71Sopenharmony_ci struct OsalSem released; 268e41f4b71Sopenharmony_ci uint32_t devType; 269e41f4b71Sopenharmony_ci struct MmcDevice *curDev; 270e41f4b71Sopenharmony_ci struct MmcCntlrOps *ops; 271e41f4b71Sopenharmony_ci struct PlatformQueue *msgQueue; 272e41f4b71Sopenharmony_ci uint16_t index; 273e41f4b71Sopenharmony_ci uint16_t voltDef; 274e41f4b71Sopenharmony_ci uint32_t vddBit; 275e41f4b71Sopenharmony_ci uint32_t freqMin; 276e41f4b71Sopenharmony_ci uint32_t freqMax; 277e41f4b71Sopenharmony_ci uint32_t freqDef; 278e41f4b71Sopenharmony_ci union MmcOcr ocrDef; 279e41f4b71Sopenharmony_ci union MmcCaps caps; 280e41f4b71Sopenharmony_ci union MmcCaps2 caps2; 281e41f4b71Sopenharmony_ci uint32_t maxBlkNum; 282e41f4b71Sopenharmony_ci uint32_t maxBlkSize; 283e41f4b71Sopenharmony_ci uint32_t maxReqSize; 284e41f4b71Sopenharmony_ci bool devPlugged; 285e41f4b71Sopenharmony_ci bool detecting; 286e41f4b71Sopenharmony_ci void *priv; 287e41f4b71Sopenharmony_ci }; 288e41f4b71Sopenharmony_ci ``` 289e41f4b71Sopenharmony_ci 290e41f4b71Sopenharmony_ci - Instantiate **MmcCntlrOps** in **MmcCntlr**. 291e41f4b71Sopenharmony_ci 292e41f4b71Sopenharmony_ci ```c 293e41f4b71Sopenharmony_ci static struct MmcCntlrOps g_himciHostOps = { 294e41f4b71Sopenharmony_ci .request = HimciDoRequest, 295e41f4b71Sopenharmony_ci .setClock = HimciSetClock, 296e41f4b71Sopenharmony_ci .setPowerMode = HimciSetPowerMode, 297e41f4b71Sopenharmony_ci .setBusWidth = HimciSetBusWidth, 298e41f4b71Sopenharmony_ci .setBusTiming = HimciSetBusTiming, 299e41f4b71Sopenharmony_ci .setSdioIrq = HimciSetSdioIrq, 300e41f4b71Sopenharmony_ci .hardwareReset = HimciHardwareReset, 301e41f4b71Sopenharmony_ci .systemInit = HimciSystemInit, 302e41f4b71Sopenharmony_ci .setEnhanceStrobe = HimciSetEnhanceStrobe, 303e41f4b71Sopenharmony_ci .switchVoltage = HimciSwitchVoltage, 304e41f4b71Sopenharmony_ci .devReadOnly = HimciDevReadOnly, 305e41f4b71Sopenharmony_ci .devPlugged = HimciCardPlugged, 306e41f4b71Sopenharmony_ci .devBusy = HimciDevBusy, 307e41f4b71Sopenharmony_ci .tune = HimciTune, 308e41f4b71Sopenharmony_ci .rescanSdioDev = HimciRescanSdioDev, 309e41f4b71Sopenharmony_ci }; 310e41f4b71Sopenharmony_ci ``` 311e41f4b71Sopenharmony_ci 312e41f4b71Sopenharmony_ci - Implement the **Bind** function. 313e41f4b71Sopenharmony_ci 314e41f4b71Sopenharmony_ci **Input parameter**: 315e41f4b71Sopenharmony_ci 316e41f4b71Sopenharmony_ci **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs. 317e41f4b71Sopenharmony_ci 318e41f4b71Sopenharmony_ci **Return value**: 319e41f4b71Sopenharmony_ci 320e41f4b71Sopenharmony_ci **HDF_STATUS**<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **//drivers/hdf_core/framework/include/utils/hdf_base.h** file. 321e41f4b71Sopenharmony_ci 322e41f4b71Sopenharmony_ci **Table 2** HDF_STATUS description 323e41f4b71Sopenharmony_ci 324e41f4b71Sopenharmony_ci | Status| Description| 325e41f4b71Sopenharmony_ci | -------- | -------- | 326e41f4b71Sopenharmony_ci | HDF_ERR_INVALID_OBJECT | Invalid controller object.| 327e41f4b71Sopenharmony_ci | HDF_ERR_MALLOC_FAIL | Failed to allocate memory.| 328e41f4b71Sopenharmony_ci | HDF_ERR_INVALID_PARAM | Invalid parameter.| 329e41f4b71Sopenharmony_ci | HDF_ERR_IO | I/O error.| 330e41f4b71Sopenharmony_ci | HDF_SUCCESS | Initialization successful.| 331e41f4b71Sopenharmony_ci | HDF_FAILURE | Initialization failed.| 332e41f4b71Sopenharmony_ci 333e41f4b71Sopenharmony_ci **Function description**: 334e41f4b71Sopenharmony_ci 335e41f4b71Sopenharmony_ci Initializes the **HimciHost** object and **MmcCntlr**, and calls the **MmcCntlrAdd** function at the core layer to add the MMC controllers. 336e41f4b71Sopenharmony_ci 337e41f4b71Sopenharmony_ci ```c 338e41f4b71Sopenharmony_ci static int32_t HimciMmcBind(struct HdfDeviceObject *obj) 339e41f4b71Sopenharmony_ci { 340e41f4b71Sopenharmony_ci struct MmcCntlr *cntlr = NULL; 341e41f4b71Sopenharmony_ci struct HimciHost *host = NULL; 342e41f4b71Sopenharmony_ci int32_t ret; 343e41f4b71Sopenharmony_ci cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr)); 344e41f4b71Sopenharmony_ci host = (struct HimciHost *)OsalMemCalloc(sizeof(struct HimciHost)); 345e41f4b71Sopenharmony_ci 346e41f4b71Sopenharmony_ci host->mmc = cntlr; // (Mandatory) Prerequisites for conversion between HimciHost and MmcCntlr. 347e41f4b71Sopenharmony_ci cntlr->priv = (void *)host; // (Mandatory) Prerequisites for conversion between HimciHost and MmcCntlr. 348e41f4b71Sopenharmony_ci cntlr->ops = &g_himciHostOps; // (Mandatory) Attach the MmcCntlrOps instance to MmcCntlr. 349e41f4b71Sopenharmony_ci cntlr->hdfDevObj = obj; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr. 350e41f4b71Sopenharmony_ci obj->service = &cntlr->service; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr. 351e41f4b71Sopenharmony_ci ret = MmcCntlrParse(cntlr, obj); // (Mandatory) Initialize MmcCntlr. If the initialization fails, execute goto _ERR. 352e41f4b71Sopenharmony_ci ... 353e41f4b71Sopenharmony_ci ret = HimciHostParse(host, obj); // (Mandatory) Initialize HimciHost. If the initialization fails, execute goto _ERR. 354e41f4b71Sopenharmony_ci ... 355e41f4b71Sopenharmony_ci ret = HimciHostInit(host, cntlr); // Customized initizlization. If the initialization fails, goto _ERR. 356e41f4b71Sopenharmony_ci ... 357e41f4b71Sopenharmony_ci ret = MmcCntlrAdd(cntlr); // Call MmcCntlrAdd at the core layer. If the operation fails, execute goto _ERR. 358e41f4b71Sopenharmony_ci ... 359e41f4b71Sopenharmony_ci (void)MmcCntlrAddDetectMsgToQueue(cntlr); // Add the card detection message to the queue. 360e41f4b71Sopenharmony_ci HDF_LOGD("HimciMmcBind: success."); 361e41f4b71Sopenharmony_ci return HDF_SUCCESS; 362e41f4b71Sopenharmony_ci ERR: 363e41f4b71Sopenharmony_ci HimciDeleteHost(host); 364e41f4b71Sopenharmony_ci HDF_LOGD("HimciMmcBind: fail, err = %d.", ret); 365e41f4b71Sopenharmony_ci return ret; 366e41f4b71Sopenharmony_ci } 367e41f4b71Sopenharmony_ci ``` 368e41f4b71Sopenharmony_ci 369e41f4b71Sopenharmony_ci - Implement the **Init** function. 370e41f4b71Sopenharmony_ci 371e41f4b71Sopenharmony_ci **Input parameter**: 372e41f4b71Sopenharmony_ci 373e41f4b71Sopenharmony_ci **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs. 374e41f4b71Sopenharmony_ci 375e41f4b71Sopenharmony_ci **Return value**: 376e41f4b71Sopenharmony_ci 377e41f4b71Sopenharmony_ci HDF_STATUS 378e41f4b71Sopenharmony_ci 379e41f4b71Sopenharmony_ci **Function description**: 380e41f4b71Sopenharmony_ci 381e41f4b71Sopenharmony_ci Implements **ProcMciInit**. 382e41f4b71Sopenharmony_ci 383e41f4b71Sopenharmony_ci ```c 384e41f4b71Sopenharmony_ci static int32_t HimciMmcInit(struct HdfDeviceObject *obj) 385e41f4b71Sopenharmony_ci { 386e41f4b71Sopenharmony_ci static bool procInit = false; 387e41f4b71Sopenharmony_ci (void)obj; 388e41f4b71Sopenharmony_ci if (procInit == false) { 389e41f4b71Sopenharmony_ci if (ProcMciInit() == HDF_SUCCESS) { 390e41f4b71Sopenharmony_ci procInit = true; 391e41f4b71Sopenharmony_ci HDF_LOGD("HimciMmcInit: proc init success."); 392e41f4b71Sopenharmony_ci } 393e41f4b71Sopenharmony_ci } 394e41f4b71Sopenharmony_ci HDF_LOGD("HimciMmcInit: success."); 395e41f4b71Sopenharmony_ci return HDF_SUCCESS; 396e41f4b71Sopenharmony_ci } 397e41f4b71Sopenharmony_ci ``` 398e41f4b71Sopenharmony_ci 399e41f4b71Sopenharmony_ci - Implement the **Release** function. 400e41f4b71Sopenharmony_ci 401e41f4b71Sopenharmony_ci **Input parameter**: 402e41f4b71Sopenharmony_ci 403e41f4b71Sopenharmony_ci **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs. 404e41f4b71Sopenharmony_ci 405e41f4b71Sopenharmony_ci **Return value**: 406e41f4b71Sopenharmony_ci 407e41f4b71Sopenharmony_ci No value is returned. 408e41f4b71Sopenharmony_ci 409e41f4b71Sopenharmony_ci **Function description**: 410e41f4b71Sopenharmony_ci 411e41f4b71Sopenharmony_ci Releases the memory and deletes the controller. This function assigns values to **Release()** in the driver entry structure. If the HDF fails to call **Init()** to initialize the driver, **Release()** is called to release driver resources. 412e41f4b71Sopenharmony_ci 413e41f4b71Sopenharmony_ci >  **NOTE**<br> 414e41f4b71Sopenharmony_ci > All forced conversion operations for obtaining the corresponding object can be successful only when **Init()** has the corresponding value assignment operations. 415e41f4b71Sopenharmony_ci 416e41f4b71Sopenharmony_ci ```c 417e41f4b71Sopenharmony_ci static void HimciMmcRelease(struct HdfDeviceObject *obj) 418e41f4b71Sopenharmony_ci { 419e41f4b71Sopenharmony_ci struct MmcCntlr *cntlr = NULL; 420e41f4b71Sopenharmony_ci ... 421e41f4b71Sopenharmony_ci cntlr = (struct MmcCntlr *)obj->service; // Forcibly convert HdfDeviceObject to MmcCntlr by using service. For details about the value assignment, see the Bind function. 422e41f4b71Sopenharmony_ci ... 423e41f4b71Sopenharmony_ci HimciDeleteHost((struct HimciHost *)cntlr->priv); // Memory release function customized. Forced conversion between MmcCntlr and HimciHost is involved. 424e41f4b71Sopenharmony_ci } 425e41f4b71Sopenharmony_ci ``` 426e41f4b71Sopenharmony_ci 427e41f4b71Sopenharmony_ci4. Debug the driver. 428e41f4b71Sopenharmony_ci 429e41f4b71Sopenharmony_ci (Optional) For new drivers, verify basic functions, for example, check the information returned after the driver is attached and whether data is successfully transmitted. 430