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