00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00059 #define USE_SOCKSWITCHES 1
00060 #define USE_POWERCONTROL 1
00061 #define USE_FIFO 1
00062
00063 #include "sceptre.h"
00064 #include "diskio.h"
00065 #include "sdcard.h"
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 #define CT_MMC 0x01
00076 #define CT_SD1 0x02
00077 #define CT_SD2 0x04
00078 #define CT_SDC (CT_SD1|CT_SD2)
00079 #define CT_BLOCK 0x08
00080
00081
00082
00083 #define CMD0 (0x40+0)
00084 #define CMD1 (0x40+1)
00085 #define ACMD41 (0xC0+41)
00086 #define CMD8 (0x40+8)
00087 #define CMD9 (0x40+9)
00088 #define CMD10 (0x40+10)
00089 #define CMD12 (0x40+12)
00090 #define ACMD13 (0xC0+13)
00091 #define CMD16 (0x40+16)
00092 #define CMD17 (0x40+17)
00093 #define CMD18 (0x40+18)
00094 #define CMD23 (0x40+23)
00095 #define ACMD23 (0xC0+23)
00096 #define CMD24 (0x40+24)
00097 #define CMD25 (0x40+25)
00098 #define CMD55 (0x40+55)
00099 #define CMD58 (0x40+58)
00100
00101 #define SOCKWP 0x20
00102 #define SOCKINS 0x10
00103
00104 static volatile
00105 DSTATUS Stat = STA_NOINIT;
00106
00107 static volatile
00108 BYTE Timer1, Timer2;
00109
00110 static
00111 BYTE CardType;
00112
00113
00114
00115
00116
00117
00118
00119
00120 #if USE_SOCKSWITCHES
00121
00122
00123 #ifndef SD_SOCKET_WP_PIN
00124
00125 #define SD_SOCKET_WP_PIN 24
00126 #define SD_SOCKET_WP_DIR IODIR1
00127 #define SD_SOCKET_WP_IN IOPIN1
00128 #endif
00129 #ifndef SD_SOCKET_INS_PIN
00131 #define SD_SOCKET_INS_PIN 25
00132 #define SD_SOCKET_INS_DIR IODIR1
00133 #define SD_SOCKET_INS_IN IOPIN1
00134 #endif
00135
00136 static inline BYTE get_SOCKWP(void)
00137 {
00138 return ( SD_SOCKET_WP_IN & (1UL << SD_SOCKET_WP_PIN) ) ? SOCKWP : 0 ;
00139 }
00140 static inline BYTE get_SOCKINS(void)
00141 {
00142 return ( SD_SOCKET_INS_IN & (1UL <<SD_SOCKET_INS_PIN) ) ? SOCKINS : 0 ;
00143 }
00144
00145 static void init_SOCKWP_SOCKINS( void )
00146 {
00147 SD_SOCKET_INS_DIR &= ~(1UL << SD_SOCKET_INS_PIN);
00148 SD_SOCKET_WP_DIR &= ~(1UL << SD_SOCKET_WP_PIN);
00149 }
00150
00151 bool_t sdcard_detect(void);
00152 bool_t sdcard_detect(void)
00153 {
00154 return (SD_SOCKET_INS_IN&(1UL<<SD_SOCKET_INS_PIN))==0? true : false;
00155 }
00156
00157 bool_t sdcard_write_protected(void);
00158 bool_t sdcard_write_protected(void)
00159 {
00160 return (SD_SOCKET_WP_IN&(1UL<<SD_SOCKET_WP_PIN))==0? false : true;
00161 }
00162
00163 #else
00164
00165 static inline BYTE get_SOCKWP(void)
00166 {
00167 return 0;
00168 }
00169 static inline BYTE get_SOCKINS(void)
00170 {
00171 return 0;
00172 }
00173 static void init_SOCKWP_SOCKINS( void )
00174 {
00175 return;
00176 }
00177
00178 #endif
00179
00180
00181 #if USE_POWERCONTROL
00182
00183
00184
00185
00186 #ifndef SD_SOCKET_POWER_PIN
00187
00188 #define SD_SOCKET_POWER_PIN 16
00189 #define SD_SOCKET_POWER_DIR IODIR1
00190 #define SD_SOCKET_POWER_IN IOPIN1
00191 #define SD_SOCKET_POWER_SET IOSET1
00192 #define SD_SOCKET_POWER_CLR IOCLR1
00193 #endif
00194
00195 static inline void set_SOCKPOWER(bool_t on)
00196 {
00197 if (on)
00198 {
00199 SD_SOCKET_POWER_CLR = (1UL<<SD_SOCKET_POWER_PIN);
00200 }
00201 else
00202 {
00203 SD_SOCKET_POWER_SET = (1UL<<SD_SOCKET_POWER_PIN);
00204 }
00205 }
00206
00207
00208 static inline bool_t get_SOCKPOWER(void)
00209 {
00210 return (SD_SOCKET_POWER_IN&(1<<SD_SOCKET_POWER_PIN))==0;
00211 }
00212
00213 static void init_SOCKPOWER(void)
00214 {
00215 SD_SOCKET_POWER_DIR |= (1UL<<SD_SOCKET_POWER_PIN);
00216 }
00217
00218 #else
00219 #error SD card needs power control
00220 static inline void set_SOCKPOWER( bool_t on )
00221 {
00222 on = on;
00223 return;
00224 }
00225
00226 static inline bool_t get_SOCKPOWER( void )
00227 {
00228 return true;
00229 }
00230 static void init_SOCKPOWER( void )
00231 {
00232 return;
00233 }
00234
00235 #endif
00236
00237
00238
00239
00240
00241
00242 #define SSPCR0_DSS 0
00243 #define SSPCR0_CPOL 6
00244 #define SSPCR0_CPHA 7
00245 #define SSPCR0_SCR 8
00246 #define SSPCR1_SSE 1
00247 #define SSPSR_TNF 1
00248 #define SSPSR_RNE 2
00249 #define SSPSR_BSY 4
00250
00251 #define PCONP_PCSPI1 10
00252
00253 #define SD_CS_BIT 20
00254 #define SD_CS_DIR IODIR0
00255 #define SD_CS_SET IOSET0
00256 #define SD_CS_CLR IOCLR0
00257 #define SD_CS_SEL PINSEL1
00258 #define SD_CS_SEL_BIT 8
00259
00260
00261 #define SPI_SPEED_20MHz 4
00262 #define SPI_SPEED_25MHz 4
00263 #define SPI_SPEED_400kHz 150
00264
00265
00266
00267 static inline void SELECT( void )
00268 {
00269 SD_CS_CLR = ( 1UL << SD_CS_BIT );
00270 }
00271
00272
00273 static inline void DESELECT( void )
00274 {
00275 SD_CS_SET = ( 1UL << SD_CS_BIT );
00276 }
00277
00278
00279 static void spiSetSpeed(BYTE speed)
00280 {
00281 speed &= 0xFE;
00282 if (speed<2) speed = 2;
00283 SSPCPSR = speed;
00284 }
00285
00286
00287 static inline BYTE spi_write_read(BYTE outgoing)
00288 {
00289 BYTE incoming;
00290
00292 SSPDR = outgoing;
00293 while ((SSPSR&(1<<SSPSR_RNE))==0)
00294 {
00295 }
00296 incoming = SSPDR;
00297
00298 return incoming;
00299 }
00300
00301
00302 #if USE_FIFO
00303
00304 #define FIFO_ELEM 8
00305
00306
00307
00308
00309 static inline void spi_rcvr_block(BYTE *buff, UINT btr)
00310 {
00311 UINT hwtr, startcnt, i, rec;
00312
00313 hwtr = btr/2;
00314 if (btr<FIFO_ELEM)
00315 {
00316 startcnt = hwtr;
00317 }
00318 else
00319 {
00320 startcnt = FIFO_ELEM;
00321 }
00322
00323 SSPCR0 |= 0x0000000f;
00324
00325 for (i=startcnt; i; i--)
00326 {
00327 SSPDR = 0xffff;
00328 }
00329
00330 do
00331 {
00332 while ((SSPSR&(1<<SSPSR_RNE))==0)
00333 {
00334
00335 }
00336 rec = SSPDR;
00337 if (i<(hwtr-startcnt))
00338 {
00339 SSPDR = 0xffff;
00340 }
00341 *buff++ = (BYTE)(rec>>8);
00342 *buff++ = (BYTE)(rec);
00343 i++;
00344 }
00345 while (i<hwtr);
00346
00347 SSPCR0 &= ~0x00000008;
00348 }
00349
00350
00351
00352
00353 static inline void spi_xmit_block(const BYTE *buff)
00354 {
00355 UINT cnt;
00356 WORD data;
00357
00358 SSPCR0 |= 0x0000000f;
00359
00360 for (cnt=0; cnt<(512/2); cnt++)
00361 {
00362 while ((SSPSR&(1<<SSPSR_TNF))==0)
00363 {
00364
00365 }
00366 data = (*buff++) << 8;
00367 data |= *buff++;
00368 SSPDR = data;
00369 }
00370
00371 while ((SSPSR&(1<<SSPSR_BSY))!=0)
00372 {
00373
00374 }
00375 while ((SSPSR&(1<<SSPSR_RNE))!=0)
00376 {
00377 data = SSPDR;
00378 }
00379
00380 SSPCR0 &= ~0x00000008;
00381 }
00382 #endif
00383
00384
00385 static void init_spi( void )
00386 {
00387 UINT dummy;
00388
00389
00390 SD_CS_SEL = (SD_CS_SEL & ~(3UL<<SD_CS_SEL_BIT));
00391 SD_CS_DIR |= (1UL << SD_CS_BIT);
00392 DESELECT();
00393
00394
00395 PCONP |= (1UL << PCONP_PCSPI1);
00396
00397
00398 PINSEL1 &= ~(
00399 (3UL << 2) |
00400 (3UL << 4) |
00401 (3UL << 6) |
00402 (3UL << 8)
00403 );
00404
00405 PINSEL1 |= (
00406 (2UL << 2) |
00407 (2UL << 4) |
00408 (2UL << 6)
00409
00410 );
00411
00412
00413 SSPCR0 = ((8-1)<<SSPCR0_DSS) | (0<<SSPCR0_CPOL) | (0<<SSPCR0_CPHA) | (0<<SSPCR0_SCR);
00414 SSPCR1 = (1<<SSPCR1_SSE);
00415
00416
00417 spiSetSpeed(SPI_SPEED_400kHz);
00418
00419
00420 while ((SSPSR&(1<<SSPSR_BSY))!=0)
00421 {
00422
00423 }
00424
00425 while ((SSPSR&(1<<SSPSR_RNE))!=0)
00426 {
00427 dummy = SSPDR;
00428 }
00429 }
00430
00431
00432 static void close_spi( void )
00433 {
00434
00435 SSPCR1 = 0;
00436
00437
00438 PINSEL1 &= ~(
00439 (3UL << 2) |
00440 (3UL << 4) |
00441 (3UL << 6) |
00442 (3UL << 8)
00443 );
00444
00445
00446 PCONP &= ~(1UL << PCONP_PCSPI1);
00447
00448 }
00449
00450
00451
00452
00453
00454
00455
00456 static inline void xmit_spi( BYTE dat )
00457 {
00458 spi_write_read( dat );
00459 }
00460
00461
00462
00463
00464
00465 static inline BYTE rcvr_spi (void)
00466 {
00467 return spi_write_read( 0xff );
00468 }
00469
00470
00471 static inline void rcvr_spi_m( BYTE *dst )
00472 {
00473 *dst = rcvr_spi();
00474 }
00475
00476
00477
00478
00479
00480
00481
00482 static
00483 BYTE wait_ready (void)
00484 {
00485 BYTE res;
00486
00487
00488 Timer2 = 50;
00489 rcvr_spi();
00490 do
00491 res = rcvr_spi();
00492 while ((res != 0xFF) && Timer2);
00493
00494 return res;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503 static
00504 void release_spi (void)
00505 {
00506 DESELECT();
00507 rcvr_spi();
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 static
00519 void power_on (void)
00520 {
00521 init_SOCKPOWER();
00522 set_SOCKPOWER( true );
00523 timer_wait_ms(100);
00524
00525 init_SOCKWP_SOCKINS();
00526 init_spi();
00527 }
00528
00529 static
00530 void power_off (void)
00531 {
00532 SELECT();
00533 wait_ready();
00534 close_spi();
00535 set_SOCKPOWER( false );
00536 Stat |= STA_NOINIT;
00537 }
00538
00539 static
00540 int chk_power(void)
00541 {
00542 return ( get_SOCKPOWER() ) ? 1 : 0;
00543 }
00544
00545
00546
00547
00548
00549
00550
00551 static
00552 bool_t rcvr_datablock (
00553 BYTE *buff,
00554 UINT btr
00555 )
00556 {
00557 BYTE token;
00558
00559
00560 Timer1 = 10;
00561 do {
00562 token = rcvr_spi();
00563 } while ((token == 0xFF) && Timer1);
00564 if(token != 0xFE) return false;
00565
00566 #if USE_FIFO
00567 spi_rcvr_block( buff, btr );
00568 #else
00569 do {
00570 rcvr_spi_m(buff++);
00571 rcvr_spi_m(buff++);
00572 rcvr_spi_m(buff++);
00573 rcvr_spi_m(buff++);
00574 } while (btr -= 4);
00575 #endif
00576 rcvr_spi();
00577 rcvr_spi();
00578
00579 return true;
00580 }
00581
00582
00583
00584
00585
00586
00587
00588 #if _READONLY == 0
00589 static
00590 bool_t xmit_datablock (
00591 const BYTE *buff,
00592 BYTE token
00593 )
00594 {
00595 BYTE resp, wc;
00596
00597
00598 if (wait_ready() != 0xFF) return false;
00599
00600 xmit_spi(token);
00601 if (token != 0xFD) {
00602 wc = 0;
00603 #if USE_FIFO
00604 spi_xmit_block( buff );
00605 #else
00606 do {
00607 xmit_spi(*buff++);
00608 xmit_spi(*buff++);
00609 } while (--wc);
00610 #endif
00611 xmit_spi(0xFF);
00612 xmit_spi(0xFF);
00613 resp = rcvr_spi();
00614 if ((resp & 0x1F) != 0x05)
00615 return false;
00616 }
00617
00618 return true;
00619 }
00620 #endif
00621
00622
00623
00624
00625
00626
00627
00628 static
00629 BYTE send_cmd (
00630 BYTE cmd,
00631 DWORD arg
00632 )
00633 {
00634 BYTE n, res;
00635
00636
00637 if (cmd & 0x80) {
00638 cmd &= 0x7F;
00639 res = send_cmd(CMD55, 0);
00640 if (res > 1) return res;
00641 }
00642
00643
00644 DESELECT();
00645 SELECT();
00646 if (wait_ready() != 0xFF) return 0xFF;
00647
00648
00649 xmit_spi(cmd);
00650 xmit_spi((BYTE)(arg >> 24));
00651 xmit_spi((BYTE)(arg >> 16));
00652 xmit_spi((BYTE)(arg >> 8));
00653 xmit_spi((BYTE)arg);
00654 n = 0x01;
00655 if (cmd == CMD0) n = 0x95;
00656 if (cmd == CMD8) n = 0x87;
00657 xmit_spi(n);
00658
00659
00660 if (cmd == CMD12) rcvr_spi();
00661 n = 10;
00662 do
00663 res = rcvr_spi();
00664 while ((res & 0x80) && --n);
00665
00666 return res;
00667 }
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682 DSTATUS disk_initialize (
00683 BYTE drv
00684 )
00685 {
00686
00687 if (Stat!=STA_NOINIT && Stat!=STA_NODISK && Stat!=STA_PROTECT) return Stat;
00688
00689 BYTE n, cmd, ty, ocr[4];
00690
00691 #if 0
00692 static BYTE pv;
00693 pv = get_SOCKWP() | get_SOCKINS();
00694 if (pv & SOCKINS)
00695 xprintf("not inserted\n");
00696 else {
00697
00698 xprintf("inserted\n");
00699 if (pv & SOCKWP)
00700 xprintf("protected\n");
00701 else
00702
00703 xprintf("unprotected\n");
00704 }
00705 #endif
00706
00707 if (drv) return STA_NOINIT;
00708 if (Stat & STA_NODISK) return Stat;
00709
00710 power_on();
00711 for (n = 10; n; n--) rcvr_spi();
00712
00713 ty = 0;
00714 if (send_cmd(CMD0, 0) == 1) {
00715 Timer1 = 100;
00716 if (send_cmd(CMD8, 0x1AA) == 1) {
00717 for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
00718 if (ocr[2] == 0x01 && ocr[3] == 0xAA) {
00719 while (Timer1 && send_cmd(ACMD41, 1UL << 30));
00720 if (Timer1 && send_cmd(CMD58, 0) == 0) {
00721 for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
00722 ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;
00723 }
00724 }
00725 } else {
00726 if (send_cmd(ACMD41, 0) <= 1) {
00727 ty = CT_SD1; cmd = ACMD41;
00728 } else {
00729 ty = CT_MMC; cmd = CMD1;
00730 }
00731 while (Timer1 && send_cmd(cmd, 0));
00732 if (!Timer1 || send_cmd(CMD16, 512) != 0)
00733 ty = 0;
00734 }
00735 }
00736 CardType = ty;
00737 release_spi();
00738
00739 if (ty) {
00740 Stat &= ~STA_NOINIT;
00741 if ( ty == CT_MMC ) {
00742 spiSetSpeed(SPI_SPEED_20MHz);
00743 } else {
00744 spiSetSpeed(SPI_SPEED_25MHz);
00745 }
00746 } else {
00747 power_off();
00748 }
00749
00750 return Stat;
00751 }
00752
00753
00754
00755
00756
00757
00758
00759 DSTATUS disk_status (
00760 BYTE drv
00761 )
00762 {
00763 if (drv) return STA_NOINIT;
00764 return Stat;
00765 }
00766
00767
00768
00769
00770
00771
00772
00773 DRESULT disk_read (
00774 BYTE drv,
00775 BYTE *buff,
00776 DWORD sector,
00777 BYTE count
00778 )
00779 {
00780 if (drv || !count) return RES_PARERR;
00781 if (Stat & STA_NOINIT) return RES_NOTRDY;
00782
00783 if (!(CardType & CT_BLOCK)) sector *= 512;
00784
00785 if (count == 1) {
00786 if ((send_cmd(CMD17, sector) == 0)
00787 && rcvr_datablock(buff, 512))
00788 count = 0;
00789 }
00790 else {
00791 if (send_cmd(CMD18, sector) == 0) {
00792 do {
00793 if (!rcvr_datablock(buff, 512)) break;
00794 buff += 512;
00795 } while (--count);
00796 send_cmd(CMD12, 0);
00797 }
00798 }
00799 release_spi();
00800
00801 return count ? RES_ERROR : RES_OK;
00802 }
00803
00804
00805
00806
00807
00808
00809
00810 #if _READONLY == 0
00811 DRESULT disk_write (
00812 BYTE drv,
00813 const BYTE *buff,
00814 DWORD sector,
00815 BYTE count
00816 )
00817 {
00818 if (drv || !count) return RES_PARERR;
00819 if (Stat & STA_NOINIT) return RES_NOTRDY;
00820 if (Stat & STA_PROTECT) return RES_WRPRT;
00821
00822 if (!(CardType & CT_BLOCK)) sector *= 512;
00823
00824 if (count == 1) {
00825 if ((send_cmd(CMD24, sector) == 0)
00826 && xmit_datablock(buff, 0xFE))
00827 count = 0;
00828 }
00829 else {
00830 if (CardType & CT_SDC) send_cmd(ACMD23, count);
00831 if (send_cmd(CMD25, sector) == 0) {
00832 do {
00833 if (!xmit_datablock(buff, 0xFC)) break;
00834 buff += 512;
00835 } while (--count);
00836 if (!xmit_datablock(0, 0xFD))
00837 count = 1;
00838 }
00839 }
00840 release_spi();
00841
00842 return count ? RES_ERROR : RES_OK;
00843 }
00844 #endif
00845
00846
00847
00848
00849
00850
00851
00852 #if _USE_IOCTL != 0
00853 DRESULT disk_ioctl (
00854 BYTE drv,
00855 BYTE ctrl,
00856 void *buff
00857 )
00858 {
00859 DRESULT res;
00860 BYTE n, csd[16], *ptr = buff;
00861 WORD csize;
00862
00863
00864 if (drv) return RES_PARERR;
00865
00866 res = RES_ERROR;
00867
00868 if (ctrl == CTRL_POWER) {
00869 switch (*ptr) {
00870 case 0:
00871 if (chk_power())
00872 power_off();
00873 res = RES_OK;
00874 break;
00875 case 1:
00876 power_on();
00877 res = RES_OK;
00878 break;
00879 case 2:
00880 *(ptr+1) = (BYTE)chk_power();
00881 res = RES_OK;
00882 break;
00883 default :
00884 res = RES_PARERR;
00885 }
00886 }
00887 else {
00888 if (Stat & STA_NOINIT) return RES_NOTRDY;
00889
00890 switch (ctrl) {
00891 case CTRL_SYNC :
00892 SELECT();
00893 if (wait_ready() == 0xFF)
00894 res = RES_OK;
00895 break;
00896
00897 case GET_SECTOR_COUNT :
00898 if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
00899 if ((csd[0] >> 6) == 1) {
00900 csize = csd[9] + ((WORD)csd[8] << 8) + 1;
00901 *(DWORD*)buff = (DWORD)csize << 10;
00902 } else {
00903 n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
00904 csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
00905 *(DWORD*)buff = (DWORD)csize << (n - 9);
00906 }
00907 res = RES_OK;
00908 }
00909 break;
00910
00911 case GET_SECTOR_SIZE :
00912 *(WORD*)buff = 512;
00913 res = RES_OK;
00914 break;
00915
00916 case GET_BLOCK_SIZE :
00917 if (CardType & CT_SD2) {
00918 if (send_cmd(ACMD13, 0) == 0) {
00919 rcvr_spi();
00920 if (rcvr_datablock(csd, 16)) {
00921 for (n = 64 - 16; n; n--) rcvr_spi();
00922 *(DWORD*)buff = 16UL << (csd[10] >> 4);
00923 res = RES_OK;
00924 }
00925 }
00926 } else {
00927 if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
00928 if (CardType & CT_SD1) {
00929 *(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
00930 } else {
00931 *(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
00932 }
00933 res = RES_OK;
00934 }
00935 }
00936 break;
00937
00938 case MMC_GET_TYPE :
00939 *ptr = CardType;
00940 res = RES_OK;
00941 break;
00942
00943 case MMC_GET_CSD :
00944 if (send_cmd(CMD9, 0) == 0
00945 && rcvr_datablock(ptr, 16))
00946 res = RES_OK;
00947 break;
00948
00949 case MMC_GET_CID :
00950 if (send_cmd(CMD10, 0) == 0
00951 && rcvr_datablock(ptr, 16))
00952 res = RES_OK;
00953 break;
00954
00955 case MMC_GET_OCR :
00956 if (send_cmd(CMD58, 0) == 0) {
00957 for (n = 4; n; n--) *ptr++ = rcvr_spi();
00958 res = RES_OK;
00959 }
00960 break;
00961
00962 case MMC_GET_SDSTAT :
00963 if (send_cmd(ACMD13, 0) == 0) {
00964 rcvr_spi();
00965 if (rcvr_datablock(ptr, 64))
00966 res = RES_OK;
00967 }
00968 break;
00969
00970 default:
00971 res = RES_PARERR;
00972 }
00973
00974 release_spi();
00975 }
00976
00977 return res;
00978 }
00979 #endif
00980
00981
00982
00983
00984
00985
00986
00987 void disk_timerproc(void)
00988 {
00989 static BYTE pv;
00990 BYTE n, s;
00991
00992 n = Timer1;
00993 if (n) Timer1 = --n;
00994 n = Timer2;
00995 if (n) Timer2 = --n;
00996
00997 n = pv;
00998 pv = get_SOCKWP() | get_SOCKINS();
00999
01000 if (n==pv)
01001 {
01002
01003 s = Stat;
01004
01005 if (pv&SOCKWP) s |= STA_PROTECT;
01006 else s &= ~STA_PROTECT;
01007
01008 if (pv&SOCKINS) s |= (STA_NODISK|STA_NOINIT);
01009 else s &= ~STA_NODISK;
01010
01011 Stat = s;
01012 }
01013 }
01014
01015
01016 bool_t SDInit(void)
01017 {
01018 return disk_initialize(0)==0;
01019 }
01020
01021 bool_t SDReadCSD(BYTE *pbCSD)
01022 {
01023 return disk_ioctl(0,MMC_GET_CSD,pbCSD)==RES_OK;
01024 }
01025
01026 bool_t SDReadCID(BYTE *pbCID)
01027 {
01028 return disk_ioctl(0,MMC_GET_CID,pbCID)==RES_OK;
01029 }
01030
01031 bool_t SDReadOCR(DWORD *pulOCR)
01032 {
01033 return disk_ioctl(0,MMC_GET_OCR,pulOCR)==RES_OK;
01034 }
01035
01036 bool_t SDReadBlock(BYTE *pbData, DWORD ulBlock)
01037 {
01038 return disk_read(0,pbData,ulBlock,1)==RES_OK;
01039 }
01040
01041 bool_t SDWriteBlock(const BYTE *pbData, DWORD ulBlock)
01042 {
01043 return disk_write(0,pbData,ulBlock,1)==RES_OK;
01044 }