• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  *    conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *    of conditions and the following disclaimer in the documentation and/or other materials
12  *    provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15  *    to endorse or promote products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "disk.h"
32 #include "fs/fs.h"
33 #include "hdf_base.h"
34 #include "hdf_log.h"
35 #include "mmc_block.h"
36 #include "mmc_sd.h"
37 #include "sys/ioctl.h"
38 #include "user_copy.h"
39 
40 #define HDF_LOG_TAG mmc_block_lite_c
41 
42 /* block ioctl */
43 #define MMC_IOC_MAGIC   'm'
44 #define RT_DEVICE_CTRL_BLK_GETGEOME _IOR(MMC_IOC_MAGIC, 1, struct RtDeviceBlkGeometry)
45 #define RT_DEVICE_CARD_STATUS       _IOR(MMC_IOC_MAGIC, 2, int)
46 #define RT_DEVICE_CARD_AU_SIZE      _IOR(MMC_IOC_MAGIC, 3, unsigned int)
47 #define RT_DEVICE_BLOCK_ERROR_COUNT _IOR(MMC_IOC_MAGIC, 4, int)
48 
49 #define RT_BLOCK_SIZE 512
50 
51 /**
52  * block device geometry structure
53  */
54 struct RtDeviceBlkGeometry {
55     unsigned long sectorCount;        /**< count of sectors */
56     unsigned long bytesPerSector;     /**< number of bytes per sector */
57     unsigned long blockSize;          /**< number of bytes to erase one block */
58 };
59 
60 struct disk_divide_info g_emmcInfo = {.sector_count = 0xffffffff};
61 
62 #ifdef LOSCFG_STORAGE_EMMC
StorageBlockGetEmmc(void)63 struct disk_divide_info *StorageBlockGetEmmc(void)
64 {
65     return &g_emmcInfo;
66 }
67 #endif
68 
StorageBlockGetEmmcNodeName(void * block)69 char *StorageBlockGetEmmcNodeName(void *block)
70 {
71     struct MmcBlock *mb = (struct MmcBlock *)block;
72 
73     if (mb == NULL) {
74         return NULL;
75     }
76     return mb->name;
77 }
78 
LiteosBlockOpen(FAR struct Vnode * vnode)79 static int LiteosBlockOpen(FAR struct Vnode *vnode)
80 {
81     (void)vnode;
82     return 0;
83 }
84 
LiteosBlockClose(FAR struct Vnode * vnode)85 static int LiteosBlockClose(FAR struct Vnode *vnode)
86 {
87     (void)vnode;
88     return 0;
89 }
90 
LiteosBlockRead(FAR struct Vnode * vnode,FAR unsigned char * buf,unsigned long long secStart,unsigned int nSecs)91 static ssize_t LiteosBlockRead(FAR struct Vnode *vnode, FAR unsigned char *buf,
92     unsigned long long secStart, unsigned int nSecs)
93 {
94     size_t max = (size_t)(-1);
95     struct MmcBlock *mb = (struct MmcBlock *)((struct drv_data*)vnode->data)->priv;
96 
97     if (secStart >= max || nSecs >= max) {
98         return HDF_ERR_INVALID_PARAM;
99     }
100     if (mb == NULL) {
101         HDF_LOGE("%s: mmc block is null", __func__);
102         return HDF_ERR_INVALID_OBJECT;
103     }
104 
105     return MmcDeviceRead(mb->mmc, buf, (size_t)secStart, (size_t)nSecs);
106 }
107 
LiteosBlockWrite(FAR struct Vnode * vnode,FAR const unsigned char * buf,unsigned long long secStart,unsigned int nSecs)108 static ssize_t LiteosBlockWrite(FAR struct Vnode *vnode, FAR const unsigned char *buf,
109     unsigned long long secStart, unsigned int nSecs)
110 {
111     size_t max = (size_t)(-1);
112     struct MmcBlock *mb = (struct MmcBlock *)((struct drv_data*)vnode->data)->priv;
113 
114     if (secStart >= max || nSecs >= max) {
115         return HDF_ERR_INVALID_PARAM;
116     }
117     if (mb == NULL) {
118         HDF_LOGE("%s: mmc block is null", __func__);
119         return HDF_ERR_INVALID_OBJECT;
120     }
121 
122     return MmcDeviceWrite(mb->mmc, (uint8_t *)buf, (size_t)secStart, (size_t)nSecs);
123 }
124 
LiteosBlockGeometry(FAR struct Vnode * vnode,FAR struct geometry * geometry)125 static int LiteosBlockGeometry(FAR struct Vnode *vnode, FAR struct geometry *geometry)
126 {
127     struct MmcBlock *mb = (struct MmcBlock *)((struct drv_data*)vnode->data)->priv;
128 
129     if (mb == NULL) {
130         return HDF_ERR_INVALID_OBJECT;
131     }
132     if (geometry == NULL) {
133         return HDF_ERR_INVALID_PARAM;
134     }
135     geometry->geo_available    = true;
136     geometry->geo_mediachanged = false;
137     geometry->geo_writeenabled = true;
138     geometry->geo_nsectors = mb->capacity; /* MmcDevice sized by sectors */
139     geometry->geo_sectorsize = mb->secSize;
140     return HDF_SUCCESS;
141 }
142 
LiteosBlockSaveGeometry(FAR struct Vnode * vnode,unsigned long arg)143 static int32_t LiteosBlockSaveGeometry(FAR struct Vnode *vnode, unsigned long arg)
144 {
145     int32_t ret;
146     struct geometry gm;
147     struct RtDeviceBlkGeometry rtGeo = {0};
148 
149     ret = LiteosBlockGeometry(vnode, &gm);
150     if (ret != HDF_SUCCESS) {
151         return ret;
152     }
153     rtGeo.sectorCount = gm.geo_nsectors;
154     rtGeo.bytesPerSector = gm.geo_sectorsize;
155     rtGeo.blockSize = RT_BLOCK_SIZE;
156     ret = LOS_CopyFromKernel((void *)(uintptr_t)arg, sizeof(struct RtDeviceBlkGeometry),
157               &rtGeo, sizeof(struct RtDeviceBlkGeometry));
158     if (ret != 0) {
159         return HDF_ERR_IO;
160     }
161     return HDF_SUCCESS;
162 }
163 
MmcBlockGetAuSize(struct MmcBlock * mb,uint32_t * auSize)164 static int32_t MmcBlockGetAuSize(struct MmcBlock *mb, uint32_t *auSize)
165 {
166     struct MmcDevice *mmc = NULL;
167     struct SdDevice *sd = NULL;
168 
169     if (mb == NULL || mb->mmc == NULL) {
170         HDF_LOGE("%s: mmc block or device is null", __func__);
171         return HDF_ERR_INVALID_OBJECT;
172     }
173 
174     mmc = (struct MmcDevice *)mb->mmc;
175     if (mmc->type != MMC_DEV_SD) {
176         HDF_LOGE("%s: media is not sd", __func__);
177         return HDF_ERR_NOT_SUPPORT;
178     }
179     sd = (struct SdDevice *)mmc;
180 
181     *auSize = sd->reg.ssr.auSize;
182     return HDF_SUCCESS;
183 }
184 
LiteosBlockIoctl(FAR struct Vnode * vnode,int cmd,unsigned long arg)185 static int32_t LiteosBlockIoctl(FAR struct Vnode *vnode, int cmd, unsigned long arg)
186 {
187     int32_t ret;
188     int flag, errCnt;
189     unsigned int au;
190     uint32_t auSize;
191     struct MmcBlock *mb = NULL;
192 
193     mb = (struct MmcBlock *)((struct drv_data*)vnode->data)->priv;
194 
195     switch (cmd) {
196         case RT_DEVICE_CTRL_BLK_GETGEOME:
197             ret = LiteosBlockSaveGeometry(vnode, arg);
198             break;
199         case RT_DEVICE_CARD_STATUS:
200             flag = (MmcDeviceIsPresent(mb->mmc)) ? 1 : 0;
201             ret = LOS_CopyFromKernel((void *)(uintptr_t)arg, sizeof(int), &flag, sizeof(int));
202             if (ret) {
203                 ret = HDF_ERR_IO;
204             }
205             break;
206         case RT_DEVICE_CARD_AU_SIZE:
207             ret = MmcBlockGetAuSize(mb, &auSize);
208             if (ret == HDF_SUCCESS) {
209                 au = (unsigned int)auSize;
210                 ret = LOS_CopyFromKernel((void *)(uintptr_t)arg, sizeof(au), &au, sizeof(au));
211                 if (ret) {
212                     ret = HDF_ERR_IO;
213                 }
214             }
215             break;
216         case RT_DEVICE_BLOCK_ERROR_COUNT:
217             errCnt = (int)mb->errCnt;
218             ret = LOS_CopyFromKernel((void *)(uintptr_t)arg, sizeof(int), &errCnt,
219                       sizeof(int));
220             if (ret) {
221                 ret = HDF_ERR_IO;
222             }
223             break;
224         default:
225             ret = HDF_ERR_NOT_SUPPORT;
226             break;
227     }
228 
229     return ret;
230 }
231 
232 static struct block_operations g_blockOps = {
233     .open = LiteosBlockOpen,
234     .close = LiteosBlockClose,
235     .read = LiteosBlockRead,
236     .write = LiteosBlockWrite,
237     .geometry = LiteosBlockGeometry,
238     .ioctl = LiteosBlockIoctl,
239 };
240 
StorageBlockGetMmcOps(void)241 struct block_operations *StorageBlockGetMmcOps(void)
242 {
243     return &g_blockOps;
244 }
245 
246 static struct MmcBlock *g_diskIdTable[SYS_MAX_DISK] = { };
247 
MmcBlockOsInit(struct MmcDevice * mmcDevice)248 int32_t MmcBlockOsInit(struct MmcDevice *mmcDevice)
249 {
250     int32_t ret;
251     int32_t diskId;
252     struct disk_divide_info *info = NULL;
253     struct MmcBlock *mb = NULL;
254 
255     if (mmcDevice == NULL || mmcDevice->mb == NULL) {
256         return HDF_ERR_INVALID_OBJECT;
257     }
258     mb = mmcDevice->mb;
259 
260     if (mb->name[0] == '\0') {
261         HDF_LOGE("%s: mmc block name invalid", __func__);
262         return HDF_ERR_INVALID_OBJECT;
263     }
264 
265     diskId = los_alloc_diskid_byname(mb->name);
266     if (!mb->removeable) {
267         info = &g_emmcInfo;
268         info->sector_count = mb->capacity;
269     }
270 
271     ret = los_disk_init(mb->name, &g_blockOps, (void *)mb, diskId, info);
272     if (ret != ENOERR) {
273         HDF_LOGE("%s: los_disk_init fail:%d", __func__, ret);
274         return ret;
275     }
276 
277     mb->osData = get_disk(diskId);
278     if (mb->osData == NULL) {
279         HDF_LOGE("%s: los_disk_init fail:%d", __func__, ret);
280         return HDF_PLT_ERR_OS_API;
281     }
282 
283     if (diskId >= 0 && diskId < SYS_MAX_DISK) {
284         g_diskIdTable[diskId] = mb;
285     }
286 
287     return HDF_SUCCESS;
288 }
289 
MmcBlockOsUninit(struct MmcDevice * mmcDevice)290 void MmcBlockOsUninit(struct MmcDevice *mmcDevice)
291 {
292     int diskId;
293     struct MmcBlock *mb = NULL;
294 
295     if (mmcDevice == NULL || mmcDevice->mb == NULL) {
296         return;
297     }
298     mb = mmcDevice->mb;
299 
300     diskId = los_get_diskid_byname(mb->name);
301     (void)los_disk_deinit(diskId);
302 
303     if (diskId >= 0 && diskId < SYS_MAX_DISK) {
304         g_diskIdTable[diskId] = NULL;
305     }
306 }
307 
MmcBlockFromDiskId(int32_t diskId)308 struct MmcBlock *MmcBlockFromDiskId(int32_t diskId)
309 {
310     if (diskId >= 0 && diskId < SYS_MAX_DISK) {
311         return g_diskIdTable[diskId];
312     }
313     return NULL;
314 }
315 
StorageBlockMmcErase(uint32_t diskId,size_t secStart,size_t secNr)316 ssize_t StorageBlockMmcErase(uint32_t diskId, size_t secStart, size_t secNr)
317 {
318     struct MmcBlock *mb = NULL;
319 
320     mb = MmcBlockFromDiskId((int32_t)diskId);
321     if (mb == NULL || mb->mmc == NULL) {
322         return HDF_ERR_INVALID_PARAM;
323     }
324     return MmcDeviceErase(mb->mmc, secStart, secNr);
325 }
326