]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/mmc.c
Adaptions for fatfs R0.15
[z180-stamp.git] / avr / mmc.c
CommitLineData
7f552300
L
1/*-----------------------------------------------------------------------*/
2/* MMCv3/SDv1/SDv2 (in SPI mode) control module (C)ChaN, 2007 */
3/*-----------------------------------------------------------------------*/
4/* Only spi_rcvr(), spi_xmit(), disk_timerproc() and some macros */
5/* are platform dependent. */
6/*-----------------------------------------------------------------------*/
7
f82d019d 8#include "common.h"
a1e8218f 9#include <util/atomic.h>
7f552300
L
10#include "timer.h"
11#include "spi.h"
12#include "diskio.h"
a870134a 13#include "debug.h"
7f552300 14
1222f338 15#define MAX_DRV 2
7f552300 16
f82d019d
L
17/* Port Controls (Platform dependent) */
18/* SD card socket connections */
19
15e476bc
L
20/* TODO: config.h cofig macros */
21
a1e8218f 22//#define SD_CD_0 SBIT(PORT,) /* Card detect switch */
1222f338
L
23//#define SD_CD_0_IN SBIT(PIN,)
24//#define SD_CD_0_DDR SBIT(DDR,)
25
a1e8218f 26//#define SD_WP_0 SBIT(PORT,) /* Write protect switch */
1222f338
L
27//#define SD_WP_0_IN SBIT(PIN,)
28//#define SD_WP_0_DDR SBIT(DDR,)
29
a1e8218f
L
30#define SD_CS_0 SBIT(PORTB,0) /* Chip select/Card sense pin */
31//#define SD_CS_0_IN SBIT(PINB,0)
1222f338
L
32#define SD_CS_0_DDR SBIT(DDRB,0)
33
15e476bc 34
a1e8218f 35#define SD_CD_1 SBIT(PORTG,3) /* Card detect switch */
7e020cdf
L
36#define SD_CD_1_IN SBIT(PING,3)
37#define SD_CD_1_DDR SBIT(DDRG,3)
f82d019d 38
a1e8218f 39//#define SD_WP_1 SBIT(PORTG,5) /* Write protect switch */
15e476bc
L
40//#define SD_WP_1_IN SBIT(PING,5)
41//#define SD_WP_1_DDR SBIT(DDRG,5)
f82d019d 42
a1e8218f
L
43#define SD_CS_1 SBIT(PORTG,4) /* Chip select/Card sense pin */
44//#define SD_CS_1_IN SBIT(PING,4)
f82d019d
L
45#define SD_CS_1_DDR SBIT(DDRG,4)
46
47
a870134a 48#define SPI_CLK_SLOW() SPISetMMCInitClock() /* Set slow clock (100k-400k) */
15e476bc 49#define SPI_CLK_FAST() SPISetFastClock() /* Set fast clock (depends on the CSD) */
f82d019d
L
50
51/*--------------------------------------------------------------------------
52 Definitions for MMC/SDC command
53 ---------------------------------------------------------------------------*/
54
7f552300
L
55#define CMD0 (0) /* GO_IDLE_STATE */
56#define CMD1 (1) /* SEND_OP_COND (MMC) */
57#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */
58#define CMD8 (8) /* SEND_IF_COND */
59#define CMD9 (9) /* SEND_CSD */
60#define CMD10 (10) /* SEND_CID */
61#define CMD12 (12) /* STOP_TRANSMISSION */
62#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */
63#define CMD16 (16) /* SET_BLOCKLEN */
64#define CMD17 (17) /* READ_SINGLE_BLOCK */
65#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
66#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */
67#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
68#define CMD24 (24) /* WRITE_BLOCK */
69#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
70#define CMD55 (55) /* APP_CMD */
71#define CMD58 (58) /* READ_OCR */
72
73
7f552300
L
74/*--------------------------------------------------------------------------
75
76 Module Private Functions
77
78 ---------------------------------------------------------------------------*/
79
f82d019d
L
80struct sdsock_stat_s {
81 volatile DSTATUS stat; /* Disk/socket status */
82 BYTE CardType; /* Card type flags */
83};
7f552300
L
84
85static
f82d019d 86struct sdsock_stat_s
1222f338 87 socket[MAX_DRV] = {
f82d019d
L
88 {.stat=STA_NOINIT},
89 {.stat=STA_NOINIT}
90 };
7f552300
L
91
92/*-----------------------------------------------------------------------*/
93/* Wait for card ready */
94/*-----------------------------------------------------------------------*/
95
96static
97int wait_ready (void) /* 1:OK, 0:Timeout */
98{
99 uint32_t to = get_timer(0);
100
101 /* Wait for ready in timeout of 500ms */
102 do {
103 if (spi_rcvr() == 0xFF) {
104 return 1;
105 }
106 } while (get_timer(to) < 500);
107
108 return 0;
109}
110
111/*-----------------------------------------------------------------------*/
112/* Deselect the card and release SPI bus */
113/*-----------------------------------------------------------------------*/
114
115static
1222f338 116void deselect(BYTE drv)
7f552300 117{
a1e8218f 118 //debug("*** enter deselect(%.2x)\n", drv);
1222f338
L
119 if (drv == 0)
120 SD_CS_0 = 1;
a870134a 121 else {
1222f338 122 SD_CS_1 = 1;
a870134a
L
123 }
124
7f552300 125 /* Dummy clock (TODO: force DO hi-z for multiple slave SPI) */
a870134a
L
126 if (socket[drv].stat & STA_FAST)
127 SPI_CLK_FAST();
128 else
129 SPI_CLK_SLOW();
7f552300 130 spi_rcvr();
a870134a
L
131 SPI_OFF();
132
133 if (drv == 0) {
2fe28316 134#ifdef SD_CS_0_IN
a1e8218f
L
135 SD_CS_0_DDR = 0; /* Input */
136 SD_CS_0 = 0; /* No Pullup */
a870134a
L
137#endif
138 } else {
2fe28316 139#ifdef SD_CS_1_IN
a870134a
L
140 SD_CS_1_DDR = 0;
141 SD_CS_1 = 0;
142#endif
143 }
a1e8218f 144 //debug("*** exit deselect(%.2x)\n", drv);
7f552300
L
145}
146
7f552300
L
147/*-----------------------------------------------------------------------*/
148/* Select the card and wait for ready */
149/*-----------------------------------------------------------------------*/
150
151static
1222f338 152int select(BYTE drv) /* 1:Successful, 0:Timeout */
7f552300 153{
a1e8218f 154 //debug("*** enter select(%.2x)\n", drv);
2fe28316
L
155 if (drv == 0) {
156#ifdef SD_CS_0_IN
157 SD_CS_0 = 1;
158 SD_CS_0_DDR = 1;
159#endif
1222f338 160 SD_CS_0 = 0;
2fe28316
L
161 } else {
162#ifdef SD_CS_1_IN
a870134a
L
163 SD_CS_1 = 1;
164 SD_CS_1_DDR = 1;
165#endif
1222f338 166 SD_CS_1 = 0;
a870134a
L
167 }
168
169 if (socket[drv].stat & STA_FAST)
170 SPI_CLK_FAST();
171 else
172 SPI_CLK_SLOW();
173
7f552300
L
174 /* Dummy clock (force DO enabled) */
175 spi_rcvr();
176
177 if (wait_ready()) {
8b6edd92 178 //debug("*** exit select() == 1\n");
7f552300
L
179 return 1; /* OK */
180 }
1222f338 181 deselect(drv);
8b6edd92 182 //debug("*** exit select() == 0\n");
7f552300
L
183
184 return 0; /* Timeout */
185}
186
187/*-----------------------------------------------------------------------*/
188/* Power Control (Platform dependent) */
189/*-----------------------------------------------------------------------*/
190/* When the target system does not support socket power control, there */
191/* is nothing to do in these functions and chk_power always returns 1. */
192
193static
1222f338 194void power_on(BYTE drv)
7f552300 195{
a1e8218f 196 //debug("*** enter power_on(%.2x)\n", drv);
7f552300 197
1222f338
L
198 if (drv == 0) {
199#ifdef SD_PWR_0
1222f338 200 SD_PWR_0 = 0; /* Drives PWR pin high */
1222f338
L
201#endif
202
1222f338 203 } else {
f82d019d 204#ifdef SD_PWR_1
1222f338 205 SD_PWR_1 = 0; /* Drives PWR pin high */
15e476bc
L
206#endif
207 }
208#if defined SD_PWR_0 || defined SD_PWR_1
1222f338
L
209 for (uint32_t to = get_timer(0); get_timer(to) < 30;)
210 ; /* Wait for 30ms */
7f552300 211#endif
a1e8218f 212 //debug("*** exit power_on(%.2x)\n", drv);
7f552300
L
213}
214
215static
1222f338 216void power_off(BYTE drv)
7f552300 217{
a1e8218f 218 //debug("*** enter power_off(%.2x)\n", drv);
1222f338
L
219 select(drv); /* Wait for card ready */
220 deselect(drv);
7f552300 221
1222f338
L
222 if (drv == 0) {
223#ifdef SD_PWR_0
224 SD_PWR_0 = 1; /* Socket power OFF */
225#endif
226 } else {
f82d019d 227#ifdef SD_PWR_1
1222f338 228 SD_PWR_1 = 1; /* Socket power OFF */
7f552300 229#endif
1222f338 230 }
a1e8218f
L
231 ATOMIC_BLOCK(ATOMIC_FORCEON) {
232 socket[drv].stat |= STA_NOINIT;
233 }
234 //debug("*** exit power_off(%.2x)\n", drv);
7f552300
L
235}
236
237#if 0
238static
1222f338 239int chk_power(BYTE drv) /* Socket power state: 0=off, 1=on */
7f552300 240{
1222f338
L
241 if (drv == 0) {
242#ifdef SD_PWR_0
243 return SD_PWR_0 == 0;
244#else
245 return 1;
246#endif /* SD_PWR_PIN */
247 } else {
f82d019d 248#ifdef SD_PWR_1
1222f338 249 return SD_PWR_1 == 0;
7f552300 250#else
1222f338 251 return 1;
7f552300 252#endif /* SD_PWR_PIN */
1222f338 253 }
7f552300
L
254}
255#endif
256
257/*-----------------------------------------------------------------------*/
258/* Receive a data packet from MMC */
259/*-----------------------------------------------------------------------*/
260
261static
262int rcvr_datablock (
263 BYTE *buff, /* Data buffer to store received data */
264UINT btr /* Byte count (must be multiple of 4) */
265) {
266 BYTE token, tmp;
267 uint32_t to = get_timer(0);
268
269 /* Wait for data packet in timeout of 200ms */
270 do {
271 token = spi_rcvr();
272 } while ((token == 0xFF) && get_timer(to) < 200);
273 if(token != 0xFE) return 0; /* If not valid data token, retutn with error */
274
275 tmp = spi_rcvr(); /* shift in first byte */
276 spi_write(0xff); /* start shift in next byte */
277 while (--btr) {
278 *buff++ = tmp;
279 asm volatile (""::"r"(buff), "r"(btr));
280 spi_wait();
281 tmp = SPDR;
282 spi_write(0xff);
283 }
284 *buff = tmp; /* store last byte in buffer while SPI module shifts in crc part1 */
285 spi_wait();
286 spi_rcvr(); /* second crc */
287
288 return 1; /* Return with success */
289}
290
291/*-----------------------------------------------------------------------*/
292/* Send a data packet to MMC */
293/*-----------------------------------------------------------------------*/
294
7f552300
L
295static
296int xmit_datablock (
297 const BYTE *buff, /* 512 byte data block to be transmitted */
298 BYTE token /* Data/Stop token */
299)
300{
301 BYTE resp, tmp;
302 UINT btr;
303
304 if (!wait_ready()) return 0;
305
306 spi_write(token); /* Xmit data token */
307 if (token != 0xFD) { /* Is data token */
308 btr = 512;
309 do {
310 tmp = *buff++;
311 spi_wait();
312 spi_write(tmp);
313 }while (--btr);
314 spi_wait();
315 spi_xmit(0xff); /* CRC (Dummy) */
316 spi_xmit(0xff);
317 resp = spi_rcvr(); /* Reveive data response */
318 return ((resp & 0x1F) != 0x05) ? 0 : 1; /* If not accepted, return with error */
319 }
320
321 spi_wait();
322 return 1;
323}
7f552300
L
324
325/*-----------------------------------------------------------------------*/
326/* Send a command packet to MMC */
327/*-----------------------------------------------------------------------*/
328
329static
330BYTE send_cmd ( /* Returns R1 resp (bit7==1:Send failed) */
1222f338
L
331 BYTE drv, /* Physical drive nmuber (0) */
332 BYTE cmd, /* Command index */
333 DWORD arg /* Argument */
7f552300
L
334) {
335 union {
336 DWORD as32;
337 BYTE as8[4];
338 } argtmp;
339 BYTE n, res;
340
7f552300
L
341 if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
342 cmd &= 0x7F;
1222f338 343 res = send_cmd(drv, CMD55, 0);
7f552300
L
344 if (res > 1)
345 return res;
346 }
347
a1e8218f
L
348 //debug("*** send_cmd( %.2x )", cmd);
349
7f552300
L
350 /* Select the card and wait for ready except to stop multiple block read */
351 if (cmd != CMD12) {
1222f338 352 deselect(drv);
a1e8218f
L
353 if (!select(drv)) {
354 //debug(" == %.2x\n", 0xff);
7f552300 355 return 0xFF;
a1e8218f 356 }
7f552300
L
357 }
358
359 /* Send command packet */
360 spi_xmit(0x40 | cmd); /* Start + Command index */
361 argtmp.as32 = arg;
362 spi_xmit(argtmp.as8[3]); /* Argument[31..24] */
363 spi_xmit(argtmp.as8[2]); /* Argument[23..16] */
364 spi_xmit(argtmp.as8[1]); /* Argument[15..8] */
365 spi_xmit(argtmp.as8[0]); /* Argument[7..0] */
366
367 n = 0x01; /* Dummy CRC + Stop */
368 if (cmd == CMD0)
369 n = 0x95; /* Valid CRC for CMD0(0) */
370 if (cmd == CMD8)
371 n = 0x87; /* Valid CRC for CMD8(0x1AA) */
372 spi_xmit(n);
373
374 /* Receive command response */
375 if (cmd == CMD12)
376 spi_rcvr(); /* Skip a stuff byte when stop reading */
377 n = 10; /* Wait for a valid response in timeout of 10 attempts */
378 do
379 res = spi_rcvr();
380 while ((res & 0x80) && --n);
381
a1e8218f 382 //debug(" == %.2x\n", res);
7f552300
L
383 return res; /* Return with the response value */
384}
385
386/*--------------------------------------------------------------------------
387
388 Public Functions
389
390 ---------------------------------------------------------------------------*/
391
15e476bc
L
392void setup_mmc(void)
393{
394#ifdef SD_PWR_0
395 SD_PWR_1 = 1; /* Drives PWR pin low */
396 SD_PWR_0_DDR = 1; /* Turns on PWR pin as output */
397#endif
398#ifdef SD_WP_0
399 SD_WP_0_DDR = 0;
400 SD_WP_0 = 1; /* Pullup */
401#endif
402
403#ifdef SD_PWR_1
404 SD_PWR_1 = 1; /* Drives PWR pin low */
405 SD_PWR_1_DDR = 1; /* Turns on PWR pin as output */
406#endif
407#ifdef SD_WP_1
408 SD_WP_1_DDR = 0;
409 SD_WP_1 = 1; /* Pullup */
410#endif
411
412 /* SPI as master */
413 PRR0 &= ~_BV(PRSPI);
414 SPI_DDR = (SPI_DDR & ~(_BV(SPI_MISO) | _BV(SPI_SS)))
415 | _BV(SPI_MOSI) | _BV(SPI_SCK);
416 SPI_PORT = SPI_PORT & ~(_BV(SPI_MOSI) | _BV(SPI_SCK));
417
418#if defined SD_CD_0
419 SD_CD_0_DDR = 0;
a1e8218f 420 SD_CD_0 = 1; /* Pullup */
15e476bc
L
421#elif defined SD_CS_0_IN
422 SD_CS_0_DDR = 0;
423 SD_CS_0 = 0;
a1e8218f
L
424#endif
425#if defined SD_CD_0 || !defined SD_CS_0_IN
15e476bc 426 SD_CS_0 = 1;
a1e8218f 427 SD_CS_0_DDR = 1;
15e476bc
L
428#endif
429
430#if defined SD_CD_1
431 SD_CD_1_DDR = 0;
a1e8218f 432 SD_CD_1 = 1; /* Pullup */
15e476bc
L
433#elif defined SD_CS_1_IN
434 SD_CS_1_DDR = 0;
a1e8218f
L
435 SD_CS_1 = 0; /* No Pullup */
436#endif
437#if defined SD_CD_1 || !defined SD_CS_1_IN
438 SD_CS_1 = 1; /* Set High */
15e476bc 439 SD_CS_1_DDR = 1;
15e476bc
L
440#endif
441}
442
7f552300
L
443/*-----------------------------------------------------------------------*/
444/* Initialize Disk Drive */
445/*-----------------------------------------------------------------------*/
446
447#define MMC_INIT_TO 1000 /* 1s */
448
449DSTATUS disk_initialize (
450 BYTE drv /* Physical drive nmuber (0) */
451)
452{
453 BYTE n, cmd, ty, ocr[4];
a1e8218f 454 DSTATUS res;
7f552300 455
1222f338 456 if (drv >= MAX_DRV)
a1e8218f
L
457 return STA_NOINIT;
458 res = socket[drv].stat;
459 if (res & STA_NODISK) {
460 return res & STAT_MASK; /* No card in the socket */
461 }
1222f338 462 power_on(drv); /* Force socket power on */
a1e8218f
L
463 ATOMIC_BLOCK(ATOMIC_FORCEON) {
464 socket[drv].stat &= ~STA_FAST;
465 }
a870134a 466 SPI_CLK_SLOW();
7f552300
L
467 for (n = 10; n; n--)
468 spi_rcvr(); /* 80 dummy clocks */
469
470 ty = 0;
1222f338 471 if (send_cmd(drv, CMD0, 0) == 1) { /* Enter Idle state */
7f552300
L
472 /* Init timeout timer */
473 uint32_t timer = get_timer(0);
474
1222f338
L
475 if (send_cmd(drv, CMD8, 0x1AA) == 1) { /* SDv2? */
476 /* Get trailing return value of R7 resp */
477 for (n = 0; n < 4; n++)
478 ocr[n] = spi_rcvr();
479 if (ocr[2] == 0x01 && ocr[3] == 0xAA) {
480 /* The card can work at vdd range of 2.7-3.6V */
481 while (get_timer(timer) < MMC_INIT_TO
482 && send_cmd(drv, ACMD41, 1UL << 30))
483 ; /* Wait for leaving idle state (ACMD41 with HCS bit) */
484 if (get_timer(timer) < MMC_INIT_TO && send_cmd(drv, CMD58, 0) == 0) {
485 /* Check CCS bit in the OCR */
486 for (n = 0; n < 4; n++)
487 ocr[n] = spi_rcvr();
7f552300
L
488 ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */
489 }
490 }
491 } else { /* SDv1 or MMCv3 */
1222f338 492 if (send_cmd(drv, ACMD41, 0) <= 1) {
7f552300
L
493 ty = CT_SD1; cmd = ACMD41; /* SDv1 */
494 } else {
495 ty = CT_MMC; cmd = CMD1; /* MMCv3 */
496 }
497
498 /* Wait for leaving idle state */
1222f338
L
499 while (get_timer(timer) < MMC_INIT_TO && send_cmd(drv, cmd, 0))
500 ;
7f552300
L
501
502 /* Set R/W block length to 512 */
1222f338 503 if (!(get_timer(timer) < MMC_INIT_TO) || send_cmd(drv, CMD16, 512) != 0)
7f552300
L
504 ty = 0;
505 }
506 }
f82d019d 507 socket[drv].CardType = ty;
1222f338 508 deselect(drv);
7f552300
L
509
510 if (ty) { /* Initialization succeded */
8b6edd92 511 /* Clear STA_NOINIT */
a1e8218f
L
512 ATOMIC_BLOCK(ATOMIC_FORCEON) {
513 res = (socket[drv].stat & ~STA_NOINIT) | STA_FAST;
514 socket[drv].stat = res;
515 }
7f552300 516 } else { /* Initialization failed */
1222f338 517 power_off(drv);
7f552300
L
518 }
519
11b53d3f 520 return socket[drv].stat & STAT_MASK;
7f552300
L
521}
522
523/*-----------------------------------------------------------------------*/
524/* Get Disk Status */
525/*-----------------------------------------------------------------------*/
526
527DSTATUS disk_status (
1222f338 528 BYTE drv /* Physical drive nmuber (0) */
7f552300
L
529)
530{
a1e8218f
L
531 DSTATUS res;
532
533 //debug("***** disk_status(%.2x)", drv);
1222f338 534 if (drv >= MAX_DRV)
a1e8218f
L
535 res = STA_NOINIT;
536 else
537 res = socket[drv].stat & STAT_MASK;
538
539 //debug(" == %.2x\n", res);
540 return res;
7f552300
L
541}
542
543/*-----------------------------------------------------------------------*/
544/* Read Sector(s) */
545/*-----------------------------------------------------------------------*/
546
547DRESULT disk_read (
1222f338
L
548 BYTE drv, /* Physical drive nmuber (0) */
549 BYTE *buff, /* Pointer to the data buffer to store read data */
550 DWORD sector, /* Start sector number (LBA) */
551 UINT count /* Sector count (1..255) */
7f552300
L
552)
553{
554 BYTE cmd;
555
1222f338
L
556 if (drv >= MAX_DRV || !count)
557 return RES_PARERR;
558 if (socket[drv].stat & STA_NOINIT)
559 return RES_NOTRDY;
7f552300 560
1222f338
L
561 /* Convert to byte address if needed */
562 if (!(socket[drv].CardType & CT_BLOCK))
563 sector *= 512;
7f552300 564
1222f338
L
565 /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
566 cmd = count > 1 ? CMD18 : CMD17;
567 if (send_cmd(drv, cmd, sector) == 0) {
7f552300
L
568 do {
569 if (!rcvr_datablock(buff, 512))
570 break;
571 buff += 512;
572 } while (--count);
573 if (cmd == CMD18)
1222f338 574 send_cmd(drv, CMD12, 0); /* STOP_TRANSMISSION */
7f552300 575 }
1222f338 576 deselect(drv);
7f552300
L
577
578 return count ? RES_ERROR : RES_OK;
579}
580
581/*-----------------------------------------------------------------------*/
582/* Write Sector(s) */
583/*-----------------------------------------------------------------------*/
584
7f552300 585DRESULT disk_write (
1222f338
L
586 BYTE drv, /* Physical drive nmuber (0) */
587 const BYTE *buff, /* Pointer to the data to be written */
588 DWORD sector, /* Start sector number (LBA) */
589 UINT count /* Sector count (1..255) */
7f552300
L
590)
591{
a1e8218f
L
592 DSTATUS res;
593
1222f338
L
594 if (drv >= MAX_DRV || !count)
595 return RES_PARERR;
a1e8218f
L
596 res = socket[drv].stat;
597 if ( res & STA_NOINIT)
1222f338 598 return RES_NOTRDY;
a1e8218f 599 if (res & STA_PROTECT)
1222f338
L
600 return RES_WRPRT;
601
602 /* Convert to byte address if needed */
603 if (!(socket[drv].CardType & CT_BLOCK))
604 sector *= 512;
1222f338
L
605
606 if (count == 1) {
607 /* Single block write */
608 if ((send_cmd(drv, CMD24, sector) == 0) /* WRITE_BLOCK */
7f552300
L
609 && xmit_datablock(buff, 0xFE))
610 count = 0;
1222f338
L
611 } else {
612 /* Multiple block write */
613 if (socket[drv].CardType & CT_SDC)
614 send_cmd(drv, ACMD23, count);
615 if (send_cmd(drv, CMD25, sector) == 0) {
616 /* WRITE_MULTIPLE_BLOCK */
7f552300 617 do {
1222f338
L
618 if (!xmit_datablock(buff, 0xFC))
619 break;
7f552300 620 buff += 512;
1222f338 621 } while (--count);
7f552300 622 if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
1222f338 623 count = 1;
7f552300
L
624 }
625 }
1222f338 626 deselect(drv);
7f552300
L
627
628 return count ? RES_ERROR : RES_OK;
629}
7f552300
L
630
631/*-----------------------------------------------------------------------*/
632/* Miscellaneous Functions */
633/*-----------------------------------------------------------------------*/
634
7f552300
L
635DRESULT disk_ioctl (
636 BYTE drv, /* Physical drive nmuber (0) */
637 BYTE cmd, /* Control code */
638 void *buff /* Buffer to send/receive control data */
639)
640{
641 DRESULT res;
642 BYTE n, csd[16], *ptr = buff;
643 DWORD csize;
644
1222f338 645 if (drv >= MAX_DRV)
7f552300
L
646 return RES_PARERR;
647
648 res = RES_ERROR;
649
1222f338
L
650 if (socket[drv].stat & STA_NOINIT)
651 return RES_NOTRDY;
7f552300 652
a870134a
L
653 /* TODO: SPI clock? */
654
7f552300
L
655 switch (cmd) {
656 case CTRL_SYNC : /* Make sure that no pending write process. Do not remove this or written sector might not left updated. */
1222f338 657 if (select(drv))
7f552300
L
658 res = RES_OK;
659 break;
660
661 case GET_SECTOR_COUNT: /* Get number of sectors on the disk (DWORD) */
1222f338 662 if ((send_cmd(drv, CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
7f552300
L
663 if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
664 csize = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
665 *(DWORD*)buff = csize << 10;
666 } else { /* SDC ver 1.XX or MMC*/
667 n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
668 csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
669 *(DWORD*)buff = csize << (n - 9);
670 }
671 res = RES_OK;
672 }
673 break;
674
675 case GET_BLOCK_SIZE: /* Get erase block size in unit of sector (DWORD) */
f82d019d 676 if (socket[drv].CardType & CT_SD2) { /* SDv2? */
1222f338 677 if (send_cmd(drv, ACMD13, 0) == 0) { /* Read SD status */
7f552300
L
678 spi_rcvr();
679 if (rcvr_datablock(csd, 16)) { /* Read partial block */
680 for (n = 64 - 16; n; n--)
681 spi_rcvr(); /* Purge trailing data */
682 *(DWORD*) buff = 16UL << (csd[10] >> 4);
683 res = RES_OK;
684 }
685 }
686 } else { /* SDv1 or MMCv3 */
1222f338 687 if ((send_cmd(drv, CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
f82d019d 688 if (socket[drv].CardType & CT_SD1) { /* SDv1 */
7f552300
L
689 *(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
690 } else { /* MMCv3 */
691 *(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
692 }
693 res = RES_OK;
694 }
695 }
696 break;
697
698 /* Following commands are never used by FatFs module */
699
700 case MMC_GET_TYPE: /* Get card type flags (1 byte) */
f82d019d 701 *ptr = socket[drv].CardType;
7f552300
L
702 res = RES_OK;
703 break;
704
705 case MMC_GET_CSD: /* Receive CSD as a data block (16 bytes) */
1222f338 706 if (send_cmd(drv, CMD9, 0) == 0 /* READ_CSD */
7f552300
L
707 && rcvr_datablock(ptr, 16))
708 res = RES_OK;
709 break;
710
711 case MMC_GET_CID: /* Receive CID as a data block (16 bytes) */
1222f338 712 if (send_cmd(drv, CMD10, 0) == 0 /* READ_CID */
7f552300
L
713 && rcvr_datablock(ptr, 16))
714 res = RES_OK;
715 break;
716
717 case MMC_GET_OCR: /* Receive OCR as an R3 resp (4 bytes) */
1222f338 718 if (send_cmd(drv, CMD58, 0) == 0) { /* READ_OCR */
7f552300
L
719 for (n = 4; n; n--)
720 *ptr++ = spi_rcvr();
721 res = RES_OK;
722 }
723 break;
724
725 case MMC_GET_SDSTAT: /* Receive SD status as a data block (64 bytes) */
1222f338 726 if (send_cmd(drv, ACMD13, 0) == 0) { /* SD_STATUS */
7f552300
L
727 spi_rcvr();
728 if (rcvr_datablock(ptr, 64))
729 res = RES_OK;
730 }
731 break;
732
733 case CTRL_POWER_OFF : /* Power off */
1222f338 734 power_off(drv);
7f552300
L
735 res = RES_OK;
736 break;
737
738 default:
739 res = RES_PARERR;
740 }
741
1222f338 742 deselect(drv);
7f552300
L
743
744 return res;
745}
7f552300
L
746
747/*-----------------------------------------------------------------------*/
748/* Device Timer Interrupt Procedure (Platform dependent) */
749/*-----------------------------------------------------------------------*/
750/* This function must be called in period of 10ms */
751
752void disk_timerproc (void)
753{
754 BYTE s;
755
f82d019d 756 s = socket[0].stat;
1222f338
L
757#ifdef SD_WP_0
758 if (SD_WP_0_IN == 0) /* Write protected */
759 s |= STA_PROTECT;
15e476bc 760 else /* Write enabled */
1222f338
L
761 s &= ~STA_PROTECT;
762#endif
15e476bc
L
763
764#if defined SD_CD_0
1222f338
L
765 if (SD_CD_0_IN == 0) /* Card inserted */
766 s &= ~STA_NODISK;
15e476bc 767 else /* Socket empty */
1222f338 768 s |= (STA_NODISK | STA_NOINIT);
15e476bc
L
769#elif defined SD_CS_0_IN
770 if (SD_CS_0_DDR == 0) {
771 if (SD_CS_0_IN == 1) /* Card inserted */
772 s &= ~STA_NODISK;
773 else /* Socket empty */
774 s |= (STA_NODISK | STA_NOINIT);
775 }
1222f338 776#endif
15e476bc 777 socket[0].stat = s; /* Update MMC status */
7f552300 778
1222f338 779 s = socket[1].stat;
f82d019d
L
780#ifdef SD_WP_1
781 if (SD_WP_1_IN == 0) /* Write protected */
7f552300 782 s |= STA_PROTECT;
15e476bc 783 else /* Write enabled */
7f552300
L
784 s &= ~STA_PROTECT;
785#endif
15e476bc
L
786
787#if defined SD_CD_1
f82d019d 788 if (SD_CD_1_IN == 0) /* Card inserted */
7f552300 789 s &= ~STA_NODISK;
15e476bc 790 else /* Socket empty */
7f552300 791 s |= (STA_NODISK | STA_NOINIT);
15e476bc 792#elif defined SD_CS_1_IN
a870134a 793 if (SD_CS_1_DDR == 0) {
15e476bc 794 if (SD_CS_1_IN == 1) /* Card inserted */
a870134a 795 s &= ~STA_NODISK;
15e476bc 796 else /* Socket empty */
a870134a
L
797 s |= (STA_NODISK | STA_NOINIT);
798 }
7f552300 799#endif
1222f338 800 socket[1].stat = s; /* Update MMC status */
7f552300 801}