00001
00005
#include "mmc.h"
00006
#include "board.h"
00007
#include "storage.h"
00008
#include "console.h"
00009
#include "buffer.h"
00010
00011
00012
00013
00014
00019 unsigned char MmcCommand(
unsigned char c1,
00020
unsigned char c2,
00021
unsigned char c3,
00022
unsigned char c4,
00023
unsigned char c5){
00024
00025
00026
unsigned int i;
00027
00028
00029
00030
00031
00032
00033
00034
00035
MMCDeselect();
00036
SPI8Clocks(8);
00037
MMCSelect();
00038
SPI8Clocks(8);
00039
00040 i=0;
00041
00042
00043
while ((
SPIGetChar()!=0xff) && (++i<60000));
00044 ;
00045
00046
00047
if ((i=
SPI_RESULT_BYTE) != 0xff){
00048 ConsoleWrite(
"\rUnexpected busy signal from MMC. ");
00049 ConsolePutHex16(i);
00050
MMCDeselect();
00051
Delay(1000);
00052
return 0x81;
00053 }
00054
00055
#ifdef MMCDEBUG
00056
DebugMessage(
" \x1b[7m");
00057 ConsolePutChar(
'C'); ConsolePutHex8(c1); ConsolePutHex8(c2); ConsolePutHex8(c3);
00058 ConsolePutHex8(c4); ConsolePutHex8(c5); ConsolePutChar(
'|');
00059
#endif
00060
00061
00062
SPIPutCharWithoutWaiting(c1);
00063
SPIPutChar(c2);
00064
SPIPutChar(c3);
00065
SPIPutChar(c4);
00066
SPIPutChar(c5);
00067
SPIPutChar(0x95);
00068
SPIWait();
00069
00070
00071
00072
#ifdef MMCDEBUG
00073
{
00074 c1=100;
00075
while((c1--)&&((c2=
SPIGetChar())&0x80)){
00076
00077
if (c2!=0xff){ConsolePutHex8(c2);ConsolePutChar(
'|');}
00078 }
00079 ConsolePutHex8(c2);
00080 DebugMessage(
"\x1b[0m ");
00081 }
00082
#else
00083
{
00084 c1=100;
00085
while((c1--)&&((c2=
SPIGetChar())&0x80))
00086 ;
00087 }
00088
#endif
00089
00090
return c2;
00091 }
00092
00093
00105 unsigned char MmcWaitForData(){
00106
00107
unsigned char c;
00108
unsigned int i;
00109
00110 DebugMessage(
"<t:");
00111
00112 i = 60000;
00113
00114
do {
00115 c=
SPIGetChar();
00116 --i;
00117 }
while ((c == 0xff) && (i));
00118
00119
00120
00121
if (c != 0xfe){
00122
00123
00124
00125
00126
00127
00128
#ifdef MMCLONGDEBUG
00129
{
00130
unsigned int i;
00131 ConsoleWrite(
"\rMMCWaitForData failed. ");
00132 ConsoleWrite(
"Expected 0xFE token, received: ");
00133
for (i=0;i<550;i++){
00134 ConsolePutHex8(c);
00135 c=
SPIGetChar();
00136 }
00137 }
00138
#else
00139
ConsoleWrite(
" NoData ");
00140
SPI8Clocks(200);
00141
SPI8Clocks(200);
00142
SPI8Clocks(200);
00143
#endif
00144
00145
MMCDeselect();
00146 DebugMessage(
"!t>");
00147
return 5;
00148 }
00149 DebugMessage(
"t>");
00150
return 0;
00151 }
00152
00153
00159 void MmcGetData(
unsigned int amountOctets){
00160 DebugMessage(
"<G");
00161
00162
dataBufPtr =
diskSect.
raw.
buf;
00163
while (amountOctets--){
00164 *
dataBufPtr++=
SPIGetChar();
00165 }
00166 DebugMessage(
"G>");
00167 }
00168
00169
00171 unsigned char GetStorageInformation(){
00172
if (
MmcCommand(0x4a,0,0,0,0)&0xfe)
00173
return 4;
00174
MmcWaitForData();
00175
MmcGetData(30);
00176
00177 ConsoleWrite(
"\rMMC Manufacturer#: ");
00178 ConsolePutUInt(
diskSect.
raw.
buf[0]);
00179 ConsoleWrite(
"Product Name: ");
00180 ConsolePutChar(
diskSect.
raw.
buf[3]);
00181 ConsolePutChar(
diskSect.
raw.
buf[4]);
00182 ConsolePutChar(
diskSect.
raw.
buf[5]);
00183 ConsolePutChar(
diskSect.
raw.
buf[6]);
00184 ConsolePutChar(
diskSect.
raw.
buf[7]);
00185 ConsolePutChar(
diskSect.
raw.
buf[8]);
00186 ConsoleWrite(
" Production date: ");
00187 ConsolePutUInt(
diskSect.
raw.
buf[14]>>4);
00188 ConsoleWrite(
"/ ");
00189 ConsolePutUInt((
diskSect.
raw.
buf[14]&0x0f)+1997);
00190 ConsolePutChar(
'\r');
00191 ConsoleWrite(
"Media serial number: ");
00192 ConsolePutHex8(
diskSect.
raw.
buf[10]);
00193 ConsolePutHex8(
diskSect.
raw.
buf[11]);
00194 ConsolePutHex8(
diskSect.
raw.
buf[12]);
00195 ConsolePutHex8(
diskSect.
raw.
buf[13]);
00196
00197
00198
00199
00200
00201
00202 ConsolePutChar(
'\r');
00203
00204
00205
00206
00207
00208
00209
00210
00211
return 0;
00212 }
00213
00214
00215
00217 unsigned char RebootMMC(){
00218
unsigned char c;
00219
00220
00221
do{
00222
SPI8Clocks(8);
00223
00224
MmcCommand(0x7B,0,0,0,0);
00225
00226 }
while (
MmcCommand(0x40,0,0,0,0)!=0x01);
00227
00228
00229 ConsoleWrite(
"Card found, starting... ");
00230
00231 c=255;
00232
while ((c--)&&(
MmcCommand(0x41,0,0,0,16))){
00233
Delay(10);
00234
if (c==1){
00235
00236 ConsoleWrite(
"Failed.\r");
00237
return 2;
00238 }
00239 }
00240
00241 ConsoleWrite(
"Ok.\r");
00242
return 0;
00243 }
00244
00245
00246 Public unsigned char InitMMC(){
00247
unsigned char c;
00248
00249
00250
MMC_OFF =
YES;
00251
00252 ConsoleWrite (
"Init: MMC\r");
00253
Delay(100);
00254
00255
00256
MMC_OFF =
NO;
00257
Delay(100);
00258
00259
MMCSelect();
00260
00261
for (c=0; c<200; c++){
00262
SPIPutCharWithoutWaiting(0xff);
00263
SPIWait();
00264 }
00265
Delay(20);
00266
00267
if (
RebootMMC())
return 1;
00268
00269
00270
GetStorageInformation();
00271
00272
00273
if ((c=
MmcCommand(0x50,0,0,2,0)))
return c|0x80;
00274
00275
00276
00277
00278
00279 {
00280
if (
SeekSector(0))
return 2;
00281
if (
ReadPhysicalSector())
return 2;
00282
00283
temp.
i =
diskSect.
raw.
buf[511];
00284
for (c=0; c<250; c++){
00285
temp.
i +=
diskSect.
raw.
buf[c];
00286 }
00287
00288
if (
SeekSector(0))
return 2;
00289
00290
00291
MMCDeselect();
00292
SPIPutCharWithoutWaiting(0xff);
00293
for (c=0; c<100; c++){
00294
SPIPutChar(0xff);
00295 }
00296
SPIWait();
00297
00298
if (
ReadPhysicalSector()){
00299 ConsoleWrite(
"Interrupted read failed.\r");
00300 ConsoleWrite(
"Using compatibility mode.\r");
00301
return 0x0e;
00302
00303 }
else{
00304
00305
temp.
i -=
diskSect.
raw.
buf[511];
00306
for (c=0; c<250; c++){
00307
temp.
i -=
diskSect.
raw.
buf[c];
00308 }
00309 }
00310
00311
if (
temp.
i) {
00312 ConsoleWrite(
"This MMC has no support for interrupted read. ");
00313 ConsoleWrite(
"Using compatibility mode.\r");
00314
return 0x0e;
00315 }
00316
00317 ConsoleWrite(
"\rInitMMC ok.\r");
00318 }
00319
00320
00321
return 0;
00322
00323 }
00324
00325
00330 void PerformBlockRead(){
00331
00332
#ifdef MMCDEBUG
00333
ConsoleWrite(
"<R");
00334
#endif
00335
00336
00337
00338
dataBufPtr =
diskSect.
raw.
buf;
00339
while (
dataBufPtr <
diskSect.
raw.
buf+512){
00340
SPIPutCharWithoutWaiting(0xff);
00341
SPIWait();
00342 *
dataBufPtr++=
SPI_RESULT_BYTE;
00343
SPIPutCharWithoutWaiting(0xff);
00344
SPIWait();
00345 *
dataBufPtr++=
SPI_RESULT_BYTE;
00346
SPIPutCharWithoutWaiting(0xff);
00347
SPIWait();
00348 *
dataBufPtr++=
SPI_RESULT_BYTE;
00349
SPIPutCharWithoutWaiting(0xff);
00350
SPIWait();
00351 *
dataBufPtr++=
SPI_RESULT_BYTE;
00352
SPIPutCharWithoutWaiting(0xff);
00353
SPIWait();
00354 *
dataBufPtr++=
SPI_RESULT_BYTE;
00355
SPIPutCharWithoutWaiting(0xff);
00356
SPIWait();
00357 *
dataBufPtr++=
SPI_RESULT_BYTE;
00358
SPIPutCharWithoutWaiting(0xff);
00359
SPIWait();
00360 *
dataBufPtr++=
SPI_RESULT_BYTE;
00361
SPIPutCharWithoutWaiting(0xff);
00362
SPIWait();
00363 *
dataBufPtr++=
SPI_RESULT_BYTE;
00364
SPIPutCharWithoutWaiting(0xff);
00365
SPIWait();
00366 *
dataBufPtr++=
SPI_RESULT_BYTE;
00367
SPIPutCharWithoutWaiting(0xff);
00368
SPIWait();
00369 *
dataBufPtr++=
SPI_RESULT_BYTE;
00370
SPIPutCharWithoutWaiting(0xff);
00371
SPIWait();
00372 *
dataBufPtr++=
SPI_RESULT_BYTE;
00373
SPIPutCharWithoutWaiting(0xff);
00374
SPIWait();
00375 *
dataBufPtr++=
SPI_RESULT_BYTE;
00376
SPIPutCharWithoutWaiting(0xff);
00377
SPIWait();
00378 *
dataBufPtr++=
SPI_RESULT_BYTE;
00379
SPIPutCharWithoutWaiting(0xff);
00380
SPIWait();
00381 *
dataBufPtr++=
SPI_RESULT_BYTE;
00382
SPIPutCharWithoutWaiting(0xff);
00383
SPIWait();
00384 *
dataBufPtr++=
SPI_RESULT_BYTE;
00385
SPIPutCharWithoutWaiting(0xff);
00386
SPIWait();
00387 *
dataBufPtr++=
SPI_RESULT_BYTE;
00388 }
00389
00390
#ifdef MMCDEBUG
00391
ConsoleWrite(
"R>");
00392
#endif
00393
00394 }
00395
00397 void ConsoleDecipherMMCResponse(
unsigned char c){
00398
00399 ConsoleWrite (
"\rSeek failed, MMC returns ");
00400 ConsolePutHex8 (c);
00401 ConsoleWrite (
"h (");
00402
00403
if (c&128) ConsoleWrite(
"which is NOT an R1 response!!");
00404
else{
00405
if (c&64) ConsoleWrite(
"ParameterError ");
00406
if (c&32) ConsoleWrite(
"AddressError ");
00407
if (c&16) ConsoleWrite(
"EraseSequenceError ");
00408
if (c&8) ConsoleWrite(
"CommandCrcError ");
00409
if (c&4) ConsoleWrite(
"IllegalCommandCode ");
00410
if (c&2) ConsoleWrite(
"EraseCancelled ");
00411
if (c&1) ConsoleWrite(
"Idle ");
00412 }
00413
00414 ConsoleWrite (
") for sector ");
00415 ConsolePutUInt (
sectorAddress.
l);
00416 ConsoleWrite(
".\rFurther reading data returns: \r");
00417
for (c=0; c<255; c++){
00418 ConsolePutHex8(
SPIGetChar());
00419 }
00420 ConsolePutChar(13);
00421
while (!
KEY_BUTTON);
00422
00423
00424 }
00425
00426
00427
00431 Public unsigned char SeekSector(
unsigned long sectorN){
00432
unsigned char c, retries;
00433
00434 retries = 0;
00435
do{
00436 retries++;
00437
sectorAddress.
l = sectorN * 2;
00438 c=
MmcCommand(0x51,
sectorAddress.
b.
b2,
sectorAddress.
b.
b1,
00439
sectorAddress.
b.
b0, 0);
00440
sectorAddress.
l =
sectorAddress.
l >> 1;
00441
00442
00443
if (c!=0x00){
00444
if (c != 0xff){
00445
00446
ConsoleDecipherMMCResponse(c);
00447 }
00448
00449
RebootMMC();
00450
if (retries > 10){
00451
return 7;
00452 }
00453 }
00454 }
while(c!=0x00);
00455
00456
MMCDeselect();
00457
00458
return 0;
00459 }
00460
00461
00462
00463 Public unsigned char ReadPhysicalSector(){
00464
00465
00466
00467
MMCSelect();
00468
MmcWaitForData();
00469
PerformBlockRead();
00470
00471
00472
00473
SPI8Clocks(4);
00474
MMCDeselect();
00475
SPI8Clocks(4);
00476
00477
00478
00479
return 0;
00480 }
00481
00482
00484 unsigned char WritePhysicalSector(){
00485
unsigned char c;
00486
00487
#ifdef MMCDEBUG
00488
ConsoleWrite(
"<W");
00489
#endif
00490
00491
00492
00493
sectorAddress.
l =
sectorAddress.
l * 2;
00494 c=
MmcCommand(0x40 | 24,
sectorAddress.
b.
b2,
sectorAddress.
b.
b1,
00495
sectorAddress.
b.
b0, 0);
00496
sectorAddress.
l =
sectorAddress.
l >> 1;
00497
00498
00499
00500
00501
if (c!=0x00)
return (c);
00502
00503
00504
00505
00506
00507
00508
00509
dataBufPtr =
diskSect.
raw.
buf;
00510
SPIPutCharWithoutWaiting(0xFE);
00511
SPIWait();
00512
00513
for (c=0;c<128;c++){
00514
SPIPutCharWithoutWaiting(*
dataBufPtr++);
00515
SPIWait();
00516
SPIPutCharWithoutWaiting(*
dataBufPtr++);
00517
SPIWait();
00518
SPIPutCharWithoutWaiting(*
dataBufPtr++);
00519
SPIWait();
00520
SPIPutCharWithoutWaiting(*
dataBufPtr++);
00521
SPIWait();
00522 }
00523
00524
00525 c =
SPIGetChar();
00526 c =
SPIGetChar();
00527 c =
SPIGetChar();
00528
00529
00530
00531
00532
00533
#ifdef MMCDEBUG
00534
ConsoleWrite(
"W>");
00535
#endif
00536
00537
00538
SPI8Clocks(16);
00539
MMCDeselect();
00540
SPI8Clocks(16);
00541
00542
00543
00544
return 0;
00545 }
00546
00547