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