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
00059 #include <cfg/arch.h>
00060 #include <cfg/arch/gpio.h>
00061 #include <cfg/mmci.h>
00062
00063 #include <errno.h>
00064 #include <string.h>
00065 #include <stdlib.h>
00066
00067 #include <sys/heap.h>
00068 #include <sys/timer.h>
00069 #include <sys/event.h>
00070 #include <fs/dospart.h>
00071 #include <fs/fs.h>
00072
00073 #include <dev/blockdev.h>
00074 #include <dev/mmcard.h>
00075 #include <dev/at91_mci.h>
00076
00077
00078 #if 0
00079
00080 #define NUTDEBUG
00081 #include <stdio.h>
00082 #endif
00083
00088
00089 #ifndef MMC_BLOCK_SIZE
00090 #define MMC_BLOCK_SIZE 512
00091 #endif
00092
00093 #ifndef MCI_INI_BITRATE
00094
00095 #define MCI_INI_BITRATE 400000
00096 #endif
00097
00098 #ifndef MCI_MMC_BITRATE
00099
00100 #define MCI_MMC_BITRATE 20000000
00101 #endif
00102
00103 #ifndef MCI_SDC_BITRATE
00104
00105 #define MCI_SDC_BITRATE 25000000
00106 #endif
00107
00108 #ifndef MMCARD_VRANGE
00109 #define MMCARD_VRANGE (MMCARD_32_33V | MMCARD_31_32V | MMCARD_30_31V)
00110 #endif
00111
00112 #ifdef MCI_SLOTA
00113
00114 #ifndef MMC_PINS_A
00115 #define MMC_PINS_A _BV(PA6_MCDA0_A) | _BV(PA7_MCCDA_A) | _BV(PA8_MCCK_A) | _BV(PA9_MCDA1_A) | _BV(PA10_MCDA2_A) | _BV(PA11_MCDA3_A)
00116 #endif
00117
00118 #ifndef MMC_PINS_B
00119 #define MMC_PINS_B 0
00120 #endif
00121
00122 #else
00123
00124 #ifndef MMC_PINS_A
00125 #define MMC_PINS_A _BV(PA8_MCCK_A)
00126 #endif
00127
00128 #ifndef MMC_PINS_B
00129 #define MMC_PINS_B _BV(PA1_MCCDB_B) | _BV(PA0_MCDB0_B) | _BV(PA5_MCDB1_B) | _BV(PA4_MCDB2_B) | _BV(PA3_MCDB3_B)
00130 #endif
00131
00132 #endif
00133
00134 #define MCICMD_ALL_SEND_CID (MMCMD_ALL_SEND_CID | MCI_MAXLAT | MCI_RSPTYP_136)
00135 #define MCICMD_DESELECT_CARD (MMCMD_SELECT_CARD)
00136 #define MCICMD_GO_IDLE_STATE (MMCMD_GO_IDLE_STATE)
00137 #define MCICMD_READ_SINGLE_BLOCK (MMCMD_READ_SINGLE_BLOCK | MCI_TRCMD_START | MCI_TRDIR | MCI_MAXLAT | MCI_RSPTYP_48)
00138 #define MCICMD_SELECT_CARD (MMCMD_SELECT_CARD | MCI_MAXLAT | MCI_RSPTYP_48)
00139 #define MCICMD_SEND_APP_CMD (MMCMD_SEND_APP_CMD | MCI_MAXLAT | MCI_RSPTYP_48)
00140 #define MCICMD_SEND_APP_OP_COND (MMCMD_SEND_APP_OP_COND | MCI_MAXLAT | MCI_RSPTYP_48)
00141 #define MCICMD_SEND_OP_COND (MMCMD_SEND_OP_COND | MCI_MAXLAT | MCI_RSPTYP_48)
00142 #define MCICMD_SEND_RELATIVE_ADDR (MMCMD_SEND_RELATIVE_ADDR | MCI_MAXLAT | MCI_RSPTYP_48)
00143 #define MCICMD_SEND_STATUS (MMCMD_SEND_STATUS | MCI_MAXLAT | MCI_RSPTYP_48)
00144 #define MCICMD_SET_BLOCKLEN (MMCMD_SET_BLOCKLEN | MCI_MAXLAT | MCI_RSPTYP_48)
00145 #define MCICMD_WRITE_BLOCK (MMCMD_WRITE_BLOCK | MCI_TRCMD_START | MCI_MAXLAT | MCI_RSPTYP_48)
00146
00147 #define MCICMD_IERROR (MCI_RTOE | MCI_RENDE | MCI_RDIRE | MCI_RINDE)
00148 #define MCICMD_ERROR (MCI_UNRE | MCI_OVRE | MCI_DTOE | MCI_DCRCE | MCI_RCRCE | MCICMD_IERROR)
00149
00150 #define MCIFLG_SDCARD 0x00000001
00151 #define MCIFLG_4BIT 0x00000010
00152
00156 typedef struct _MCIFC {
00158 uint32_t ifc_config;
00160 uint32_t ifc_opcond;
00162 uint32_t ifc_reladdr;
00164 uint8_t *ifc_buff;
00166 uint32_t ifc_resp[4];
00168 uint32_t ifc_cid[4];
00169 } MCIFC;
00170
00174 typedef struct _MCIFCB {
00177 NUTDEVICE *fcb_fsdev;
00178
00181 DOSPART fcb_part;
00182
00190 uint32_t fcb_blknum;
00191
00201 uint8_t fcb_blkbuf[MMC_BLOCK_SIZE];
00202 } MCIFCB;
00203
00204
00205
00206
00207
00208
00209 static HANDLE mutex;
00210
00216 static uint32_t At91MciClockDiv(uint32_t clk)
00217 {
00218 uint32_t rc;
00219
00220
00221 rc = NutArchClockGet(NUT_HWCLK_PERIPHERAL) / 2;
00222
00223 rc += clk - 10000;
00224
00225 rc /= clk;
00226
00227 if (rc) {
00228 rc -= 1;
00229 }
00230
00231
00232 if (rc > 255) {
00233 rc = 255;
00234 }
00235 return rc;
00236 }
00237
00244 static void At91MciReset(int init)
00245 {
00246 uint32_t mode;
00247 uint32_t dtmo;
00248 uint32_t slot;
00249
00250
00251 outr(PMC_PCER, _BV(MCI_ID));
00252
00253 if (init) {
00254 outr(MCI_IDR, 0xFFFFFFFF);
00255
00256 dtmo = MCI_DTOMUL_1M | MCI_DTOCYC;
00257 mode = MCI_RDPROOF | MCI_WRPROOF | (2 << MCI_PWSDIV_LSB);
00258
00259 mode |= At91MciClockDiv(MCI_INI_BITRATE) << MCI_CLKDIV_LSB;
00260 #ifdef MCI_SLOTA
00261 slot = MCI_SDCSEL_SLOTA;
00262 #else
00263 slot = MCI_SDCSEL_SLOTB;
00264 #endif
00265 } else {
00266
00267 dtmo = inr(MCI_DTOR);
00268 mode = inr(MCI_MR) & 0xffff;
00269 slot = inr(MCI_SDCR);
00270 }
00271
00272
00273 outr(MCI_CR, MCI_MCIDIS | MCI_SWRST);
00274
00275
00276 outr(MCI_DTOR, dtmo);
00277 outr(MCI_MR, mode);
00278 outr(MCI_SDCR, slot);
00279
00280
00281 outr(MCI_CR, MCI_MCIEN | MCI_PWSEN);
00282 }
00283
00284 static void At91MciEnablePins(void)
00285 {
00286
00287 outr(PIOA_PDR, MMC_PINS_A | MMC_PINS_B);
00288
00289 outr(PIOA_ASR, MMC_PINS_A);
00290 outr(PIOA_BSR, MMC_PINS_B);
00291 }
00292
00293 static void At91MciDisablePins(void)
00294 {
00295 #ifdef MCI0_PIN_SHARING
00296
00297 outr(PIOA_ODR, MMC_PINS_A | MMC_PINS_B);
00298 outr(PIOA_PER, MMC_PINS_A | MMC_PINS_B);
00299 #endif
00300 }
00301
00310 static int At91MciInit(NUTDEVICE * dev)
00311 {
00312
00313 At91MciReset(1);
00314
00315 return 0;
00316 }
00317
00327 static uint32_t At91MciTxCmd(MCIFC * ifc, uint32_t cmd, uint32_t param)
00328 {
00329 uint32_t sr;
00330 uint32_t rl;
00331 uint32_t i;
00332 uint32_t wfs = MCI_CMDRDY;
00333 uint32_t ces = MCICMD_IERROR;
00334
00335
00336
00337
00338 #ifdef NUTDEBUG
00339 printf("[Cmd%lu,%lx]", cmd & MCI_CMDNB, param);
00340 #endif
00341 outr(MCI_PTCR, PDC_TXTDIS | PDC_RXTDIS);
00342 outr(MCI_MR, inr(MCI_MR) & ~(MCI_BLKLEN | MCI_PDCMODE));
00343 outr(MCI_RCR, 0);
00344 outr(MCI_RNCR, 0);
00345 outr(MCI_TCR, 0);
00346 outr(MCI_TNCR, 0);
00347
00348 if (cmd & MCI_TRCMD_START) {
00349
00350 if (ifc->ifc_buff == NULL) {
00351 errno = EINVAL;
00352 return MCI_OVRE | MCI_UNRE;
00353 }
00354
00355 outr(MCI_MR, (inr(MCI_MR) & ~MCI_BLKLEN) | (MMC_BLOCK_SIZE << MCI_BLKLEN_LSB) | MCI_PDCMODE);
00356 if (cmd & MCI_TRDIR) {
00357
00358 outr(MCI_RPR, (uint32_t) ifc->ifc_buff);
00359 outr(MCI_RCR, MMC_BLOCK_SIZE / 4);
00360
00361 outr(MCI_PTCR, PDC_RXTEN);
00362
00363 wfs = MCI_ENDRX;
00364 } else {
00365
00366 outr(MCI_TPR, (uint32_t) ifc->ifc_buff);
00367 outr(MCI_TCR, MMC_BLOCK_SIZE / 4);
00368
00369 wfs = MCI_BLKE;
00370 }
00371 }
00372
00373 outr(MCI_ARGR, param);
00374 outr(MCI_CMDR, cmd);
00375
00376
00377 if ((cmd & (MCI_TRCMD_START | MCI_TRDIR)) == MCI_TRCMD_START) {
00378 outr(MCI_PTCR, PDC_TXTEN);
00379 }
00380
00381
00382 switch (cmd & MCI_RSPTYP) {
00383 case MCI_RSPTYP_48:
00384 rl = 2;
00385 break;
00386 case MCI_RSPTYP_136:
00387 rl = 4;
00388 break;
00389 default:
00390 rl = 0;
00391 break;
00392 }
00393
00394 while (((sr = inr(MCI_SR)) & wfs) == 0);
00395
00396 if (sr & ces) {
00397 return sr;
00398 }
00399
00400 for (i = 0; i < rl; i++) {
00401 ifc->ifc_resp[i] = inr(MCI_RSPR);
00402 }
00403 #ifdef NUTDEBUG
00404 printf("[Sta=%lx]", sr);
00405 if (rl) {
00406 printf("[Rsp");
00407 for (i = 0; i < rl; i++) {
00408 printf(" %lx", ifc->ifc_resp[i]);
00409 }
00410 putchar(']');
00411 }
00412 putchar('\n');
00413 #endif
00414
00415 if (wfs & MCI_BLKE) {
00416 while ((inr(MCI_SR) & MCI_NOTBUSY) == 0);
00417 }
00418
00419 ifc->ifc_buff = NULL;
00420
00421 return sr;
00422 }
00423
00434 static int At91MciDiscover(MCIFC * ifc)
00435 {
00436 uint32_t sr;
00437 uint32_t clk = MCI_MMC_BITRATE;
00438 uint32_t opd = 0;
00439 int tmo;
00440
00441 At91MciEnablePins();
00442
00443
00444 At91MciTxCmd(ifc, MCICMD_GO_IDLE_STATE | MCI_SPCMD_INIT, 0);
00445 At91MciTxCmd(ifc, MCICMD_GO_IDLE_STATE, 0);
00446
00447
00448 for (tmo = 1000; --tmo;) {
00449 sr = At91MciTxCmd(ifc, MCICMD_SEND_APP_CMD, 0);
00450 if ((ifc->ifc_resp[0] & (1 << 8)) != 0 && (sr & MCICMD_IERROR) == 0) {
00451 sr = At91MciTxCmd(ifc, MCICMD_SEND_APP_OP_COND, MMCARD_VRANGE);
00452 if ((sr & MCICMD_IERROR) == 0) {
00453 ifc->ifc_opcond = ifc->ifc_resp[0];
00454 if (ifc->ifc_resp[0] & MMCOP_NBUSY) {
00455 ifc->ifc_config |= MCIFLG_SDCARD;
00456 break;
00457 }
00458 }
00459 }
00460 NutSleep(1);
00461 }
00462
00463 if (tmo == 0) {
00464
00465 opd = MCI_OPDCMD;
00466 At91MciTxCmd(ifc, MCICMD_GO_IDLE_STATE, 0);
00467
00468
00469 for (tmo = 100; --tmo;) {
00470 sr = At91MciTxCmd(ifc, MCICMD_SEND_OP_COND | opd, MMCARD_VRANGE);
00471 ifc->ifc_opcond = ifc->ifc_resp[0];
00472 if (ifc->ifc_resp[0] & MMCOP_NBUSY) {
00473 break;
00474 }
00475 NutSleep(1);
00476 }
00477 }
00478
00479 if (tmo == 0) {
00480
00481 At91MciDisablePins();
00482 return -1;
00483 }
00484
00485
00486 ifc->ifc_reladdr = 0;
00487 for (tmo = 50; --tmo;) {
00488 sr = At91MciTxCmd(ifc, MCICMD_ALL_SEND_CID | opd, 0);
00489 memcpy(ifc->ifc_cid, ifc->ifc_resp, sizeof(ifc->ifc_cid));
00490 if (sr & MCI_RTOE) {
00491
00492 break;
00493 }
00494 if (ifc->ifc_config & MCIFLG_SDCARD) {
00495
00496 ifc->ifc_reladdr = 0;
00497 } else {
00498
00499 ifc->ifc_reladdr++;
00500 }
00501 At91MciTxCmd(ifc, MCICMD_SEND_RELATIVE_ADDR | opd, ifc->ifc_reladdr << 16);
00502 if (ifc->ifc_config & MCIFLG_SDCARD) {
00503
00504 ifc->ifc_reladdr = ifc->ifc_resp[0] >> 16;
00505
00506 clk = MCI_SDC_BITRATE;
00507 }
00508 }
00509
00510 At91MciDisablePins();
00511 if (ifc->ifc_reladdr) {
00512
00513 outr(MCI_MR, (inr(MCI_MR) & ~MCI_CLKDIV) | (At91MciClockDiv(clk) << MCI_CLKDIV_LSB));
00514 return 0;
00515 }
00516 return -1;
00517 }
00518
00528 static int At91MciReadSingle(MCIFC * ifc, uint32_t blk, uint8_t * buf)
00529 {
00530 int rc = -1;
00531 uint32_t sr;
00532
00533
00534 NutEventWait(&mutex, 0);
00535 At91MciEnablePins();
00536
00537 sr = At91MciTxCmd(ifc, MCICMD_SELECT_CARD, ifc->ifc_reladdr << 16);
00538 if ((sr & MCICMD_ERROR) == 0) {
00539 sr = At91MciTxCmd(ifc, MCICMD_SET_BLOCKLEN, MMC_BLOCK_SIZE);
00540 if ((sr & MCICMD_ERROR) == 0) {
00541 ifc->ifc_buff = buf;
00542 sr = At91MciTxCmd(ifc, MCICMD_READ_SINGLE_BLOCK, blk * MMC_BLOCK_SIZE);
00543 if ((sr & MCICMD_ERROR) == 0) {
00544 rc = 0;
00545 }
00546 }
00547 At91MciTxCmd(ifc, MCICMD_DESELECT_CARD, 0);
00548 }
00549
00550
00551 At91MciDisablePins();
00552 NutEventPost(&mutex);
00553
00554 return rc;
00555 }
00556
00566 static int At91MciWriteSingle(MCIFC * ifc, uint32_t blk, CONST uint8_t * buf)
00567 {
00568 int rc = -1;
00569 uint32_t sr;
00570
00571
00572 NutEventWait(&mutex, 0);
00573 At91MciEnablePins();
00574
00575 sr = At91MciTxCmd(ifc, MCICMD_SELECT_CARD, ifc->ifc_reladdr << 16);
00576 if ((sr & MCICMD_ERROR) == 0) {
00577 sr = At91MciTxCmd(ifc, MCICMD_SET_BLOCKLEN, MMC_BLOCK_SIZE);
00578 if ((sr & MCICMD_ERROR) == 0) {
00579 ifc->ifc_buff = (uint8_t *)buf;
00580 sr = At91MciTxCmd(ifc, MCICMD_WRITE_BLOCK, blk * MMC_BLOCK_SIZE);
00581 if ((sr & MCICMD_ERROR) == 0) {
00582 rc = 0;
00583 }
00584 }
00585 At91MciTxCmd(ifc, MCICMD_DESELECT_CARD, 0);
00586 }
00587
00588
00589 At91MciDisablePins();
00590 NutEventPost(&mutex);
00591
00592 return rc;
00593 }
00594
00607 static int At91MciBlockRead(NUTFILE * nfp, void *buffer, int num)
00608 {
00609 MCIFCB *fcb = (MCIFCB *) nfp->nf_fcb;
00610 uint32_t blk = fcb->fcb_blknum;
00611 NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
00612 MCIFC *ifc = (MCIFC *) dev->dev_icb;
00613 int rt;
00614
00615 if (buffer == 0) {
00616 buffer = fcb->fcb_blkbuf;
00617 }
00618 blk += fcb->fcb_part.part_sect_offs;
00619
00620 for (rt = 10; --rt >= 0;) {
00621 if (At91MciReadSingle(ifc, blk, buffer) == 0) {
00622 return 1;
00623 }
00624 At91MciReset(0);
00625 }
00626 return -1;
00627 }
00628
00641 static int At91MciBlockWrite(NUTFILE * nfp, CONST void *buffer, int num)
00642 {
00643 MCIFCB *fcb = (MCIFCB *) nfp->nf_fcb;
00644 uint32_t blk = fcb->fcb_blknum;
00645 NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
00646 MCIFC *ifc = (MCIFC *) dev->dev_icb;
00647
00648 if (buffer == 0) {
00649 buffer = fcb->fcb_blkbuf;
00650 }
00651 blk += fcb->fcb_part.part_sect_offs;
00652
00653 if (At91MciWriteSingle(ifc, blk, buffer) == 0) {
00654 return 1;
00655 }
00656 return -1;
00657 }
00658
00667 static int At91MciUnmount(NUTFILE * nfp)
00668 {
00669 int rc = -1;
00670
00671 if (nfp) {
00672 MCIFCB *fcb = (MCIFCB *) nfp->nf_fcb;
00673
00674 if (fcb) {
00675 rc = fcb->fcb_fsdev->dev_ioctl(fcb->fcb_fsdev, FS_VOL_UNMOUNT, NULL);
00676 NutHeapFree(fcb);
00677 }
00678 NutHeapFree(nfp);
00679 }
00680 return rc;
00681 }
00682
00708 static NUTFILE *At91MciMount(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00709 {
00710 int partno = 0;
00711 int i;
00712 NUTDEVICE *fsdev;
00713 NUTFILE *nfp;
00714 MCIFCB *fcb;
00715 DOSPART *part;
00716 MCIFC *ifc = (MCIFC *) dev->dev_icb;
00717 FSCP_VOL_MOUNT mparm;
00718
00719 if (At91MciDiscover(ifc)) {
00720 errno = ENODEV;
00721 return NUTFILE_EOF;
00722 }
00723
00724
00725 if (*name) {
00726 partno = atoi(name);
00727 do {
00728 name++;
00729 } while (*name && *name != '/');
00730 if (*name == '/') {
00731 name++;
00732 }
00733 }
00734 #ifdef NUTDEBUG
00735 printf("['%s'-PART%d]", name, partno);
00736 #endif
00737
00738
00739
00740
00741
00742
00743
00744 for (fsdev = nutDeviceList; fsdev; fsdev = fsdev->dev_next) {
00745 if (*name == 0) {
00746 if (fsdev->dev_type == IFTYP_FS) {
00747 break;
00748 }
00749 } else if (strcmp(fsdev->dev_name, name) == 0) {
00750 break;
00751 }
00752 }
00753
00754 if (fsdev == 0) {
00755 #ifdef NUTDEBUG
00756 printf("[No FSDriver]");
00757 #endif
00758 errno = ENODEV;
00759 return NUTFILE_EOF;
00760 }
00761
00762 if ((fcb = NutHeapAllocClear(sizeof(MCIFCB))) == 0) {
00763 errno = ENOMEM;
00764 return NUTFILE_EOF;
00765 }
00766 fcb->fcb_fsdev = fsdev;
00767
00768
00769 NutEventPost(&mutex);
00770
00771
00772 if (At91MciReadSingle(ifc, 0, fcb->fcb_blkbuf)) {
00773 NutHeapFree(fcb);
00774 return NUTFILE_EOF;
00775 }
00776
00777 if (fcb->fcb_blkbuf[DOSPART_MAGICPOS] != 0x55 || fcb->fcb_blkbuf[DOSPART_MAGICPOS + 1] != 0xAA) {
00778 NutHeapFree(fcb);
00779 return NUTFILE_EOF;
00780 }
00781
00782
00783 if(fcb->fcb_blkbuf[DOSPART_TYPEPOS] == 'F' &&
00784 fcb->fcb_blkbuf[DOSPART_TYPEPOS + 1] == 'A' &&
00785 fcb->fcb_blkbuf[DOSPART_TYPEPOS + 2] == 'T') {
00786
00787 fcb->fcb_part.part_type = PTYPE_FAT12;
00788 fcb->fcb_part.part_sect_offs = 0;
00789 fcb->fcb_part.part_sects = 65536;
00790 }
00791 else {
00792
00793 part = (DOSPART *) & fcb->fcb_blkbuf[DOSPART_SECTORPOS];
00794 for (i = 1; i <= 4; i++) {
00795 if (partno) {
00796 if (i == partno) {
00797
00798 fcb->fcb_part = *part;
00799 break;
00800 }
00801 } else if (part->part_state & 0x80) {
00802
00803 fcb->fcb_part = *part;
00804 break;
00805 }
00806 part++;
00807 }
00808
00809 if (fcb->fcb_part.part_type == PTYPE_EMPTY) {
00810 NutHeapFree(fcb);
00811 return NUTFILE_EOF;
00812 }
00813 }
00814 if ((nfp = NutHeapAlloc(sizeof(NUTFILE))) == 0) {
00815 NutHeapFree(fcb);
00816 errno = ENOMEM;
00817 return NUTFILE_EOF;
00818 }
00819 nfp->nf_next = 0;
00820 nfp->nf_dev = dev;
00821 nfp->nf_fcb = fcb;
00822
00823
00824
00825
00826 mparm.fscp_bmnt = nfp;
00827 mparm.fscp_part_type = fcb->fcb_part.part_type;
00828 if (fsdev->dev_ioctl(fsdev, FS_VOL_MOUNT, &mparm)) {
00829 At91MciUnmount(nfp);
00830 return NUTFILE_EOF;
00831 }
00832 return nfp;
00833 }
00834
00858 static int At91MciIOCtrl(NUTDEVICE * dev, int req, void *conf)
00859 {
00860 int rc = 0;
00861 MCIFC *ifc = (MCIFC *) dev->dev_icb;
00862
00863 switch (req) {
00864 case NUTBLKDEV_MEDIAAVAIL:
00865 *((int *) conf) = 1;
00866 break;
00867 case NUTBLKDEV_MEDIACHANGE:
00868 *((int *) conf) = 0;
00869 break;
00870 case NUTBLKDEV_INFO:
00871 {
00872 BLKPAR_INFO *par = (BLKPAR_INFO *) conf;
00873 MCIFCB *fcb = (MCIFCB *) par->par_nfp->nf_fcb;
00874
00875 par->par_nblks = fcb->fcb_part.part_sects;
00876 par->par_blksz = MMC_BLOCK_SIZE;
00877 par->par_blkbp = fcb->fcb_blkbuf;
00878 }
00879 break;
00880 case NUTBLKDEV_SEEK:
00881 {
00882 BLKPAR_SEEK *par = (BLKPAR_SEEK *) conf;
00883 MCIFCB *fcb = (MCIFCB *) par->par_nfp->nf_fcb;
00884
00885 fcb->fcb_blknum = par->par_blknum;
00886 }
00887 break;
00888 case MMCARD_GETOCR:
00889 *((uint32_t *) conf) = ifc->ifc_opcond;
00890 break;
00891 default:
00892 rc = -1;
00893 break;
00894 }
00895 return rc;
00896 }
00897
00898 static MCIFC mci0_info;
00899
00912 NUTDEVICE devAt91Mci0 = {
00913 0,
00914 {'M', 'C', 'I', '0', 0, 0, 0, 0, 0}
00915 ,
00916 0,
00917 0,
00918 0,
00919 &mci0_info,
00920 0,
00921 At91MciInit,
00922 At91MciIOCtrl,
00923 At91MciBlockRead,
00924 At91MciBlockWrite,
00925 At91MciMount,
00926 At91MciUnmount,
00927 0
00928 };
00929