sdcard.c 18 KB

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