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