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