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