xref: /nrf52832-nimble/rt-thread/components/drivers/sdio/block_dev.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero  *
4*10465441SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero  *
6*10465441SEvalZero  * Change Logs:
7*10465441SEvalZero  * Date           Author        Notes
8*10465441SEvalZero  * 2011-07-25     weety     first version
9*10465441SEvalZero  */
10*10465441SEvalZero 
11*10465441SEvalZero #include <rtthread.h>
12*10465441SEvalZero #include <dfs_fs.h>
13*10465441SEvalZero 
14*10465441SEvalZero #include <drivers/mmcsd_core.h>
15*10465441SEvalZero 
16*10465441SEvalZero #define DBG_ENABLE
17*10465441SEvalZero #define DBG_SECTION_NAME               "SDIO"
18*10465441SEvalZero #ifdef RT_SDIO_DEBUG
19*10465441SEvalZero #define DBG_LEVEL                      DBG_LOG
20*10465441SEvalZero #else
21*10465441SEvalZero #define DBG_LEVEL                      DBG_INFO
22*10465441SEvalZero #endif /* RT_SDIO_DEBUG */
23*10465441SEvalZero #define DBG_COLOR
24*10465441SEvalZero #include <rtdbg.h>
25*10465441SEvalZero 
26*10465441SEvalZero static rt_list_t blk_devices = RT_LIST_OBJECT_INIT(blk_devices);
27*10465441SEvalZero 
28*10465441SEvalZero #define BLK_MIN(a, b) ((a) < (b) ? (a) : (b))
29*10465441SEvalZero 
30*10465441SEvalZero struct mmcsd_blk_device
31*10465441SEvalZero {
32*10465441SEvalZero     struct rt_mmcsd_card *card;
33*10465441SEvalZero     rt_list_t list;
34*10465441SEvalZero     struct rt_device dev;
35*10465441SEvalZero     struct dfs_partition part;
36*10465441SEvalZero     struct rt_device_blk_geometry geometry;
37*10465441SEvalZero     rt_size_t max_req_size;
38*10465441SEvalZero };
39*10465441SEvalZero 
40*10465441SEvalZero #ifndef RT_MMCSD_MAX_PARTITION
41*10465441SEvalZero #define RT_MMCSD_MAX_PARTITION 16
42*10465441SEvalZero #endif
43*10465441SEvalZero 
mmcsd_num_wr_blocks(struct rt_mmcsd_card * card)44*10465441SEvalZero rt_int32_t mmcsd_num_wr_blocks(struct rt_mmcsd_card *card)
45*10465441SEvalZero {
46*10465441SEvalZero     rt_int32_t err;
47*10465441SEvalZero     rt_uint32_t blocks;
48*10465441SEvalZero 
49*10465441SEvalZero     struct rt_mmcsd_req req;
50*10465441SEvalZero     struct rt_mmcsd_cmd cmd;
51*10465441SEvalZero     struct rt_mmcsd_data data;
52*10465441SEvalZero     rt_uint32_t timeout_us;
53*10465441SEvalZero 
54*10465441SEvalZero     rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd));
55*10465441SEvalZero 
56*10465441SEvalZero     cmd.cmd_code = APP_CMD;
57*10465441SEvalZero     cmd.arg = card->rca << 16;
58*10465441SEvalZero     cmd.flags = RESP_SPI_R1 | RESP_R1 | CMD_AC;
59*10465441SEvalZero 
60*10465441SEvalZero     err = mmcsd_send_cmd(card->host, &cmd, 0);
61*10465441SEvalZero     if (err)
62*10465441SEvalZero         return -RT_ERROR;
63*10465441SEvalZero     if (!controller_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
64*10465441SEvalZero         return -RT_ERROR;
65*10465441SEvalZero 
66*10465441SEvalZero     rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd));
67*10465441SEvalZero 
68*10465441SEvalZero     cmd.cmd_code = SD_APP_SEND_NUM_WR_BLKS;
69*10465441SEvalZero     cmd.arg = 0;
70*10465441SEvalZero     cmd.flags = RESP_SPI_R1 | RESP_R1 | CMD_ADTC;
71*10465441SEvalZero 
72*10465441SEvalZero     rt_memset(&data, 0, sizeof(struct rt_mmcsd_data));
73*10465441SEvalZero 
74*10465441SEvalZero     data.timeout_ns = card->tacc_ns * 100;
75*10465441SEvalZero     data.timeout_clks = card->tacc_clks * 100;
76*10465441SEvalZero 
77*10465441SEvalZero     timeout_us = data.timeout_ns / 1000;
78*10465441SEvalZero     timeout_us += data.timeout_clks * 1000 /
79*10465441SEvalZero         (card->host->io_cfg.clock / 1000);
80*10465441SEvalZero 
81*10465441SEvalZero     if (timeout_us > 100000)
82*10465441SEvalZero     {
83*10465441SEvalZero         data.timeout_ns = 100000000;
84*10465441SEvalZero         data.timeout_clks = 0;
85*10465441SEvalZero     }
86*10465441SEvalZero 
87*10465441SEvalZero     data.blksize = 4;
88*10465441SEvalZero     data.blks = 1;
89*10465441SEvalZero     data.flags = DATA_DIR_READ;
90*10465441SEvalZero     data.buf = &blocks;
91*10465441SEvalZero 
92*10465441SEvalZero     rt_memset(&req, 0, sizeof(struct rt_mmcsd_req));
93*10465441SEvalZero 
94*10465441SEvalZero     req.cmd = &cmd;
95*10465441SEvalZero     req.data = &data;
96*10465441SEvalZero 
97*10465441SEvalZero     mmcsd_send_request(card->host, &req);
98*10465441SEvalZero 
99*10465441SEvalZero     if (cmd.err || data.err)
100*10465441SEvalZero         return -RT_ERROR;
101*10465441SEvalZero 
102*10465441SEvalZero     return blocks;
103*10465441SEvalZero }
104*10465441SEvalZero 
rt_mmcsd_req_blk(struct rt_mmcsd_card * card,rt_uint32_t sector,void * buf,rt_size_t blks,rt_uint8_t dir)105*10465441SEvalZero static rt_err_t rt_mmcsd_req_blk(struct rt_mmcsd_card *card,
106*10465441SEvalZero                                  rt_uint32_t           sector,
107*10465441SEvalZero                                  void                 *buf,
108*10465441SEvalZero                                  rt_size_t             blks,
109*10465441SEvalZero                                  rt_uint8_t            dir)
110*10465441SEvalZero {
111*10465441SEvalZero     struct rt_mmcsd_cmd  cmd, stop;
112*10465441SEvalZero     struct rt_mmcsd_data  data;
113*10465441SEvalZero     struct rt_mmcsd_req  req;
114*10465441SEvalZero     struct rt_mmcsd_host *host = card->host;
115*10465441SEvalZero     rt_uint32_t r_cmd, w_cmd;
116*10465441SEvalZero 
117*10465441SEvalZero     mmcsd_host_lock(host);
118*10465441SEvalZero     rt_memset(&req, 0, sizeof(struct rt_mmcsd_req));
119*10465441SEvalZero     rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd));
120*10465441SEvalZero     rt_memset(&stop, 0, sizeof(struct rt_mmcsd_cmd));
121*10465441SEvalZero     rt_memset(&data, 0, sizeof(struct rt_mmcsd_data));
122*10465441SEvalZero     req.cmd = &cmd;
123*10465441SEvalZero     req.data = &data;
124*10465441SEvalZero 
125*10465441SEvalZero     cmd.arg = sector;
126*10465441SEvalZero     if (!(card->flags & CARD_FLAG_SDHC))
127*10465441SEvalZero     {
128*10465441SEvalZero         cmd.arg <<= 9;
129*10465441SEvalZero     }
130*10465441SEvalZero     cmd.flags = RESP_SPI_R1 | RESP_R1 | CMD_ADTC;
131*10465441SEvalZero 
132*10465441SEvalZero     data.blksize = SECTOR_SIZE;
133*10465441SEvalZero     data.blks  = blks;
134*10465441SEvalZero 
135*10465441SEvalZero     if (blks > 1)
136*10465441SEvalZero     {
137*10465441SEvalZero         if (!controller_is_spi(card->host) || !dir)
138*10465441SEvalZero         {
139*10465441SEvalZero             req.stop = &stop;
140*10465441SEvalZero             stop.cmd_code = STOP_TRANSMISSION;
141*10465441SEvalZero             stop.arg = 0;
142*10465441SEvalZero             stop.flags = RESP_SPI_R1B | RESP_R1B | CMD_AC;
143*10465441SEvalZero         }
144*10465441SEvalZero         r_cmd = READ_MULTIPLE_BLOCK;
145*10465441SEvalZero         w_cmd = WRITE_MULTIPLE_BLOCK;
146*10465441SEvalZero     }
147*10465441SEvalZero     else
148*10465441SEvalZero     {
149*10465441SEvalZero         req.stop = RT_NULL;
150*10465441SEvalZero         r_cmd = READ_SINGLE_BLOCK;
151*10465441SEvalZero         w_cmd = WRITE_BLOCK;
152*10465441SEvalZero     }
153*10465441SEvalZero 
154*10465441SEvalZero     if (!dir)
155*10465441SEvalZero     {
156*10465441SEvalZero         cmd.cmd_code = r_cmd;
157*10465441SEvalZero         data.flags |= DATA_DIR_READ;
158*10465441SEvalZero     }
159*10465441SEvalZero     else
160*10465441SEvalZero     {
161*10465441SEvalZero         cmd.cmd_code = w_cmd;
162*10465441SEvalZero         data.flags |= DATA_DIR_WRITE;
163*10465441SEvalZero     }
164*10465441SEvalZero 
165*10465441SEvalZero     mmcsd_set_data_timeout(&data, card);
166*10465441SEvalZero     data.buf = buf;
167*10465441SEvalZero     mmcsd_send_request(host, &req);
168*10465441SEvalZero 
169*10465441SEvalZero     if (!controller_is_spi(card->host) && dir != 0)
170*10465441SEvalZero     {
171*10465441SEvalZero         do
172*10465441SEvalZero         {
173*10465441SEvalZero             rt_int32_t err;
174*10465441SEvalZero 
175*10465441SEvalZero             cmd.cmd_code = SEND_STATUS;
176*10465441SEvalZero             cmd.arg = card->rca << 16;
177*10465441SEvalZero             cmd.flags = RESP_R1 | CMD_AC;
178*10465441SEvalZero             err = mmcsd_send_cmd(card->host, &cmd, 5);
179*10465441SEvalZero             if (err)
180*10465441SEvalZero             {
181*10465441SEvalZero                 LOG_E("error %d requesting status", err);
182*10465441SEvalZero                 break;
183*10465441SEvalZero             }
184*10465441SEvalZero             /*
185*10465441SEvalZero              * Some cards mishandle the status bits,
186*10465441SEvalZero              * so make sure to check both the busy
187*10465441SEvalZero              * indication and the card state.
188*10465441SEvalZero              */
189*10465441SEvalZero          } while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
190*10465441SEvalZero             (R1_CURRENT_STATE(cmd.resp[0]) == 7));
191*10465441SEvalZero     }
192*10465441SEvalZero 
193*10465441SEvalZero     mmcsd_host_unlock(host);
194*10465441SEvalZero 
195*10465441SEvalZero     if (cmd.err || data.err || stop.err)
196*10465441SEvalZero     {
197*10465441SEvalZero         LOG_E("mmcsd request blocks error");
198*10465441SEvalZero         LOG_E("%d,%d,%d, 0x%08x,0x%08x",
199*10465441SEvalZero                    cmd.err, data.err, stop.err, data.flags, sector);
200*10465441SEvalZero 
201*10465441SEvalZero         return -RT_ERROR;
202*10465441SEvalZero     }
203*10465441SEvalZero 
204*10465441SEvalZero     return RT_EOK;
205*10465441SEvalZero }
206*10465441SEvalZero 
rt_mmcsd_init(rt_device_t dev)207*10465441SEvalZero static rt_err_t rt_mmcsd_init(rt_device_t dev)
208*10465441SEvalZero {
209*10465441SEvalZero     return RT_EOK;
210*10465441SEvalZero }
211*10465441SEvalZero 
rt_mmcsd_open(rt_device_t dev,rt_uint16_t oflag)212*10465441SEvalZero static rt_err_t rt_mmcsd_open(rt_device_t dev, rt_uint16_t oflag)
213*10465441SEvalZero {
214*10465441SEvalZero     return RT_EOK;
215*10465441SEvalZero }
216*10465441SEvalZero 
rt_mmcsd_close(rt_device_t dev)217*10465441SEvalZero static rt_err_t rt_mmcsd_close(rt_device_t dev)
218*10465441SEvalZero {
219*10465441SEvalZero     return RT_EOK;
220*10465441SEvalZero }
221*10465441SEvalZero 
rt_mmcsd_control(rt_device_t dev,int cmd,void * args)222*10465441SEvalZero static rt_err_t rt_mmcsd_control(rt_device_t dev, int cmd, void *args)
223*10465441SEvalZero {
224*10465441SEvalZero     struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data;
225*10465441SEvalZero     switch (cmd)
226*10465441SEvalZero     {
227*10465441SEvalZero     case RT_DEVICE_CTRL_BLK_GETGEOME:
228*10465441SEvalZero         rt_memcpy(args, &blk_dev->geometry, sizeof(struct rt_device_blk_geometry));
229*10465441SEvalZero         break;
230*10465441SEvalZero     default:
231*10465441SEvalZero         break;
232*10465441SEvalZero     }
233*10465441SEvalZero     return RT_EOK;
234*10465441SEvalZero }
235*10465441SEvalZero 
rt_mmcsd_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)236*10465441SEvalZero static rt_size_t rt_mmcsd_read(rt_device_t dev,
237*10465441SEvalZero                                rt_off_t    pos,
238*10465441SEvalZero                                void       *buffer,
239*10465441SEvalZero                                rt_size_t   size)
240*10465441SEvalZero {
241*10465441SEvalZero     rt_err_t err = 0;
242*10465441SEvalZero     rt_size_t offset = 0;
243*10465441SEvalZero     rt_size_t req_size = 0;
244*10465441SEvalZero     rt_size_t remain_size = size;
245*10465441SEvalZero     void *rd_ptr = (void *)buffer;
246*10465441SEvalZero     struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data;
247*10465441SEvalZero     struct dfs_partition *part = &blk_dev->part;
248*10465441SEvalZero 
249*10465441SEvalZero     if (dev == RT_NULL)
250*10465441SEvalZero     {
251*10465441SEvalZero         rt_set_errno(-EINVAL);
252*10465441SEvalZero         return 0;
253*10465441SEvalZero     }
254*10465441SEvalZero 
255*10465441SEvalZero     rt_sem_take(part->lock, RT_WAITING_FOREVER);
256*10465441SEvalZero     while (remain_size)
257*10465441SEvalZero     {
258*10465441SEvalZero         req_size = (remain_size > blk_dev->max_req_size) ? blk_dev->max_req_size : remain_size;
259*10465441SEvalZero         err = rt_mmcsd_req_blk(blk_dev->card, part->offset + pos + offset, rd_ptr, req_size, 0);
260*10465441SEvalZero         if (err)
261*10465441SEvalZero             break;
262*10465441SEvalZero         offset += req_size;
263*10465441SEvalZero         rd_ptr = (void *)((rt_uint8_t *)rd_ptr + (req_size << 9));
264*10465441SEvalZero         remain_size -= req_size;
265*10465441SEvalZero     }
266*10465441SEvalZero     rt_sem_release(part->lock);
267*10465441SEvalZero 
268*10465441SEvalZero     /* the length of reading must align to SECTOR SIZE */
269*10465441SEvalZero     if (err)
270*10465441SEvalZero     {
271*10465441SEvalZero         rt_set_errno(-EIO);
272*10465441SEvalZero         return 0;
273*10465441SEvalZero     }
274*10465441SEvalZero     return size - remain_size;
275*10465441SEvalZero }
276*10465441SEvalZero 
rt_mmcsd_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)277*10465441SEvalZero static rt_size_t rt_mmcsd_write(rt_device_t dev,
278*10465441SEvalZero                                 rt_off_t    pos,
279*10465441SEvalZero                                 const void *buffer,
280*10465441SEvalZero                                 rt_size_t   size)
281*10465441SEvalZero {
282*10465441SEvalZero     rt_err_t err = 0;
283*10465441SEvalZero     rt_size_t offset = 0;
284*10465441SEvalZero     rt_size_t req_size = 0;
285*10465441SEvalZero     rt_size_t remain_size = size;
286*10465441SEvalZero     void *wr_ptr = (void *)buffer;
287*10465441SEvalZero     struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data;
288*10465441SEvalZero     struct dfs_partition *part = &blk_dev->part;
289*10465441SEvalZero 
290*10465441SEvalZero     if (dev == RT_NULL)
291*10465441SEvalZero     {
292*10465441SEvalZero         rt_set_errno(-EINVAL);
293*10465441SEvalZero         return 0;
294*10465441SEvalZero     }
295*10465441SEvalZero 
296*10465441SEvalZero     rt_sem_take(part->lock, RT_WAITING_FOREVER);
297*10465441SEvalZero     while (remain_size)
298*10465441SEvalZero     {
299*10465441SEvalZero         req_size = (remain_size > blk_dev->max_req_size) ? blk_dev->max_req_size : remain_size;
300*10465441SEvalZero         err = rt_mmcsd_req_blk(blk_dev->card, part->offset + pos + offset, wr_ptr, req_size, 1);
301*10465441SEvalZero         if (err)
302*10465441SEvalZero             break;
303*10465441SEvalZero         offset += req_size;
304*10465441SEvalZero         wr_ptr = (void *)((rt_uint8_t *)wr_ptr + (req_size << 9));
305*10465441SEvalZero         remain_size -= req_size;
306*10465441SEvalZero     }
307*10465441SEvalZero     rt_sem_release(part->lock);
308*10465441SEvalZero 
309*10465441SEvalZero     /* the length of reading must align to SECTOR SIZE */
310*10465441SEvalZero     if (err)
311*10465441SEvalZero     {
312*10465441SEvalZero         rt_set_errno(-EIO);
313*10465441SEvalZero 
314*10465441SEvalZero         return 0;
315*10465441SEvalZero     }
316*10465441SEvalZero     return size - remain_size;
317*10465441SEvalZero }
318*10465441SEvalZero 
mmcsd_set_blksize(struct rt_mmcsd_card * card)319*10465441SEvalZero static rt_int32_t mmcsd_set_blksize(struct rt_mmcsd_card *card)
320*10465441SEvalZero {
321*10465441SEvalZero     struct rt_mmcsd_cmd cmd;
322*10465441SEvalZero     int err;
323*10465441SEvalZero 
324*10465441SEvalZero     /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
325*10465441SEvalZero     if (card->flags & CARD_FLAG_SDHC)
326*10465441SEvalZero         return 0;
327*10465441SEvalZero 
328*10465441SEvalZero     mmcsd_host_lock(card->host);
329*10465441SEvalZero     cmd.cmd_code = SET_BLOCKLEN;
330*10465441SEvalZero     cmd.arg = 512;
331*10465441SEvalZero     cmd.flags = RESP_SPI_R1 | RESP_R1 | CMD_AC;
332*10465441SEvalZero     err = mmcsd_send_cmd(card->host, &cmd, 5);
333*10465441SEvalZero     mmcsd_host_unlock(card->host);
334*10465441SEvalZero 
335*10465441SEvalZero     if (err)
336*10465441SEvalZero     {
337*10465441SEvalZero         LOG_E("MMCSD: unable to set block size to %d: %d", cmd.arg, err);
338*10465441SEvalZero 
339*10465441SEvalZero         return -RT_ERROR;
340*10465441SEvalZero     }
341*10465441SEvalZero 
342*10465441SEvalZero     return 0;
343*10465441SEvalZero }
344*10465441SEvalZero 
345*10465441SEvalZero #ifdef RT_USING_DEVICE_OPS
346*10465441SEvalZero const static struct rt_device_ops mmcsd_blk_ops =
347*10465441SEvalZero {
348*10465441SEvalZero     rt_mmcsd_init,
349*10465441SEvalZero     rt_mmcsd_open,
350*10465441SEvalZero     rt_mmcsd_close,
351*10465441SEvalZero     rt_mmcsd_read,
352*10465441SEvalZero     rt_mmcsd_write,
353*10465441SEvalZero     rt_mmcsd_control
354*10465441SEvalZero };
355*10465441SEvalZero #endif
356*10465441SEvalZero 
rt_mmcsd_blk_probe(struct rt_mmcsd_card * card)357*10465441SEvalZero rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card)
358*10465441SEvalZero {
359*10465441SEvalZero     rt_int32_t err = 0;
360*10465441SEvalZero     rt_uint8_t i, status;
361*10465441SEvalZero     rt_uint8_t *sector;
362*10465441SEvalZero     char dname[4];
363*10465441SEvalZero     char sname[8];
364*10465441SEvalZero     struct mmcsd_blk_device *blk_dev = RT_NULL;
365*10465441SEvalZero 
366*10465441SEvalZero     err = mmcsd_set_blksize(card);
367*10465441SEvalZero     if(err)
368*10465441SEvalZero     {
369*10465441SEvalZero         return err;
370*10465441SEvalZero     }
371*10465441SEvalZero 
372*10465441SEvalZero     LOG_I("probe mmcsd block device!");
373*10465441SEvalZero 
374*10465441SEvalZero     /* get the first sector to read partition table */
375*10465441SEvalZero     sector = (rt_uint8_t *)rt_malloc(SECTOR_SIZE);
376*10465441SEvalZero     if (sector == RT_NULL)
377*10465441SEvalZero     {
378*10465441SEvalZero         LOG_E("allocate partition sector buffer failed!");
379*10465441SEvalZero 
380*10465441SEvalZero         return -RT_ENOMEM;
381*10465441SEvalZero     }
382*10465441SEvalZero 
383*10465441SEvalZero     status = rt_mmcsd_req_blk(card, 0, sector, 1, 0);
384*10465441SEvalZero     if (status == RT_EOK)
385*10465441SEvalZero     {
386*10465441SEvalZero         for (i = 0; i < RT_MMCSD_MAX_PARTITION; i++)
387*10465441SEvalZero         {
388*10465441SEvalZero             blk_dev = rt_calloc(1, sizeof(struct mmcsd_blk_device));
389*10465441SEvalZero             if (!blk_dev)
390*10465441SEvalZero             {
391*10465441SEvalZero                 LOG_E("mmcsd:malloc memory failed!");
392*10465441SEvalZero                 break;
393*10465441SEvalZero             }
394*10465441SEvalZero 
395*10465441SEvalZero             blk_dev->max_req_size = BLK_MIN((card->host->max_dma_segs *
396*10465441SEvalZero                                              card->host->max_seg_size) >> 9,
397*10465441SEvalZero                                             (card->host->max_blk_count *
398*10465441SEvalZero                                              card->host->max_blk_size) >> 9);
399*10465441SEvalZero 
400*10465441SEvalZero             /* get the first partition */
401*10465441SEvalZero             status = dfs_filesystem_get_partition(&blk_dev->part, sector, i);
402*10465441SEvalZero             if (status == RT_EOK)
403*10465441SEvalZero             {
404*10465441SEvalZero                 rt_snprintf(dname, 4, "sd%d",  i);
405*10465441SEvalZero                 rt_snprintf(sname, 8, "sem_sd%d",  i);
406*10465441SEvalZero                 blk_dev->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
407*10465441SEvalZero 
408*10465441SEvalZero                 /* register mmcsd device */
409*10465441SEvalZero                 blk_dev->dev.type = RT_Device_Class_Block;
410*10465441SEvalZero #ifdef RT_USING_DEVICE_OPS
411*10465441SEvalZero                 blk_dev->dev.ops  = &mmcsd_blk_ops;
412*10465441SEvalZero #else
413*10465441SEvalZero                 blk_dev->dev.init = rt_mmcsd_init;
414*10465441SEvalZero                 blk_dev->dev.open = rt_mmcsd_open;
415*10465441SEvalZero                 blk_dev->dev.close = rt_mmcsd_close;
416*10465441SEvalZero                 blk_dev->dev.read = rt_mmcsd_read;
417*10465441SEvalZero                 blk_dev->dev.write = rt_mmcsd_write;
418*10465441SEvalZero                 blk_dev->dev.control = rt_mmcsd_control;
419*10465441SEvalZero #endif
420*10465441SEvalZero                 blk_dev->dev.user_data = blk_dev;
421*10465441SEvalZero 
422*10465441SEvalZero                 blk_dev->card = card;
423*10465441SEvalZero 
424*10465441SEvalZero                 blk_dev->geometry.bytes_per_sector = 1<<9;
425*10465441SEvalZero                 blk_dev->geometry.block_size = card->card_blksize;
426*10465441SEvalZero                 blk_dev->geometry.sector_count = blk_dev->part.size;
427*10465441SEvalZero 
428*10465441SEvalZero                 rt_device_register(&blk_dev->dev, dname,
429*10465441SEvalZero                     RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
430*10465441SEvalZero                 rt_list_insert_after(&blk_devices, &blk_dev->list);
431*10465441SEvalZero             }
432*10465441SEvalZero             else
433*10465441SEvalZero             {
434*10465441SEvalZero                 if (i == 0)
435*10465441SEvalZero                 {
436*10465441SEvalZero                     /* there is no partition table */
437*10465441SEvalZero                     blk_dev->part.offset = 0;
438*10465441SEvalZero                     blk_dev->part.size   = 0;
439*10465441SEvalZero                     blk_dev->part.lock = rt_sem_create("sem_sd0", 1, RT_IPC_FLAG_FIFO);
440*10465441SEvalZero 
441*10465441SEvalZero                     /* register mmcsd device */
442*10465441SEvalZero                     blk_dev->dev.type  = RT_Device_Class_Block;
443*10465441SEvalZero #ifdef RT_USING_DEVICE_OPS
444*10465441SEvalZero                     blk_dev->dev.ops  = &mmcsd_blk_ops;
445*10465441SEvalZero #else
446*10465441SEvalZero                     blk_dev->dev.init = rt_mmcsd_init;
447*10465441SEvalZero                     blk_dev->dev.open = rt_mmcsd_open;
448*10465441SEvalZero                     blk_dev->dev.close = rt_mmcsd_close;
449*10465441SEvalZero                     blk_dev->dev.read = rt_mmcsd_read;
450*10465441SEvalZero                     blk_dev->dev.write = rt_mmcsd_write;
451*10465441SEvalZero                     blk_dev->dev.control = rt_mmcsd_control;
452*10465441SEvalZero #endif
453*10465441SEvalZero                     blk_dev->dev.user_data = blk_dev;
454*10465441SEvalZero 
455*10465441SEvalZero                     blk_dev->card = card;
456*10465441SEvalZero 
457*10465441SEvalZero                     blk_dev->geometry.bytes_per_sector = 1<<9;
458*10465441SEvalZero                     blk_dev->geometry.block_size = card->card_blksize;
459*10465441SEvalZero                     blk_dev->geometry.sector_count =
460*10465441SEvalZero                         card->card_capacity * (1024 / 512);
461*10465441SEvalZero 
462*10465441SEvalZero                     rt_device_register(&blk_dev->dev, "sd0",
463*10465441SEvalZero                         RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
464*10465441SEvalZero                     rt_list_insert_after(&blk_devices, &blk_dev->list);
465*10465441SEvalZero 
466*10465441SEvalZero                     break;
467*10465441SEvalZero                 }
468*10465441SEvalZero                 else
469*10465441SEvalZero                 {
470*10465441SEvalZero                     rt_free(blk_dev);
471*10465441SEvalZero                     blk_dev = RT_NULL;
472*10465441SEvalZero                     break;
473*10465441SEvalZero                 }
474*10465441SEvalZero             }
475*10465441SEvalZero 
476*10465441SEvalZero #ifdef RT_USING_DFS_MNTTABLE
477*10465441SEvalZero             if (0) // if (blk_dev)
478*10465441SEvalZero             {
479*10465441SEvalZero             	LOG_I("try to mount file system!");
480*10465441SEvalZero             	/* try to mount file system on this block device */
481*10465441SEvalZero             	dfs_mount_device(&(blk_dev->dev));
482*10465441SEvalZero             }
483*10465441SEvalZero #endif
484*10465441SEvalZero         }
485*10465441SEvalZero     }
486*10465441SEvalZero     else
487*10465441SEvalZero     {
488*10465441SEvalZero         LOG_E("read mmcsd first sector failed");
489*10465441SEvalZero         err = -RT_ERROR;
490*10465441SEvalZero     }
491*10465441SEvalZero 
492*10465441SEvalZero     /* release sector buffer */
493*10465441SEvalZero     rt_free(sector);
494*10465441SEvalZero 
495*10465441SEvalZero     return err;
496*10465441SEvalZero }
497*10465441SEvalZero 
rt_mmcsd_blk_remove(struct rt_mmcsd_card * card)498*10465441SEvalZero void rt_mmcsd_blk_remove(struct rt_mmcsd_card *card)
499*10465441SEvalZero {
500*10465441SEvalZero     rt_list_t *l, *n;
501*10465441SEvalZero     struct mmcsd_blk_device *blk_dev;
502*10465441SEvalZero 
503*10465441SEvalZero     for (l = (&blk_devices)->next, n = l->next; l != &blk_devices; l = n)
504*10465441SEvalZero     {
505*10465441SEvalZero         blk_dev = (struct mmcsd_blk_device *)rt_list_entry(l, struct mmcsd_blk_device, list);
506*10465441SEvalZero         if (blk_dev->card == card)
507*10465441SEvalZero         {
508*10465441SEvalZero         	/* unmount file system */
509*10465441SEvalZero         	const char * mounted_path = dfs_filesystem_get_mounted_path(&(blk_dev->dev));
510*10465441SEvalZero         	if (mounted_path)
511*10465441SEvalZero         	{
512*10465441SEvalZero         		dfs_unmount(mounted_path);
513*10465441SEvalZero         	}
514*10465441SEvalZero 
515*10465441SEvalZero             rt_device_unregister(&blk_dev->dev);
516*10465441SEvalZero             rt_list_remove(&blk_dev->list);
517*10465441SEvalZero             rt_free(blk_dev);
518*10465441SEvalZero         }
519*10465441SEvalZero     }
520*10465441SEvalZero }
521*10465441SEvalZero 
522*10465441SEvalZero /*
523*10465441SEvalZero  * This function will initialize block device on the mmc/sd.
524*10465441SEvalZero  *
525*10465441SEvalZero  * @deprecated since 2.1.0, this function does not need to be invoked
526*10465441SEvalZero  * in the system initialization.
527*10465441SEvalZero  */
rt_mmcsd_blk_init(void)528*10465441SEvalZero int rt_mmcsd_blk_init(void)
529*10465441SEvalZero {
530*10465441SEvalZero     /* nothing */
531*10465441SEvalZero     return 0;
532*10465441SEvalZero }
533