sdcard.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /*
  2. * File : sdcard.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2007 - 2012, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2007-12-02 Yi.Qiu the first version
  13. * 2010-01-01 Bernard Modify for mini2440
  14. * 2010-10-13 Wangmeng Added sep4020 support
  15. */
  16. #include <rtthread.h>
  17. #include "sdcard.h"
  18. #ifdef RT_USING_DFS
  19. volatile rt_int32_t RCA;
  20. /* RT-Thread Device Driver Interface */
  21. #include <dfs_fs.h>
  22. /*GLOBAL SD DEVICE PONITER*/
  23. static struct sd_device *ptr_sddev;
  24. static rt_uint8_t gsec_buf[SECTOR_SIZE];
  25. #define USE_TIMEOUT
  26. /*This file is to power on/off the SEP4020 SDC*/
  27. /**
  28. * This function will power on/off the SEP4020 SDC
  29. *
  30. * @param sd_ctl: 0/power on; 1/power off
  31. * @return none
  32. *
  33. */
  34. static void sd_pwr(int sd_ctl)
  35. {
  36. if (sd_ctl)
  37. {
  38. *(RP)GPIO_PORTA_SEL |= 0x0200;
  39. *(RP)GPIO_PORTA_DIR &= (~0x0200);
  40. *(RP)GPIO_PORTA_DATA |= 0x0200;
  41. }
  42. else
  43. {
  44. *(RP)GPIO_PORTA_SEL |= 0x0200;
  45. *(RP)GPIO_PORTA_DIR &= (~0x0200);
  46. *(RP)GPIO_PORTA_DATA &= (~0x0200);
  47. }
  48. }
  49. /*a nop operation to delay*/
  50. static void delay(U32 j)
  51. {
  52. U32 i;
  53. for (i = 0; i < j; i++)
  54. {
  55. /* nothing */
  56. }
  57. }
  58. /*
  59. * Send the command to set the data transfer mode
  60. * @param cmd:the command to sent
  61. * @param arg:the argument of the command
  62. * @param mode:SDC transfer mode
  63. * @param blk_len:the block size of each data
  64. * @param num:number of blocks
  65. * @param mask:sdc interrupt mask
  66. */
  67. static rt_err_t cmd_data(U16 cmd, U32 arg, U16 mode, U16 blk_len, U16 num, U16 mask)
  68. {
  69. U32 i;
  70. #ifdef USE_TIMEOUT
  71. U32 to = 10000;
  72. #endif
  73. *(RP)SDC_CLOCK_CONTROL = 0Xff00;
  74. *(RP)SDC_CLOCK_CONTROL = 0Xff04;
  75. *(RP)SDC_INTERRUPT_STATUS_MASK = mask;
  76. *(RP)SDC_TRANSFER_MODE = mode;
  77. *(RP)SDC_BLOCK_SIZE = blk_len;
  78. *(RP)SDC_BLOCK_COUNT = num;
  79. *(RP)SDC_ARGUMENT = arg;
  80. *(RP)SDC_COMMAND = cmd;
  81. delay(10);
  82. i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
  83. while (i != 0x1000)
  84. {
  85. i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
  86. #ifdef USE_TIMEOUT
  87. to --;
  88. if (!to)
  89. {
  90. EOUT("%s TIMEOUT\n", __FUNCTION__);
  91. return RT_ETIMEOUT;
  92. }
  93. #endif
  94. }
  95. delay(160);
  96. return *(RP)SDC_RESPONSE0;
  97. }
  98. static rt_err_t cmd_response(U16 Cmd, U32 Arg, U16 TransMode, U16 BlkLen, U16 Nob, U16 IntMask)
  99. {
  100. U32 i;
  101. #ifdef USE_TIMEOUT
  102. U32 to = 50000;
  103. #endif
  104. *(RP)SDC_CLOCK_CONTROL = 0Xff00;
  105. *(RP)SDC_CLOCK_CONTROL = 0Xff04;
  106. *(RP)SDC_INTERRUPT_STATUS_MASK = IntMask;
  107. *(RP)SDC_TRANSFER_MODE = TransMode;
  108. *(RP)SDC_BLOCK_SIZE = BlkLen;
  109. *(RP)SDC_BLOCK_COUNT = Nob;
  110. *(RP)SDC_ARGUMENT = Arg;
  111. *(RP)SDC_COMMAND = Cmd;
  112. delay(10);
  113. i = *(RP)SDC_INTERRUPT_STATUS & 0x1040;
  114. while (i != 0x1040)
  115. {
  116. i = *(RP)SDC_INTERRUPT_STATUS & 0x1040;
  117. #ifdef USE_TIMEOUT
  118. to--;
  119. if (!to)
  120. {
  121. EOUT("%s Timeout\n", __FUNCTION__);
  122. return RT_ETIMEOUT;
  123. }
  124. #endif
  125. }
  126. //DBOUT("cmd_response TO is %d\n",to);
  127. delay(100);
  128. return RT_EOK;
  129. }
  130. static rt_err_t cmd_wait(U16 Cmd, U32 Arg, U16 IntMask)
  131. {
  132. int i;
  133. #ifdef USE_TIMEOUT
  134. U32 to = 200000;
  135. #endif
  136. *(RP)SDC_CLOCK_CONTROL = 0Xff00;
  137. *(RP)SDC_CLOCK_CONTROL = 0Xff04;
  138. *(RP)SDC_COMMAND = Cmd;
  139. *(RP)SDC_INTERRUPT_STATUS_MASK = IntMask;
  140. *(RP)SDC_ARGUMENT = Arg;
  141. i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
  142. while (i != 0x1000)
  143. {
  144. i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
  145. #ifdef USE_TIMEOUT
  146. to--;
  147. if (!to)
  148. {
  149. EOUT("%s Timeout\n", __FUNCTION__);
  150. return RT_ETIMEOUT;
  151. }
  152. #endif
  153. }
  154. //DBOUT("cmd_wait TO is %d\n",to);
  155. delay(10);
  156. return RT_EOK;
  157. }
  158. /**
  159. * This function will set a hook function, which will be invoked when a memory
  160. * block is allocated from heap memory.
  161. *
  162. * @param hook the hook function
  163. */
  164. static rt_err_t sd_init(void)
  165. {
  166. rt_err_t err;
  167. #ifdef USE_TIMEOUT
  168. rt_uint32_t to = 1000;
  169. #endif
  170. sd_pwr(1);
  171. *(RP)SDC_SOFTWARE_RESET = 0x0;
  172. delay(200);
  173. *(RP)SDC_SOFTWARE_RESET = 0x1;
  174. delay(200);
  175. cmd_wait(0x08, 0x0, 0xfff);
  176. do
  177. {
  178. err = cmd_wait(0x6ea, 0x0, 0xfff);
  179. #ifdef USE_TIMEOUT
  180. if (err != RT_EOK)
  181. {
  182. EOUT("cmd_wait err in %s\n", __FUNCTION__);
  183. return RT_ETIMEOUT;
  184. }
  185. #endif
  186. delay(3);
  187. err = cmd_wait(0x52a, 0x80ff8000, 0xfff);
  188. if (err != RT_EOK)
  189. {
  190. EOUT("cmd_wait err in %s\n", __FUNCTION__);
  191. return RT_ETIMEOUT;
  192. }
  193. #ifdef USE_TIMEOUT
  194. to--;
  195. if (!to)
  196. {
  197. EOUT("%s timeout\n", __FUNCTION__);
  198. return RT_ETIMEOUT;
  199. }
  200. #endif
  201. }
  202. while (*(RP)SDC_RESPONSE0 < 0X80008000);
  203. cmd_data(0x49, 0X0, 0X0, 0x0, 0x0, 0Xfff);
  204. cmd_data(0x6a, 0X0, 0X0, 0x0, 0x0, 0Xfff);
  205. RCA = *(RP)SDC_RESPONSE0;
  206. cmd_data(0xea, RCA, 0X0, 0x0, 0x0, 0Xfff);
  207. return RT_EOK;
  208. }
  209. /**
  210. * This function will set a hook function, which will be invoked when a memory
  211. * block is allocated from heap memory.
  212. *
  213. * @param hook the hook function
  214. */
  215. static rt_err_t sd_readblock(rt_uint32_t address, rt_uint8_t *buf)
  216. {
  217. U32 complete, i;
  218. rt_uint8_t temp;
  219. rt_err_t err;
  220. RT_UNUSED rt_uint32_t discard;
  221. #ifdef USE_TIMEOUT
  222. rt_uint32_t to = 10;
  223. #endif
  224. //rt_kprintf("in readblock:%x\n",address);
  225. //Clear all the errors & interrups
  226. *(RP)DMAC_INTINTERRCLR |= 0x1;
  227. *(RP)DMAC_INTINTERRCLR &= ~0x1;
  228. *(RP)DMAC_INTTCCLEAR |= 0x1;
  229. *(RP)DMAC_INTTCCLEAR &= ~0x1;
  230. /*Clear read fifo*/
  231. *(RP)(SDC_INTERRUPT_STATUS_MASK) = ~(0x1 << 9); //don't mask fifo empty
  232. while ((*(RP)SDC_INTERRUPT_STATUS) & 0x200 != 0x200)
  233. discard = *(RP)SDC_READ_BUFER_ACCESS;
  234. /*DMAC2,word,size=0x80*/
  235. *(RP)DMAC_C2SRCADDR = SDC_READ_BUFER_ACCESS;
  236. *(RP)DMAC_C2DESTADDR = (rt_uint32_t)buf;
  237. *(RP)DMAC_C2CONTROL = 0x20249b;
  238. *(RP)DMAC_C2CONFIGURATION = 0x38d;
  239. err = cmd_wait(0x6ea, RCA, 0xfff);
  240. if (err != RT_EOK)
  241. {
  242. rt_set_errno(err);
  243. return err;
  244. }
  245. err = cmd_wait(0xca, 0x2, 0xfff);
  246. if (err != RT_EOK)
  247. {
  248. rt_set_errno(err);
  249. return err;
  250. }
  251. err = cmd_response(0x22e, address, 0X1, 0x0200, 0x1, 0Xfff); //CMD17 4bit mode
  252. if (err != RT_EOK)
  253. {
  254. rt_set_errno(err);
  255. return err;
  256. }
  257. complete = *(RP)SDC_INTERRUPT_STATUS;
  258. /*CRC*/
  259. if ((complete | 0xfffffffd) != 0xfffffffd)
  260. {
  261. rt_kprintf("CRC ERROR!!!\n");
  262. complete = *(RP)SDC_INTERRUPT_STATUS;
  263. }
  264. while (((*(RP)(DMAC_INTTCSTATUS)) & 0x4) != 0x4)
  265. {
  266. delay(10);
  267. #ifdef USE_TIMEOUT
  268. to--;
  269. if (!to)
  270. {
  271. EOUT("%s TIMEOUT\n", __FUNCTION__);
  272. return RT_ETIMEOUT;
  273. }
  274. #endif
  275. }
  276. #ifdef USE_TIMEOUT
  277. //DBOUT("%s timeout is %d\n",__FUNCTION__,to);
  278. #endif
  279. /*for the buf is big-endian we must reverse it*/
  280. for (i = 0; i < 0x80; i++)
  281. {
  282. temp = buf[0];
  283. buf[0] = buf[3];
  284. buf[3] = temp;
  285. temp = buf[1];
  286. buf[1] = buf[2];
  287. buf[2] = temp;
  288. buf += 4;
  289. }
  290. return RT_EOK;
  291. }
  292. static rt_uint8_t sd_readmultiblock(rt_uint32_t address, rt_uint8_t *buf, rt_uint32_t size)
  293. {
  294. rt_int32_t index;
  295. rt_uint8_t status = RT_EOK;
  296. for (index = 0; index < size; index++)
  297. {
  298. status = sd_readblock(address + index * SECTOR_SIZE, buf + index * SECTOR_SIZE);
  299. if (status != RT_EOK)
  300. break;
  301. }
  302. return status;
  303. }
  304. /**
  305. * This function will set a hook function, which will be invoked when a memory
  306. * block is allocated from heap memory.
  307. *
  308. * @param hook the hook function
  309. */
  310. static rt_uint8_t sd_writeblock(rt_uint32_t address, rt_uint8_t *buf)
  311. {
  312. U32 complete;
  313. rt_uint8_t temp;
  314. rt_uint8_t *ptr = buf;
  315. rt_err_t err;
  316. #ifdef USE_TIMEOUT
  317. rt_uint32_t to = 10;
  318. #endif
  319. int i;
  320. rt_kprintf("in writeblock:%x\n", address);
  321. /*for the buf is big-endian we must reverse it*/
  322. for (i = 0; i < 0x80; i++)
  323. {
  324. temp = ptr[0];
  325. ptr[0] = ptr[3];
  326. ptr[3] = temp;
  327. temp = ptr[1];
  328. ptr[1] = ptr[2];
  329. ptr[2] = temp;
  330. ptr += 4;
  331. }
  332. //Clear all the errors & interrups
  333. *(RP)DMAC_INTINTERRCLR |= 0x1;
  334. *(RP)DMAC_INTINTERRCLR &= ~0x1;
  335. *(RP)DMAC_INTTCCLEAR |= 0x1;
  336. *(RP)DMAC_INTTCCLEAR &= ~0x1;
  337. *(RP)DMAC_C2SRCADDR = (U32)buf;
  338. *(RP)DMAC_C2DESTADDR = SDC_WRITE_BUFER_ACCESS;
  339. *(RP)DMAC_C2CONTROL = 0x20149b;
  340. *(RP)DMAC_C2CONFIGURATION = 0x380b;
  341. err = cmd_wait(0x6ea, RCA, 0xfff);
  342. if (err != RT_EOK)
  343. {
  344. rt_set_errno(err);
  345. return err;
  346. }
  347. err = cmd_wait(0xca, 0x2, 0xfff);
  348. if (err != RT_EOK)
  349. {
  350. rt_set_errno(err);
  351. return err;
  352. }
  353. err = cmd_response(0x30e, address, 0X3, 0x0200, 0x1, 0Xfff); //CMD24 1bit mode
  354. if (err != RT_EOK)
  355. {
  356. rt_set_errno(err);
  357. return err;
  358. }
  359. complete = *(RP)SDC_INTERRUPT_STATUS;
  360. if ((complete | 0xfffffffe) != 0xfffffffe)
  361. {
  362. //printf("CRC ERROR");
  363. complete = *(RP)SDC_INTERRUPT_STATUS;
  364. }
  365. while (((*(RP)(DMAC_INTTCSTATUS)) & 0x4) != 0x4)
  366. {
  367. delay(10);
  368. #ifdef USE_TIMEOUT
  369. to--;
  370. if (!to)
  371. {
  372. EOUT("%s TIMEOUT\n", __FUNCTION__);
  373. }
  374. #endif
  375. }
  376. #ifdef USE_TIMEOUT
  377. //DBOUT("%s timeout is %d\n",__FUNCTION__,to);
  378. #endif
  379. return RT_EOK;
  380. }
  381. /**
  382. * This function will set a hook function, which will be invoked when a memory
  383. * block is allocated from heap memory.
  384. *
  385. * @param hook the hook function
  386. */
  387. static rt_err_t rt_sdcard_init(rt_device_t dev)
  388. {
  389. return 0;
  390. }
  391. /**
  392. * This function will set a hook function, which will be invoked when a memory
  393. * block is allocated from heap memory.
  394. *
  395. * @param hook the hook function
  396. */
  397. static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
  398. {
  399. return 0;
  400. }
  401. /**
  402. * This function will set a hook function, which will be invoked when a memory
  403. * block is allocated from heap memory.
  404. *
  405. * @param hook the hook function
  406. */
  407. static rt_err_t rt_sdcard_close(rt_device_t dev)
  408. {
  409. return 0;
  410. }
  411. /**
  412. * This function will set a hook function, which will be invoked when a memory
  413. * block is allocated from heap memory.
  414. *
  415. * @param hook the hook function
  416. */
  417. static rt_err_t rt_sdcard_control(rt_device_t dev, int cmd, void *args)
  418. {
  419. rt_kprintf("cmd = %d\n", cmd);
  420. RT_ASSERT(dev != RT_NULL);
  421. if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
  422. {
  423. struct rt_device_blk_geometry *geometry;
  424. geometry = (struct rt_device_blk_geometry *)args;
  425. if (geometry == RT_NULL) return -RT_ERROR;
  426. geometry->bytes_per_sector = 512;
  427. geometry->block_size = 0x200000;
  428. //if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  429. // geometry->sector_count = (SDCardInfo.SD_csd.DeviceSize + 1) * 1024;
  430. //else
  431. geometry->sector_count = 0x200000;//SDCardInfo.CardCapacity/SDCardInfo.CardBlockSize;
  432. }
  433. return RT_EOK;
  434. }
  435. /**
  436. * This function will set a hook function, which will be invoked when a memory
  437. * block is allocated from heap memory.
  438. *
  439. * @param hook the hook function
  440. */
  441. static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  442. {
  443. rt_uint32_t retry = 3;
  444. rt_uint8_t status;
  445. rt_uint32_t index;
  446. struct dfs_partition *part;
  447. if (dev == RT_NULL)
  448. {
  449. rt_set_errno(-DFS_STATUS_EINVAL);
  450. return 0;
  451. }
  452. part = (struct dfs_partition *)dev->user_data;
  453. // take the semaphore
  454. rt_sem_take(part->lock, RT_WAITING_FOREVER);
  455. while (retry--)
  456. {
  457. if (((rt_uint32_t)buffer % 4 != 0) ||
  458. ((rt_uint32_t)buffer > 0x20080000))
  459. {
  460. for (index = 0; index < size; index++)
  461. {
  462. status = sd_readblock((part->offset + pos) * SECTOR_SIZE, ptr_sddev->sec_buf);
  463. if (status != RT_EOK)
  464. break;
  465. rt_memcpy((rt_uint8_t *)buffer + (index * SECTOR_SIZE), ptr_sddev->sec_buf, SECTOR_SIZE);
  466. }
  467. }
  468. else
  469. {
  470. for (index = 0; index < size; index++)
  471. {
  472. status = sd_readblock((pos) * SECTOR_SIZE, (rt_uint8_t *)buffer + index * SECTOR_SIZE);
  473. if (status != RT_EOK)
  474. break;
  475. }
  476. }
  477. }
  478. rt_sem_release(part->lock);
  479. if (status == RT_EOK)
  480. return size;
  481. rt_kprintf("read failed: %d, buffer 0x%08x\n", status, buffer);
  482. return 0;
  483. }
  484. /**
  485. * This function will set a hook function, which will be invoked when a memory
  486. * block is allocated from heap memory.
  487. *
  488. * @param hook the hook function
  489. */
  490. static rt_size_t rt_sdcard_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  491. {
  492. int i;
  493. rt_uint8_t status;
  494. struct dfs_partition *part;
  495. if (dev == RT_NULL)
  496. {
  497. rt_set_errno(-DFS_STATUS_EINVAL);
  498. return 0;
  499. }
  500. part = (struct dfs_partition *)dev->user_data;
  501. rt_sem_take(part->lock, RT_WAITING_FOREVER);
  502. if (((rt_uint32_t)buffer % 4 != 0) ||
  503. ((rt_uint32_t)buffer > 0x20080000))
  504. {
  505. rt_uint32_t index;
  506. for (index = 0; index < size; index++)
  507. {
  508. rt_memcpy(ptr_sddev->sec_buf, ((rt_uint8_t *)buffer + index * SECTOR_SIZE), SECTOR_SIZE);
  509. status = sd_writeblock((part->offset + index + pos) * SECTOR_SIZE, ptr_sddev->sec_buf);
  510. }
  511. }
  512. else
  513. {
  514. for (i = 0; i < size; i++)
  515. {
  516. status = sd_writeblock((part->offset + i + pos) * SECTOR_SIZE,
  517. (rt_uint8_t *)((rt_uint8_t *)buffer + i * SECTOR_SIZE));
  518. if (status != RT_EOK) break;
  519. }
  520. }
  521. rt_sem_release(part->lock);
  522. if (status == RT_EOK)
  523. return size;
  524. rt_kprintf("read failed: %d, buffer 0x%08x\n", status, buffer);
  525. return 0;
  526. }
  527. rt_err_t rt_hw_sdcard_exit()
  528. {
  529. if (ptr_sddev->device != RT_NULL)
  530. rt_free(ptr_sddev->device);
  531. if (ptr_sddev->part != RT_NULL)
  532. rt_free(ptr_sddev->part);
  533. if (ptr_sddev != RT_NULL)
  534. rt_free(ptr_sddev);
  535. return RT_EOK;
  536. }
  537. /**
  538. * This function will init sd card
  539. *
  540. * @param void
  541. */
  542. rt_err_t rt_hw_sdcard_init()
  543. {
  544. /*For test*/
  545. rt_err_t err;
  546. rt_int32_t i;
  547. char dname[4];
  548. char sname[8];
  549. /*Initialize structure*/
  550. ptr_sddev = (struct sd_device *)rt_malloc(sizeof(struct sd_device));
  551. if (ptr_sddev == RT_NULL)
  552. {
  553. EOUT("Failed to allocate sdcard device structure\n");
  554. return RT_ENOMEM;
  555. }
  556. /*sdcard intialize*/
  557. err = sd_init();
  558. if (err != RT_EOK)
  559. goto FAIL2;
  560. /*set sector buffer*/
  561. ptr_sddev->sec_buf = gsec_buf;
  562. ptr_sddev->buf_size = SECTOR_SIZE;
  563. ptr_sddev->sdc = (struct sd_c *)SD_BASE;
  564. //DBOUT("allocate partition sector buffer OK!");
  565. err = sd_readblock(0, ptr_sddev->sec_buf);
  566. if (err != RT_EOK)
  567. {
  568. EOUT("read first block error\n");
  569. goto FAIL2;
  570. }
  571. /*sdcard driver initialize*/
  572. ptr_sddev->part = (struct dfs_partition *)rt_malloc(4 * sizeof(struct dfs_partition));
  573. if (ptr_sddev->part == RT_NULL)
  574. {
  575. EOUT("allocate partition failed\n");
  576. err = RT_ENOMEM;
  577. goto FAIL2;
  578. }
  579. /*alloc device buffer*/
  580. ptr_sddev->device = (struct rt_device *)rt_malloc(4 * sizeof(struct rt_device));
  581. if (ptr_sddev->device == RT_NULL)
  582. {
  583. EOUT("allocate device failed\n");
  584. err = RT_ENOMEM;
  585. goto FAIL1;
  586. }
  587. ptr_sddev->part_num = 0;
  588. err = sd_readblock(0, ptr_sddev->sec_buf);
  589. if (err != RT_EOK)
  590. {
  591. EOUT("Read block 0 to initialize ERROR\n");
  592. goto FAIL1;
  593. }
  594. for (i = 0; i < 4; i++)
  595. {
  596. /* get the first partition */
  597. err = dfs_filesystem_get_partition(&(ptr_sddev->part[i]), ptr_sddev->sec_buf, i);
  598. if (err == RT_EOK)
  599. {
  600. rt_snprintf(dname, 4, "sd%d", i);
  601. rt_snprintf(sname, 8, "sem_sd%d", i);
  602. ptr_sddev->part[i].lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
  603. /* register sdcard device */
  604. ptr_sddev->device[i].init = rt_sdcard_init;
  605. ptr_sddev->device[i].open = rt_sdcard_open;
  606. ptr_sddev->device[i].close = rt_sdcard_close;
  607. ptr_sddev->device[i].read = rt_sdcard_read;
  608. ptr_sddev->device[i].write = rt_sdcard_write;
  609. ptr_sddev->device[i].control = rt_sdcard_control;
  610. ptr_sddev->device[i].user_data = &ptr_sddev->part[i];
  611. err = rt_device_register(&ptr_sddev->device[i], dname,
  612. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
  613. if (err == RT_EOK)
  614. ptr_sddev->part_num++;
  615. }
  616. else
  617. {
  618. if (i == 0)
  619. {
  620. /* there is no partition table */
  621. ptr_sddev->part[0].offset = 0;
  622. ptr_sddev->part[0].size = 0;
  623. ptr_sddev->part[0].lock = rt_sem_create("sem_sd0", 1, RT_IPC_FLAG_FIFO);
  624. /* register sdcard device */
  625. ptr_sddev->device[0].init = rt_sdcard_init;
  626. ptr_sddev->device[0].open = rt_sdcard_open;
  627. ptr_sddev->device[0].close = rt_sdcard_close;
  628. ptr_sddev->device[0].read = rt_sdcard_read;
  629. ptr_sddev->device[0].write = rt_sdcard_write;
  630. ptr_sddev->device[0].control = rt_sdcard_control;
  631. ptr_sddev->device[0].user_data = &ptr_sddev->part[0];
  632. err = rt_device_register(&ptr_sddev->device[0], "sd0",
  633. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
  634. if (err == RT_EOK)
  635. ptr_sddev->part_num++;
  636. break;
  637. }
  638. }
  639. }
  640. if (ptr_sddev->part_num == 0)
  641. goto FAIL0;
  642. return err;
  643. FAIL0:
  644. rt_free(ptr_sddev->device);
  645. ptr_sddev->device = RT_NULL;
  646. FAIL1:
  647. rt_free(ptr_sddev->part);
  648. ptr_sddev->part = RT_NULL;
  649. FAIL2:
  650. rt_free(ptr_sddev);
  651. ptr_sddev = RT_NULL;
  652. return err;
  653. }
  654. #endif