at91_mci.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. /*
  2. * Copyright (C) 2006 by egnite Software GmbH.
  3. * Copyright (C) 2008, 2011-2012 by egnite GmbH.
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the copyright holders nor the names of
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * For additional information see http://www.ethernut.de/
  34. */
  35. /*!
  36. * \brief Multimedia Card Interface.
  37. *
  38. * This simple implementation supports reading a single
  39. * 3.3V MultiMedia Card in slot A or B only.
  40. *
  41. * \verbatim
  42. *
  43. * $Log$
  44. * Revision 1.3 2008/10/03 11:28:58 haraldkipp
  45. * Corrected and modified initialization of MultiMedia and SD Cards.
  46. *
  47. * Revision 1.2 2008/08/11 06:59:04 haraldkipp
  48. * BSD types replaced by stdint types (feature request #1282721).
  49. *
  50. * Revision 1.1 2006/09/05 12:34:21 haraldkipp
  51. * Support for hardware MultiMedia Card interface added.
  52. * SD Cards are currently not supported.
  53. *
  54. *
  55. * \endverbatim
  56. */
  57. #include <cfg/arch.h>
  58. #include <cfg/arch/gpio.h>
  59. #include <cfg/mmci.h>
  60. #include <errno.h>
  61. #include <string.h>
  62. #include <stdlib.h>
  63. #include <sys/heap.h>
  64. #include <sys/timer.h>
  65. #include <sys/event.h>
  66. #include <fs/dospart.h>
  67. #include <fs/fs.h>
  68. #include <dev/blockdev.h>
  69. #include <dev/mmcard.h>
  70. #include <dev/at91_mci.h>
  71. #if 0
  72. /* Use for local debugging. */
  73. #define NUTDEBUG
  74. #include <stdio.h>
  75. #endif
  76. /*!
  77. * \addtogroup xgAt91Mci
  78. */
  79. /*@{*/
  80. #ifndef MMC_BLOCK_SIZE
  81. #define MMC_BLOCK_SIZE 512
  82. #endif
  83. #ifndef MCI_INI_BITRATE
  84. /* MMC starts in open drain mode with 400 kHz max. clock. */
  85. #define MCI_INI_BITRATE 400000
  86. #endif
  87. #ifndef MCI_MMC_BITRATE
  88. /* Max. clock for MMC in push-pull mode is 20 MHz. */
  89. #define MCI_MMC_BITRATE 20000000
  90. #endif
  91. #ifndef MCI_SDC_BITRATE
  92. /* Max. clock for SD-Card is 25 MHz. */
  93. #define MCI_SDC_BITRATE 25000000
  94. #endif
  95. #ifndef MMCARD_VRANGE
  96. #define MMCARD_VRANGE (MMCARD_32_33V | MMCARD_31_32V | MMCARD_30_31V)
  97. #endif
  98. #ifdef MCI_SLOTA
  99. #ifndef MMC_PINS_A
  100. #define MMC_PINS_A _BV(PA6_MCDA0_A) | _BV(PA7_MCCDA_A) | _BV(PA8_MCCK_A) | _BV(PA9_MCDA1_A) | _BV(PA10_MCDA2_A) | _BV(PA11_MCDA3_A)
  101. #endif
  102. #ifndef MMC_PINS_B
  103. #define MMC_PINS_B 0
  104. #endif
  105. #else
  106. #ifndef MMC_PINS_A
  107. #define MMC_PINS_A _BV(PA8_MCCK_A)
  108. #endif
  109. #ifndef MMC_PINS_B
  110. #define MMC_PINS_B _BV(PA1_MCCDB_B) | _BV(PA0_MCDB0_B) | _BV(PA5_MCDB1_B) | _BV(PA4_MCDB2_B) | _BV(PA3_MCDB3_B)
  111. #endif
  112. #endif
  113. #define MCICMD_ALL_SEND_CID (MMCMD_ALL_SEND_CID | MCI_MAXLAT | MCI_RSPTYP_136)
  114. #define MCICMD_DESELECT_CARD (MMCMD_SELECT_CARD)
  115. #define MCICMD_GO_IDLE_STATE (MMCMD_GO_IDLE_STATE)
  116. #define MCICMD_READ_SINGLE_BLOCK (MMCMD_READ_SINGLE_BLOCK | MCI_TRCMD_START | MCI_TRDIR | MCI_MAXLAT | MCI_RSPTYP_48)
  117. #define MCICMD_SELECT_CARD (MMCMD_SELECT_CARD | MCI_MAXLAT | MCI_RSPTYP_48)
  118. #define MCICMD_SEND_APP_CMD (MMCMD_SEND_APP_CMD | MCI_MAXLAT | MCI_RSPTYP_48)
  119. #define MCICMD_SEND_APP_OP_COND (MMCMD_SEND_APP_OP_COND | MCI_MAXLAT | MCI_RSPTYP_48)
  120. #define MCICMD_SEND_OP_COND (MMCMD_SEND_OP_COND | MCI_MAXLAT | MCI_RSPTYP_48)
  121. #define MCICMD_SEND_RELATIVE_ADDR (MMCMD_SEND_RELATIVE_ADDR | MCI_MAXLAT | MCI_RSPTYP_48)
  122. #define MCICMD_SEND_STATUS (MMCMD_SEND_STATUS | MCI_MAXLAT | MCI_RSPTYP_48)
  123. #define MCICMD_SET_BLOCKLEN (MMCMD_SET_BLOCKLEN | MCI_MAXLAT | MCI_RSPTYP_48)
  124. #define MCICMD_WRITE_BLOCK (MMCMD_WRITE_BLOCK | MCI_TRCMD_START | MCI_MAXLAT | MCI_RSPTYP_48)
  125. #define MCICMD_IERROR (MCI_RTOE | MCI_RENDE | MCI_RDIRE | MCI_RINDE)
  126. #define MCICMD_ERROR (MCI_UNRE | MCI_OVRE | MCI_DTOE | MCI_DCRCE | MCI_RCRCE | MCICMD_IERROR)
  127. #define MCIFLG_SDCARD 0x00000001
  128. #define MCIFLG_4BIT 0x00000010
  129. /*!
  130. * \brief Local card interface information.
  131. */
  132. typedef struct _MCIFC {
  133. /*! \brief Configuration flags. */
  134. uint32_t ifc_config;
  135. /*! \brief Operating conditions. */
  136. uint32_t ifc_opcond;
  137. /*! \brief Relative card address. */
  138. uint32_t ifc_reladdr;
  139. /*! \brief Pointer to sector buffer. */
  140. uint8_t *ifc_buff;
  141. /*! \brief MMC response. */
  142. uint32_t ifc_resp[4];
  143. /*! \brief Card identification. */
  144. uint32_t ifc_cid[4];
  145. } MCIFC;
  146. /*!
  147. * \brief Local multimedia card mount information.
  148. */
  149. typedef struct _MCIFCB {
  150. /*! \brief Attached file system device.
  151. */
  152. NUTDEVICE *fcb_fsdev;
  153. /*! \brief Partition table entry of the currently mounted partition.
  154. */
  155. DOSPART fcb_part;
  156. /*! \brief Next block number to read.
  157. *
  158. * The file system driver will send a NUTBLKDEV_SEEK control command
  159. * to set this value before calling the read or the write routine.
  160. *
  161. * The number is partition relative.
  162. */
  163. uint32_t fcb_blknum;
  164. /*! \brief Internal block buffer.
  165. *
  166. * A file system driver may use this one or optionally provide it's
  167. * own buffers.
  168. *
  169. * Minimal systems may share their external bus interface with
  170. * device I/O lines, in which case the buffer must be located
  171. * in internal memory.
  172. */
  173. uint8_t fcb_blkbuf[MMC_BLOCK_SIZE];
  174. } MCIFCB;
  175. /*
  176. * Several routines call NutSleep, which results in a context switch.
  177. * This mutual exclusion semaphore takes care, that multiple threads
  178. * do not interfere with each other.
  179. */
  180. static HANDLE mutex;
  181. /*!
  182. * \brief Get divider for a given MCI clock rate.
  183. *
  184. * \param clk Requested clock rate.
  185. */
  186. static uint32_t At91MciClockDiv(uint32_t clk)
  187. {
  188. uint32_t rc;
  189. /* MCI is driven by MCK/2. */
  190. rc = NutArchClockGet(NUT_HWCLK_PERIPHERAL) / 2;
  191. /* Compensate rounding error, but do not care about 10kHz. */
  192. rc += clk - 10000;
  193. /* Calculate the divider. */
  194. rc /= clk;
  195. /* Actual divider is 1 less, avoid underflow. */
  196. if (rc) {
  197. rc -= 1;
  198. }
  199. /* In reality, overflow will only happen when the caller requests
  200. a unrealistic low MCI clock. */
  201. if (rc > 255) {
  202. rc = 255;
  203. }
  204. return rc;
  205. }
  206. /*!
  207. * \brief Reset the MCI hardware.
  208. *
  209. * \param init If 0, the current settings will be kept, otherwise initial
  210. * values are loaded.
  211. */
  212. static void At91MciReset(int init)
  213. {
  214. uint32_t mode;
  215. uint32_t dtmo;
  216. uint32_t slot;
  217. /* Enable MCI clock. */
  218. outr(PMC_PCER, _BV(MCI_ID));
  219. if (init) {
  220. outr(MCI_IDR, 0xFFFFFFFF);
  221. /* Set initial configuration. */
  222. dtmo = MCI_DTOMUL_1M | MCI_DTOCYC;
  223. mode = MCI_RDPROOF | MCI_WRPROOF | (2 << MCI_PWSDIV_LSB);
  224. /* Slow start. */
  225. mode |= At91MciClockDiv(MCI_INI_BITRATE) << MCI_CLKDIV_LSB;
  226. #ifdef MCI_SLOTA
  227. slot = MCI_SDCSEL_SLOTA;
  228. #else
  229. slot = MCI_SDCSEL_SLOTB;
  230. #endif
  231. } else {
  232. /* Retrieve current configuration. */
  233. dtmo = inr(MCI_DTOR);
  234. mode = inr(MCI_MR) & 0xffff;
  235. slot = inr(MCI_SDCR);
  236. }
  237. /* Disable and software reset. */
  238. outr(MCI_CR, MCI_MCIDIS | MCI_SWRST);
  239. /* Set configuration values. */
  240. outr(MCI_DTOR, dtmo);
  241. outr(MCI_MR, mode);
  242. outr(MCI_SDCR, slot);
  243. /* Enable card interface. */
  244. outr(MCI_CR, MCI_MCIEN | MCI_PWSEN);
  245. }
  246. static void At91MciEnablePins(void)
  247. {
  248. /* Disable PIO lines used for MCI. */
  249. outr(PIOA_PDR, MMC_PINS_A | MMC_PINS_B);
  250. /* Enable peripherals. */
  251. outr(PIOA_ASR, MMC_PINS_A);
  252. outr(PIOA_BSR, MMC_PINS_B);
  253. }
  254. static void At91MciDisablePins(void)
  255. {
  256. #ifdef MCI0_PIN_SHARING
  257. /* Enable PIO input lines used for MCI. */
  258. outr(PIOA_ODR, MMC_PINS_A | MMC_PINS_B);
  259. outr(PIOA_PER, MMC_PINS_A | MMC_PINS_B);
  260. #endif
  261. }
  262. /*!
  263. * \brief Initialize MMC hardware interface.
  264. *
  265. * This function is automatically executed during during device
  266. * registration via NutRegisterDevice().
  267. *
  268. * \param dev Identifies the device to initialize.
  269. */
  270. static int At91MciInit(NUTDEVICE * dev)
  271. {
  272. /* Initialize the MCI hardware. */
  273. At91MciReset(1);
  274. return 0;
  275. }
  276. /*!
  277. * \brief Send command to multimedia card.
  278. *
  279. * \param ifc Specifies the hardware interface.
  280. * \param cmd Command code. See MMCMD_ macros.
  281. * \param param Optional command parameter.
  282. *
  283. * \return MCI status.
  284. */
  285. static uint32_t At91MciTxCmd(MCIFC * ifc, uint32_t cmd, uint32_t param)
  286. {
  287. uint32_t sr;
  288. uint32_t rl;
  289. uint32_t i;
  290. uint32_t wfs = MCI_CMDRDY;
  291. uint32_t ces = MCICMD_IERROR;
  292. /*
  293. * Disable PDC.
  294. */
  295. #ifdef NUTDEBUG
  296. printf("[Cmd%lu,%lx]", cmd & MCI_CMDNB, param);
  297. #endif
  298. outr(MCI_PTCR, PDC_TXTDIS | PDC_RXTDIS);
  299. outr(MCI_MR, inr(MCI_MR) & ~(MCI_BLKLEN | MCI_PDCMODE));
  300. outr(MCI_RCR, 0);
  301. outr(MCI_RNCR, 0);
  302. outr(MCI_TCR, 0);
  303. outr(MCI_TNCR, 0);
  304. if (cmd & MCI_TRCMD_START) {
  305. /* Data transfer. Make sure that the buffer is set. */
  306. if (ifc->ifc_buff == NULL) {
  307. errno = EINVAL;
  308. return MCI_OVRE | MCI_UNRE;
  309. }
  310. /* Set block length and PDC mode. */
  311. outr(MCI_MR, (inr(MCI_MR) & ~MCI_BLKLEN) | (MMC_BLOCK_SIZE << MCI_BLKLEN_LSB) | MCI_PDCMODE);
  312. if (cmd & MCI_TRDIR) {
  313. /* Set PDC address and counter for reading. */
  314. outr(MCI_RPR, (uint32_t) ifc->ifc_buff);
  315. outr(MCI_RCR, MMC_BLOCK_SIZE / 4);
  316. /* Enable PDC read. */
  317. outr(MCI_PTCR, PDC_RXTEN);
  318. /* We will wait until end of data transmission. */
  319. wfs = MCI_ENDRX;
  320. } else {
  321. /* Set PDC address and counter for writing. */
  322. outr(MCI_TPR, (uint32_t) ifc->ifc_buff);
  323. outr(MCI_TCR, MMC_BLOCK_SIZE / 4);
  324. /* We will wait until data block ended. */
  325. wfs = MCI_BLKE;
  326. }
  327. }
  328. /* Set card parameter and command. */
  329. outr(MCI_ARGR, param);
  330. outr(MCI_CMDR, cmd);
  331. /* When writing, enable PDC after sending the command. */
  332. if ((cmd & (MCI_TRCMD_START | MCI_TRDIR)) == MCI_TRCMD_START) {
  333. outr(MCI_PTCR, PDC_TXTEN);
  334. }
  335. /* Determine the number of words of the expected response. */
  336. switch (cmd & MCI_RSPTYP) {
  337. case MCI_RSPTYP_48:
  338. rl = 2;
  339. break;
  340. case MCI_RSPTYP_136:
  341. rl = 4;
  342. break;
  343. default:
  344. rl = 0;
  345. break;
  346. }
  347. /* Wait for MCI_CMDRDY, MCI_ENDRX or MCI_BLKE. */
  348. while (((sr = inr(MCI_SR)) & wfs) == 0);
  349. /* Check for error. */
  350. if (sr & ces) {
  351. return sr;
  352. }
  353. /* Read the resonse. */
  354. for (i = 0; i < rl; i++) {
  355. ifc->ifc_resp[i] = inr(MCI_RSPR);
  356. }
  357. #ifdef NUTDEBUG
  358. printf("[Sta=%lx]", sr);
  359. if (rl) {
  360. printf("[Rsp");
  361. for (i = 0; i < rl; i++) {
  362. printf(" %lx", ifc->ifc_resp[i]);
  363. }
  364. putchar(']');
  365. }
  366. putchar('\n');
  367. #endif
  368. /* When writing, wait until the card is not busy. */
  369. if (wfs & MCI_BLKE) {
  370. while ((inr(MCI_SR) & MCI_NOTBUSY) == 0);
  371. }
  372. /* Do we need this? */
  373. ifc->ifc_buff = NULL;
  374. return sr;
  375. }
  376. /*!
  377. * \brief Discover available cards.
  378. *
  379. * Currently this has been tested for SanDisk SD Cards and several
  380. * MultiMedia Cards. It doesn't seem to work with RS-MMC, though.
  381. *
  382. * \param ifc Specifies the hardware interface.
  383. *
  384. * \return 0 on success, -1 otherwise.
  385. */
  386. static int At91MciDiscover(MCIFC * ifc)
  387. {
  388. uint32_t sr;
  389. uint32_t clk = MCI_MMC_BITRATE;
  390. uint32_t opd = 0;
  391. int tmo;
  392. At91MciEnablePins();
  393. /* Put all cards in idle state. */
  394. At91MciTxCmd(ifc, MCICMD_GO_IDLE_STATE | MCI_SPCMD_INIT, 0);
  395. At91MciTxCmd(ifc, MCICMD_GO_IDLE_STATE, 0);
  396. /* Poll SDC operating conditions. */
  397. for (tmo = 1000; --tmo;) {
  398. sr = At91MciTxCmd(ifc, MCICMD_SEND_APP_CMD, 0);
  399. if ((ifc->ifc_resp[0] & (1 << 8)) != 0 && (sr & MCICMD_IERROR) == 0) {
  400. sr = At91MciTxCmd(ifc, MCICMD_SEND_APP_OP_COND, MMCARD_VRANGE);
  401. if ((sr & MCICMD_IERROR) == 0) {
  402. ifc->ifc_opcond = ifc->ifc_resp[0];
  403. if (ifc->ifc_resp[0] & MMCOP_NBUSY) {
  404. ifc->ifc_config |= MCIFLG_SDCARD;
  405. break;
  406. }
  407. }
  408. }
  409. NutSleep(1);
  410. }
  411. if (tmo == 0) {
  412. /* No SDC. Put all cards back in idle state and try MMC. */
  413. opd = MCI_OPDCMD;
  414. At91MciTxCmd(ifc, MCICMD_GO_IDLE_STATE, 0);
  415. /* Poll MMC operating conditions. */
  416. for (tmo = 100; --tmo;) {
  417. sr = At91MciTxCmd(ifc, MCICMD_SEND_OP_COND | opd, MMCARD_VRANGE);
  418. ifc->ifc_opcond = ifc->ifc_resp[0];
  419. if (ifc->ifc_resp[0] & MMCOP_NBUSY) {
  420. break;
  421. }
  422. NutSleep(1);
  423. }
  424. }
  425. if (tmo == 0) {
  426. /* No valid card. */
  427. At91MciDisablePins();
  428. return -1;
  429. }
  430. /* Discover cards. */
  431. ifc->ifc_reladdr = 0;
  432. for (tmo = 50; --tmo;) {
  433. sr = At91MciTxCmd(ifc, MCICMD_ALL_SEND_CID | opd, 0);
  434. memcpy(ifc->ifc_cid, ifc->ifc_resp, sizeof(ifc->ifc_cid));
  435. if (sr & MCI_RTOE) {
  436. /* No more cards. */
  437. break;
  438. }
  439. if (ifc->ifc_config & MCIFLG_SDCARD) {
  440. /* SD Card will send an address. */
  441. ifc->ifc_reladdr = 0;
  442. } else {
  443. /* MultiMedia Card will receive an address. */
  444. ifc->ifc_reladdr++;
  445. }
  446. At91MciTxCmd(ifc, MCICMD_SEND_RELATIVE_ADDR | opd, ifc->ifc_reladdr << 16);
  447. if (ifc->ifc_config & MCIFLG_SDCARD) {
  448. /* Store SD Card address. */
  449. ifc->ifc_reladdr = ifc->ifc_resp[0] >> 16;
  450. /* SD Cards can run at higher clock rates. */
  451. clk = MCI_SDC_BITRATE;
  452. }
  453. }
  454. At91MciDisablePins();
  455. if (ifc->ifc_reladdr) {
  456. /* Switch to high speed transfer. */
  457. outr(MCI_MR, (inr(MCI_MR) & ~MCI_CLKDIV) | (At91MciClockDiv(clk) << MCI_CLKDIV_LSB));
  458. return 0;
  459. }
  460. return -1;
  461. }
  462. /*!
  463. * \brief Read a single block.
  464. *
  465. * \param ifc Specifies the hardware interface.
  466. * \param blk Block number to read or verify.
  467. * \param buf Data buffer. Receives the data being read from the card.
  468. *
  469. * \return 0 on success, -1 otherwise.
  470. */
  471. static int At91MciReadSingle(MCIFC * ifc, uint32_t blk, uint8_t * buf)
  472. {
  473. int rc = -1;
  474. uint32_t sr;
  475. /* Gain mutex access. */
  476. NutEventWait(&mutex, 0);
  477. At91MciEnablePins();
  478. sr = At91MciTxCmd(ifc, MCICMD_SELECT_CARD, ifc->ifc_reladdr << 16);
  479. if ((sr & MCICMD_ERROR) == 0) {
  480. sr = At91MciTxCmd(ifc, MCICMD_SET_BLOCKLEN, MMC_BLOCK_SIZE);
  481. if ((sr & MCICMD_ERROR) == 0) {
  482. ifc->ifc_buff = buf;
  483. sr = At91MciTxCmd(ifc, MCICMD_READ_SINGLE_BLOCK, blk * MMC_BLOCK_SIZE);
  484. if ((sr & MCICMD_ERROR) == 0) {
  485. rc = 0;
  486. }
  487. }
  488. At91MciTxCmd(ifc, MCICMD_DESELECT_CARD, 0);
  489. }
  490. /* Release mutex access. */
  491. At91MciDisablePins();
  492. NutEventPost(&mutex);
  493. return rc;
  494. }
  495. /*!
  496. * \brief Write a single block.
  497. *
  498. * \param ifc Specifies the hardware interface.
  499. * \param blk Block number to read or verify.
  500. * \param buf Pointer to the data to be sent to the card.
  501. *
  502. * \return 0 on success, -1 otherwise.
  503. */
  504. static int At91MciWriteSingle(MCIFC * ifc, uint32_t blk, const uint8_t * buf)
  505. {
  506. int rc = -1;
  507. uint32_t sr;
  508. /* Gain mutex access. */
  509. NutEventWait(&mutex, 0);
  510. At91MciEnablePins();
  511. sr = At91MciTxCmd(ifc, MCICMD_SELECT_CARD, ifc->ifc_reladdr << 16);
  512. if ((sr & MCICMD_ERROR) == 0) {
  513. sr = At91MciTxCmd(ifc, MCICMD_SET_BLOCKLEN, MMC_BLOCK_SIZE);
  514. if ((sr & MCICMD_ERROR) == 0) {
  515. ifc->ifc_buff = (uint8_t *)buf;
  516. sr = At91MciTxCmd(ifc, MCICMD_WRITE_BLOCK, blk * MMC_BLOCK_SIZE);
  517. if ((sr & MCICMD_ERROR) == 0) {
  518. rc = 0;
  519. }
  520. }
  521. At91MciTxCmd(ifc, MCICMD_DESELECT_CARD, 0);
  522. }
  523. /* Release mutex access. */
  524. At91MciDisablePins();
  525. NutEventPost(&mutex);
  526. return rc;
  527. }
  528. /*!
  529. * \brief Read data blocks from a mounted partition.
  530. *
  531. * \param nfp Pointer to a ::NUTFILE structure, obtained by a previous
  532. * call to At91MciMount().
  533. * \param buffer Pointer to the data buffer to fill.
  534. * \param num Maximum number of blocks to read. However, reading
  535. * multiple blocks is not yet supported by this driver.
  536. *
  537. * \return The number of blocks actually read. A return value of -1
  538. * indicates an error.
  539. */
  540. static int At91MciBlockRead(NUTFILE * nfp, void *buffer, int num)
  541. {
  542. MCIFCB *fcb = (MCIFCB *) nfp->nf_fcb;
  543. uint32_t blk = fcb->fcb_blknum;
  544. NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
  545. MCIFC *ifc = (MCIFC *) dev->dev_icb;
  546. int rt;
  547. if (buffer == 0) {
  548. buffer = fcb->fcb_blkbuf;
  549. }
  550. blk += fcb->fcb_part.part_sect_offs;
  551. for (rt = 10; --rt >= 0;) {
  552. if (At91MciReadSingle(ifc, blk, buffer) == 0) {
  553. return 1;
  554. }
  555. At91MciReset(0);
  556. }
  557. return -1;
  558. }
  559. /*!
  560. * \brief Write data blocks to a mounted partition.
  561. *
  562. * \param nfp Pointer to a \ref NUTFILE structure, obtained by a previous
  563. * call to At91MciMount().
  564. * \param buffer Pointer to the data to be written.
  565. * \param num Maximum number of blocks to write. However, writing
  566. * multiple blocks is not yet supported by this driver.
  567. *
  568. * \return The number of blocks written. A return value of -1 indicates an
  569. * error.
  570. */
  571. static int At91MciBlockWrite(NUTFILE * nfp, const void *buffer, int num)
  572. {
  573. MCIFCB *fcb = (MCIFCB *) nfp->nf_fcb;
  574. uint32_t blk = fcb->fcb_blknum;
  575. NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
  576. MCIFC *ifc = (MCIFC *) dev->dev_icb;
  577. if (buffer == 0) {
  578. buffer = fcb->fcb_blkbuf;
  579. }
  580. blk += fcb->fcb_part.part_sect_offs;
  581. if (At91MciWriteSingle(ifc, blk, buffer) == 0) {
  582. return 1;
  583. }
  584. return -1;
  585. }
  586. /*!
  587. * \brief Unmount a previously mounted partition.
  588. *
  589. * Applications should not directly call this function, but use the high
  590. * level stdio routines for closing a previously opened volume.
  591. *
  592. * \return 0 on success, -1 otherwise.
  593. */
  594. static int At91MciUnmount(NUTFILE * nfp)
  595. {
  596. int rc = -1;
  597. if (nfp) {
  598. MCIFCB *fcb = (MCIFCB *) nfp->nf_fcb;
  599. if (fcb) {
  600. rc = fcb->fcb_fsdev->dev_ioctl(fcb->fcb_fsdev, FS_VOL_UNMOUNT, NULL);
  601. NutHeapFree(fcb);
  602. }
  603. NutHeapFree(nfp);
  604. }
  605. return rc;
  606. }
  607. /*!
  608. * \brief Mount a partition.
  609. *
  610. * Nut/OS doesn't provide specific routines for mounting. Instead routines
  611. * for opening files are used.
  612. *
  613. * Applications should not directly call this function, but use the high
  614. * level stdio routines for opening a file.
  615. *
  616. * \param dev Pointer to the MMC device.
  617. * \param name Partition number followed by a slash followed by a name
  618. * of the file system device. Both items are optional. If no
  619. * file system driver name is given, the first file system
  620. * driver found in the list of registered devices will be
  621. * used. If no partition number is specified or if partition
  622. * zero is given, the first active primary partition will be
  623. * used.
  624. * \param mode Opening mode. Currently ignored, but
  625. * \code _O_RDWR | _O_BINARY \endcode should be used for
  626. * compatibility with future enhancements.
  627. * \param acc File attributes, ignored.
  628. *
  629. * \return Pointer to a newly created file pointer to the mounted
  630. * partition or NUTFILE_EOF in case of any error.
  631. */
  632. static NUTFILE *At91MciMount(NUTDEVICE * dev, const char *name, int mode, int acc)
  633. {
  634. int partno = 0;
  635. int i;
  636. NUTDEVICE *fsdev;
  637. NUTFILE *nfp;
  638. MCIFCB *fcb;
  639. DOSPART *part;
  640. MCIFC *ifc = (MCIFC *) dev->dev_icb;
  641. FSCP_VOL_MOUNT mparm;
  642. if (At91MciDiscover(ifc)) {
  643. errno = ENODEV;
  644. return NUTFILE_EOF;
  645. }
  646. /* Parse the name for a partition number and a file system driver. */
  647. if (*name) {
  648. partno = atoi(name);
  649. do {
  650. name++;
  651. } while (*name && *name != '/');
  652. if (*name == '/') {
  653. name++;
  654. }
  655. }
  656. #ifdef NUTDEBUG
  657. printf("['%s'-PART%d]", name, partno);
  658. #endif
  659. /*
  660. * Check the list of registered devices for the given name of the
  661. * files system driver. If none has been specified, get the first
  662. * file system driver in the list. Hopefully the application
  663. * registered one only.
  664. */
  665. for (fsdev = nutDeviceList; fsdev; fsdev = fsdev->dev_next) {
  666. if (*name == 0) {
  667. if (fsdev->dev_type == IFTYP_FS) {
  668. break;
  669. }
  670. } else if (strcmp(fsdev->dev_name, name) == 0) {
  671. break;
  672. }
  673. }
  674. if (fsdev == 0) {
  675. #ifdef NUTDEBUG
  676. printf("[No FSDriver]");
  677. #endif
  678. errno = ENODEV;
  679. return NUTFILE_EOF;
  680. }
  681. if ((fcb = NutHeapAllocClear(sizeof(MCIFCB))) == 0) {
  682. errno = ENOMEM;
  683. return NUTFILE_EOF;
  684. }
  685. fcb->fcb_fsdev = fsdev;
  686. /* Initialize MMC access mutex semaphore. */
  687. NutEventPost(&mutex);
  688. /* Read MBR. */
  689. if (At91MciReadSingle(ifc, 0, fcb->fcb_blkbuf)) {
  690. NutHeapFree(fcb);
  691. return NUTFILE_EOF;
  692. }
  693. /* Check for the cookie at the end of this sector. */
  694. if (fcb->fcb_blkbuf[DOSPART_MAGICPOS] != 0x55 || fcb->fcb_blkbuf[DOSPART_MAGICPOS + 1] != 0xAA) {
  695. NutHeapFree(fcb);
  696. return NUTFILE_EOF;
  697. }
  698. /* Check for the partition table. */
  699. if(fcb->fcb_blkbuf[DOSPART_TYPEPOS] == 'F' &&
  700. fcb->fcb_blkbuf[DOSPART_TYPEPOS + 1] == 'A' &&
  701. fcb->fcb_blkbuf[DOSPART_TYPEPOS + 2] == 'T') {
  702. /* No partition table. Assume FAT12 and 32MB size. */
  703. fcb->fcb_part.part_type = PTYPE_FAT12;
  704. fcb->fcb_part.part_sect_offs = 0;
  705. fcb->fcb_part.part_sects = 65536; /* How to find out? */
  706. }
  707. else {
  708. /* Read partition table. */
  709. part = (DOSPART *) & fcb->fcb_blkbuf[DOSPART_SECTORPOS];
  710. for (i = 1; i <= 4; i++) {
  711. if (partno) {
  712. if (i == partno) {
  713. /* Found specified partition number. */
  714. fcb->fcb_part = *part;
  715. break;
  716. }
  717. } else if (part->part_state & 0x80) {
  718. /* Located first active partition. */
  719. fcb->fcb_part = *part;
  720. break;
  721. }
  722. part++;
  723. }
  724. if (fcb->fcb_part.part_type == PTYPE_EMPTY) {
  725. NutHeapFree(fcb);
  726. return NUTFILE_EOF;
  727. }
  728. }
  729. if ((nfp = NutHeapAlloc(sizeof(NUTFILE))) == 0) {
  730. NutHeapFree(fcb);
  731. errno = ENOMEM;
  732. return NUTFILE_EOF;
  733. }
  734. nfp->nf_dev = dev;
  735. nfp->nf_fcb = fcb;
  736. /*
  737. * Mount the file system volume.
  738. */
  739. mparm.fscp_bmnt = nfp;
  740. mparm.fscp_part_type = fcb->fcb_part.part_type;
  741. if (fsdev->dev_ioctl(fsdev, FS_VOL_MOUNT, &mparm)) {
  742. At91MciUnmount(nfp);
  743. return NUTFILE_EOF;
  744. }
  745. return nfp;
  746. }
  747. /*!
  748. * \brief Perform MMC control functions.
  749. *
  750. * This function is called by the ioctl() function of the C runtime
  751. * library. Applications should not directly call this function.
  752. *
  753. * \todo Card change detection should verify the serial card number.
  754. *
  755. * \param dev Identifies the device that receives the device-control
  756. * function.
  757. * \param req Requested control function. May be set to one of the
  758. * following constants:
  759. * - \ref NUTBLKDEV_MEDIAAVAIL
  760. * - \ref NUTBLKDEV_MEDIACHANGE
  761. * - \ref NUTBLKDEV_INFO
  762. * - \ref NUTBLKDEV_SEEK
  763. * - \ref MMCARD_GETOCR
  764. *
  765. * \param conf Points to a buffer that contains any data required for
  766. * the given control function or receives data from that
  767. * function.
  768. * \return 0 on success, -1 otherwise.
  769. */
  770. static int At91MciIOCtrl(NUTDEVICE * dev, int req, void *conf)
  771. {
  772. int rc = 0;
  773. MCIFC *ifc = (MCIFC *) dev->dev_icb;
  774. switch (req) {
  775. case NUTBLKDEV_MEDIAAVAIL:
  776. *((int *) conf) = 1;
  777. break;
  778. case NUTBLKDEV_MEDIACHANGE:
  779. *((int *) conf) = 0;
  780. break;
  781. case NUTBLKDEV_INFO:
  782. {
  783. BLKPAR_INFO *par = (BLKPAR_INFO *) conf;
  784. MCIFCB *fcb = (MCIFCB *) par->par_nfp->nf_fcb;
  785. par->par_nblks = fcb->fcb_part.part_sects;
  786. par->par_blksz = MMC_BLOCK_SIZE;
  787. par->par_blkbp = fcb->fcb_blkbuf;
  788. }
  789. break;
  790. case NUTBLKDEV_SEEK:
  791. {
  792. BLKPAR_SEEK *par = (BLKPAR_SEEK *) conf;
  793. MCIFCB *fcb = (MCIFCB *) par->par_nfp->nf_fcb;
  794. fcb->fcb_blknum = par->par_blknum;
  795. }
  796. break;
  797. case MMCARD_GETOCR:
  798. *((uint32_t *) conf) = ifc->ifc_opcond;
  799. break;
  800. default:
  801. rc = -1;
  802. break;
  803. }
  804. return rc;
  805. }
  806. static MCIFC mci0_info;
  807. /*!
  808. * \brief Multimedia card device information structure.
  809. *
  810. * A pointer to this structure must be passed to NutRegisterDevice()
  811. * to bind this driver to the Nut/OS kernel. An application may then
  812. * call
  813. * /verbatim
  814. * _open("MCI0:", _O_RDWR | _O_BINARY);
  815. * /endverbatim
  816. * to mount the first active primary partition with any previously
  817. * registered file system driver (typically devPhat0).
  818. */
  819. NUTDEVICE devAt91Mci0 = {
  820. 0, /*!< Pointer to next device, dev_next. */
  821. {'M', 'C', 'I', '0', 0, 0, 0, 0, 0}
  822. , /*!< Unique device name, dev_name. */
  823. 0, /*!< Type of device, dev_type. Obsolete. */
  824. 0, /*!< Base address, dev_base. Unused. */
  825. 0, /*!< First interrupt number, dev_irq. Unused. */
  826. &mci0_info, /*!< Interface control block, dev_icb. */
  827. 0, /*!< Driver control block used by the low level part, dev_dcb. */
  828. At91MciInit, /*!< Driver initialization routine, dev_init. */
  829. At91MciIOCtrl, /*!< Driver specific control function, dev_ioctl. */
  830. At91MciBlockRead, /*!< Read data from a file, dev_read. */
  831. At91MciBlockWrite, /*!< Write data to a file, dev_write. */
  832. At91MciMount, /*!< Mount a file system, dev_open. */
  833. At91MciUnmount, /*!< Unmount a file system, dev_close. */
  834. 0, /*!< Return file size, dev_size. */
  835. 0, /*!< Select function, optional, not yet implemented */
  836. };
  837. /*@}*/