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 ConsoleWrite ("Init: MMC\r");
00251 MMCSelect();
00252
00253 for (c=0; c<200; c++){
00254 SPIPutCharWithoutWaiting(0xff);
00255 SPIWait();
00256 }
00257 Delay(20);
00258
00259 if (RebootMMC()) return 1;
00260
00261
00262 GetStorageInformation();
00263
00264
00265 if ((c=MmcCommand(0x50,0,0,2,0))) return c|0x80;
00266
00267
00268
00269
00270
00271 {
00272 if (SeekSector(0)) return 2;
00273 if (ReadPhysicalSector()) return 2;
00274
00275 temp.i = diskSect.raw.buf[511];
00276 for (c=0; c<250; c++){
00277 temp.i += diskSect.raw.buf[c];
00278 }
00279
00280 if (SeekSector(0)) return 2;
00281
00282
00283 MMCDeselect();
00284 SPIPutCharWithoutWaiting(0xff);
00285 for (c=0; c<100; c++){
00286 SPIPutChar(0xff);
00287 }
00288 SPIWait();
00289
00290 if (ReadPhysicalSector()){
00291 ConsoleWrite("Interrupted read failed.\r");
00292 ConsoleWrite("Using compatibility mode.\r");
00293 return 0x0e;
00294
00295 }else{
00296
00297 temp.i -= diskSect.raw.buf[511];
00298 for (c=0; c<250; c++){
00299 temp.i -= diskSect.raw.buf[c];
00300 }
00301 }
00302
00303 if (temp.i) {
00304 ConsoleWrite("This MMC has no support for interrupted read. ");
00305 ConsoleWrite("Using compatibility mode.\r");
00306 return 0x0e;
00307 }
00308
00309 ConsoleWrite("\rInitMMC ok.\r");
00310 }
00311
00312
00313 return 0;
00314
00315 }
00316
00317
00318
00319 #define USE_C_CODE_INSTEAD_OF_ASM 0
00320
00325 void PerformBlockRead(){
00326
00327 #ifdef MMCDEBUG
00328 ConsoleWrite("<R");
00329 #endif
00330
00331
00332
00333
00334
00335 dataBufPtr = diskSect.raw.buf;
00336
00337
00338
00339 #if USE_C_CODE_INSTEAD_OF_ASM
00340
00341 while (dataBufPtr < diskSect.raw.buf+512){
00342 SPIPutCharWithoutWaiting(0xff);
00343 SPIWait();
00344 *dataBufPtr++=SPI_RESULT_BYTE;
00345 SPIPutCharWithoutWaiting(0xff);
00346 SPIWait();
00347 *dataBufPtr++=SPI_RESULT_BYTE;
00348 SPIPutCharWithoutWaiting(0xff);
00349 SPIWait();
00350 *dataBufPtr++=SPI_RESULT_BYTE;
00351 SPIPutCharWithoutWaiting(0xff);
00352 SPIWait();
00353 *dataBufPtr++=SPI_RESULT_BYTE;
00354 SPIPutCharWithoutWaiting(0xff);
00355 SPIWait();
00356 *dataBufPtr++=SPI_RESULT_BYTE;
00357 SPIPutCharWithoutWaiting(0xff);
00358 SPIWait();
00359 *dataBufPtr++=SPI_RESULT_BYTE;
00360 SPIPutCharWithoutWaiting(0xff);
00361 SPIWait();
00362 *dataBufPtr++=SPI_RESULT_BYTE;
00363 SPIPutCharWithoutWaiting(0xff);
00364 SPIWait();
00365 *dataBufPtr++=SPI_RESULT_BYTE;
00366 SPIPutCharWithoutWaiting(0xff);
00367 SPIWait();
00368 *dataBufPtr++=SPI_RESULT_BYTE;
00369 SPIPutCharWithoutWaiting(0xff);
00370 SPIWait();
00371 *dataBufPtr++=SPI_RESULT_BYTE;
00372 SPIPutCharWithoutWaiting(0xff);
00373 SPIWait();
00374 *dataBufPtr++=SPI_RESULT_BYTE;
00375 SPIPutCharWithoutWaiting(0xff);
00376 SPIWait();
00377 *dataBufPtr++=SPI_RESULT_BYTE;
00378 SPIPutCharWithoutWaiting(0xff);
00379 SPIWait();
00380 *dataBufPtr++=SPI_RESULT_BYTE;
00381 SPIPutCharWithoutWaiting(0xff);
00382 SPIWait();
00383 *dataBufPtr++=SPI_RESULT_BYTE;
00384 SPIPutCharWithoutWaiting(0xff);
00385 SPIWait();
00386 *dataBufPtr++=SPI_RESULT_BYTE;
00387 SPIPutCharWithoutWaiting(0xff);
00388 SPIWait();
00389 *dataBufPtr++=SPI_RESULT_BYTE;
00390 }
00391
00392 #else
00393
00394
00395
00396 _asm
00397
00398 push psw
00399 push acc
00400 mov a,r2
00401 push acc
00402 push dpl
00403 push dph
00404
00405
00406 mov dpl,_dataBufPtr
00407 mov dph,(_dataBufPtr + 1)
00408 2106$:
00409 clr c
00410 mov a,_dataBufPtr
00411 subb a,#(_diskSect + 0x0200)
00412 mov a,(_dataBufPtr + 1)
00413 subb a,#((_diskSect + 0x0200) >> 8)
00414 jc 2122$
00415 ljmp 2108$
00416 2122$:
00417 mov _SPDAT,#0xFF
00418 mov dpl,_dataBufPtr
00419 mov dph,(_dataBufPtr + 1)
00420
00421 mov a,_SPSTA
00422 mov a,_SPDAT
00423 mov _SPDAT,#0xFF
00424 movx @dptr,a
00425 inc dptr
00426
00427 mov a,_SPSTA
00428 mov a,_SPDAT
00429 mov _SPDAT,#0xFF
00430 movx @dptr,a
00431 inc dptr
00432
00433 mov a,_SPSTA
00434 mov a,_SPDAT
00435 mov _SPDAT,#0xFF
00436 movx @dptr,a
00437 inc dptr
00438
00439 mov a,_SPSTA
00440 mov a,_SPDAT
00441 mov _SPDAT,#0xFF
00442 movx @dptr,a
00443 inc dptr
00444
00445 mov a,_SPSTA
00446 mov a,_SPDAT
00447 mov _SPDAT,#0xFF
00448 movx @dptr,a
00449 inc dptr
00450
00451 mov a,_SPSTA
00452 mov a,_SPDAT
00453 mov _SPDAT,#0xFF
00454 movx @dptr,a
00455 inc dptr
00456
00457 mov a,_SPSTA
00458 mov a,_SPDAT
00459 mov _SPDAT,#0xFF
00460 movx @dptr,a
00461 inc dptr
00462
00463 mov a,_SPSTA
00464 mov a,_SPDAT
00465 mov _SPDAT,#0xFF
00466 movx @dptr,a
00467 inc dptr
00468
00469 mov a,_SPSTA
00470 mov a,_SPDAT
00471 mov _SPDAT,#0xFF
00472 movx @dptr,a
00473 inc dptr
00474
00475 mov a,_SPSTA
00476 mov a,_SPDAT
00477 mov _SPDAT,#0xFF
00478 movx @dptr,a
00479 inc dptr
00480
00481 mov a,_SPSTA
00482 mov a,_SPDAT
00483 mov _SPDAT,#0xFF
00484 movx @dptr,a
00485 inc dptr
00486
00487 mov a,_SPSTA
00488 mov a,_SPDAT
00489 mov _SPDAT,#0xFF
00490 movx @dptr,a
00491 inc dptr
00492
00493 mov a,_SPSTA
00494 mov a,_SPDAT
00495 mov _SPDAT,#0xFF
00496 movx @dptr,a
00497 inc dptr
00498
00499 mov a,_SPSTA
00500 mov a,_SPDAT
00501 mov _SPDAT,#0xFF
00502 movx @dptr,a
00503 inc dptr
00504
00505 mov a,_SPSTA
00506 mov a,_SPDAT
00507 mov _SPDAT,#0xFF
00508 movx @dptr,a
00509 inc dptr
00510
00511 mov a,_SPSTA
00512 mov a,_SPDAT
00513 movx @dptr,a
00514 inc dptr
00515
00516
00517 mov a, dph
00518 mov (_dataBufPtr + 1),a
00519 mov a, dpl
00520 mov _dataBufPtr,a
00521
00522 ljmp 2106$
00523 2108$:
00524
00525 pop dph
00526 pop dpl
00527 pop acc
00528 mov r2,a
00529 pop acc
00530 pop psw
00531
00532 _endasm;
00533
00534
00535
00536
00537 #endif
00538
00539
00540
00541
00542 #ifdef MMCDEBUG
00543 ConsoleWrite("R>");
00544 #endif
00545
00546
00547
00548 }
00549
00550
00551
00555 Public unsigned char SeekSector(unsigned long sectorN){
00556 unsigned char c, retries;
00557
00558 retries = 0;
00559 do{
00560 retries++;
00561 sectorAddress.l = sectorN * 2;
00562 c=MmcCommand(0x51,sectorAddress.b.b2,sectorAddress.b.b1,
00563 sectorAddress.b.b0, 0);
00564 sectorAddress.l = sectorAddress.l >> 1;
00565
00566
00567 if (c!=0x00){
00568 if (c != 0xff){
00569
00570
00571 }
00572
00573 RebootMMC();
00574 if (retries > 10){
00575 return 7;
00576 }
00577 }
00578 }while(c!=0x00);
00579
00580 MMCDeselect();
00581
00582 return 0;
00583 }
00584
00585
00586
00587 Public unsigned char ReadPhysicalSector(){
00588
00589
00590
00591 MMCSelect();
00592 MmcWaitForData();
00593 PerformBlockRead();
00594
00595
00596
00597 SPI8Clocks(4);
00598 MMCDeselect();
00599 SPI8Clocks(4);
00600
00601
00602
00603 return 0;
00604 }
00605
00606
00607
00609 unsigned char WritePhysicalSector(){
00610 unsigned char c;
00611
00612 #ifdef MMCDEBUG
00613 ConsoleWrite("<W");
00614 #endif
00615
00616
00617
00618 sectorAddress.l = sectorAddress.l * 2;
00619 c=MmcCommand(0x40 | 24, sectorAddress.b.b2, sectorAddress.b.b1,
00620 sectorAddress.b.b0, 0);
00621 sectorAddress.l = sectorAddress.l >> 1;
00622
00623
00624
00625
00626 if (c!=0x00) return (c);
00627
00628
00629
00630
00631
00632
00633
00634
00635 SPIPutCharWithoutWaiting(0xFE);
00636 SPIWait();
00637
00638 for (c=0;c<32;c++){
00639 SPIPutCharWithoutWaiting(*dataBufPtr++);
00640 SPIPutCharWithoutWaiting(*dataBufPtr++);
00641 SPIPutCharWithoutWaiting(*dataBufPtr++);
00642 SPIPutCharWithoutWaiting(*dataBufPtr++);
00643 SPIPutCharWithoutWaiting(*dataBufPtr++);
00644 SPIPutCharWithoutWaiting(*dataBufPtr++);
00645 SPIPutCharWithoutWaiting(*dataBufPtr++);
00646 SPIPutCharWithoutWaiting(*dataBufPtr++);
00647 SPIPutCharWithoutWaiting(*dataBufPtr++);
00648 SPIPutCharWithoutWaiting(*dataBufPtr++);
00649 SPIPutCharWithoutWaiting(*dataBufPtr++);
00650 SPIPutCharWithoutWaiting(*dataBufPtr++);
00651 SPIPutCharWithoutWaiting(*dataBufPtr++);
00652 SPIPutCharWithoutWaiting(*dataBufPtr++);
00653 SPIPutCharWithoutWaiting(*dataBufPtr++);
00654 SPIPutCharWithoutWaiting(*dataBufPtr++);
00655 }
00656
00657
00658 c = SPIGetChar();
00659 c = SPIGetChar();
00660 c = SPIGetChar();
00661
00662
00663
00664
00665
00666 #ifdef MMCDEBUG
00667 ConsoleWrite("W>");
00668 #endif
00669
00670
00671 SPI8Clocks(16);
00672 MMCDeselect();
00673 SPI8Clocks(16);
00674
00675
00676
00677 return 0;
00678 }
00679
00680
00681
00682
00683