📄 mmc_protocol.c
字号:
} switch (dev->request.cmd) { case MMC_SELECT_CARD: if ( (retval = mmc_unpack_r1( &dev->request, &r1, slot->state )) ) goto lock_error; for ( i = 0 ; i < dev->num_slots ; i++ ) dev->slot[i].state = ( i == t->id ? CARD_STATE_TRAN : CARD_STATE_STBY ); mmc_simple_cmd(dev, MMC_SET_BLOCKLEN, t->block_len, RESPONSE_R1 ); break; case MMC_SET_BLOCKLEN: if ( (retval = mmc_unpack_r1( &dev->request, &r1, slot->state )) ) goto lock_error; mmc_send_cmd(dev, MMC_LOCK_UNLOCK, 0, 1, t->block_len, RESPONSE_R1B ); break; case MMC_LOCK_UNLOCK: if ( (retval = mmc_unpack_r1( &dev->request, &r1, slot->state )) ) goto lock_error; mmc_simple_cmd(dev, MMC_SEND_STATUS, slot->rca, RESPONSE_R1 ); break; case MMC_SEND_STATUS: if ( (retval = mmc_unpack_r1( &dev->request, &r1, slot->state)) ) { switch (retval) { case MMC_ERROR_STATE_MISMATCH: /* poll unitl it's done */ mmc_simple_cmd(dev, MMC_SEND_STATUS, slot->rca, RESPONSE_R1 ); return NULL; case MMC_ERROR_LOCK_UNLOCK_FAILED: /* nothing */ break; default: goto lock_error; } } if (retval == MMC_ERROR_LOCK_UNLOCK_FAILED) slot->flags |= MMC_SLOT_FLAG_LOCK_FAILED; if (r1.status & R1_CARD_IS_LOCKED) slot->flags |= MMC_SLOT_FLAG_LOCKED; else slot->flags &= ~MMC_SLOT_FLAG_LOCKED; mmc_finish_io_request(dev, 1); return mmc_cim_default_state; default: goto lock_error; break; } return NULL; lock_error: DEBUG(0,": failure during cmd %d, error %d (%s)\n", dev->request.cmd, retval, mmc_result_to_string(retval)); printk(" failure during cmd %d, error %d (%s)\n", dev->request.cmd, retval, mmc_result_to_string(retval)); slot->flags |= MMC_SLOT_FLAG_LOCK_FAILED; mmc_finish_io_request(dev, 0); return mmc_cim_default_state;}/* Update the card's status information in preparation to running a read/write cycle */static void * mmc_cim_get_status( struct mmc_dev *dev, int first ){ struct mmc_slot *slot = dev->slot + dev->io_request->id; struct mmc_response_r1 r1; int retval = MMC_NO_ERROR; DEBUG(2," first=%d\n",first); if ( first ) { mmc_simple_cmd(dev, MMC_SEND_STATUS, slot->rca, RESPONSE_R1 ); return NULL; } switch (dev->request.cmd) { case MMC_SEND_STATUS: retval = mmc_unpack_r1(&dev->request,&r1,slot->state); if ( retval && (retval != MMC_ERROR_STATE_MISMATCH) ) goto err_out; slot->state = R1_CURRENT_STATE(r1.status); if (dev->io_request->cmd == MMC_IO_LOCK) return mmc_cim_lock_unlock; if ( !(r1.status & R1_CARD_IS_LOCKED) ) { slot->flags &= ~MMC_SLOT_FLAG_LOCKED; return mmc_cim_read_write_block; } else slot->flags |= MMC_SLOT_FLAG_LOCKED; break; default: break; }err_out: DEBUG(0, ": failure during cmd %d, error=%d (%s)\n", dev->request.cmd, retval, mmc_result_to_string(retval));//#ifdef CONFIG_ARCH_EZX_E680 /* add by w20598 */ if (!mmc_slot_enable) { if (MMC_IO_READ == dev->io_request->cmd) mmc_media_transfer_done(dev->io_request,0); else mmc_media_transfer_done(dev->io_request,1); dev->io_request = NULL; } else /* add end *///#endif mmc_finish_io_request(dev,0); return mmc_cim_default_state;}static void * mmc_cim_handle_request( struct mmc_dev *dev, int first ){ DEBUG(2," first=%d\n",first); if ( !first && !mmc_has_valid_request(dev)) { DEBUG(0, ": invalid request\n");//#ifdef CONFIG_ARCH_EZX_E680 /* add by w20598 */ if (!mmc_slot_enable) { if (MMC_IO_READ == dev->io_request->cmd) mmc_media_transfer_done(dev->io_request,0); else mmc_media_transfer_done(dev->io_request,1); dev->io_request = NULL; } else /* add end *///#endif mmc_finish_io_request(dev,0); return mmc_cim_default_state; } if ( first ) return mmc_cim_get_status;//#ifdef CONFIG_ARCH_EZX_E680 /* add by w20598 */ if (!mmc_slot_enable) { if (MMC_IO_READ == dev->io_request->cmd) mmc_media_transfer_done(dev->io_request,0); else mmc_media_transfer_done(dev->io_request,1); dev->io_request = NULL; return mmc_cim_default_state; } else /* add end *///#endif return mmc_cim_read_write_block;}/****************************************************************** * * State machine routines to initialize card(s) * ******************************************************************//* CIM_SINGLE_CARD_ACQ (frequency at 400 kHz) --- Must enter from GO_IDLE_STATE --- 1. SD_SEND_OP_COND (SD Card) [CMD55] + [CMD41] 2. SEND_OP_COND (Full Range) [CMD1] {optional} 3. SEND_OP_COND (Set Range ) [CMD1] If busy, delay and repeat step 2 4. ALL_SEND_CID [CMD2] If timeout, set an error (no cards found) 5. SET_RELATIVE_ADDR [CMD3] 6. SEND_CSD [CMD9] 7. SET_DSR [CMD4] Only call this if (csd.dsr_imp). 8. Set clock frequency (check available in csd.tran_speed) */static void * mmc_cim_single_card_acq( struct mmc_dev *dev, int first ){ struct mmc_response_r3 r3; struct mmc_response_r1 r1; struct mmc_slot *slot = dev->slot; /* Must be slot 0 */ int retval; DEBUG(2,"\n"); if ( first ) { mmc_simple_cmd(dev, MMC_GO_IDLE_STATE, 0, RESPONSE_NONE); slot->sd = 1; return NULL; } switch (dev->request.cmd) { case MMC_GO_IDLE_STATE: /* No response to parse */ if ( (dev->sdrive->flags & MMC_SDFLAG_VOLTAGE )) DEBUG(0,": error - current driver doesn't do OCR\n"); if (slot->sd) mmc_simple_cmd(dev, MMC_APP_CMD, 0, RESPONSE_R1); else mmc_simple_cmd(dev, MMC_SEND_OP_COND, dev->sdrive->ocr, RESPONSE_R3); break; case MMC_APP_CMD: retval = mmc_unpack_r1(&dev->request,&r1,slot->state); if ( retval ) { DEBUG(0, ": unable to MMC_APP_CMD error=%d (%s)\n", retval, mmc_result_to_string(retval)); /* reset the card to idle*/ mmc_simple_cmd(dev, MMC_GO_IDLE_STATE, 0, RESPONSE_NONE); slot->sd = 0; } else { mmc_simple_cmd(dev, SD_SEND_OP_COND, 0x00ff8000, RESPONSE_R3); } break; case SD_SEND_OP_COND: retval = mmc_unpack_r3(&dev->request, &r3); if ( retval ) { /* Try MMC card */ mmc_simple_cmd(dev, MMC_SEND_OP_COND, dev->sdrive->ocr, RESPONSE_R3); break; } DEBUG(2,": read ocr value = 0x%08x\n", r3.ocr); if (!(r3.ocr & MMC_CARD_BUSY)) { mmc_simple_cmd(dev, MMC_APP_CMD, 0, RESPONSE_R1); } else { /* Set the data bus width to 4 bits */ slot->sd = 1; /* SD Card ready */ slot->state = CARD_STATE_READY; mmc_simple_cmd(dev, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID); } break; case MMC_SEND_OP_COND: retval = mmc_unpack_r3(&dev->request, &r3); if ( retval ) { DEBUG(0,": failed SEND_OP_COND error=%d (%s)\n", retval, mmc_result_to_string(retval)); return mmc_cim_default_state; } DEBUG(2,": read ocr value = 0x%08x\n", r3.ocr); if (!(r3.ocr & MMC_CARD_BUSY)) { mmc_simple_cmd(dev, MMC_SEND_OP_COND, dev->sdrive->ocr, RESPONSE_R3); } else { slot->sd = 0; /* MMC Card ready */ slot->state = CARD_STATE_READY; mmc_simple_cmd(dev, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID); } break; case MMC_ALL_SEND_CID: retval = mmc_unpack_cid( &dev->request, &slot->cid ); /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */ if ( retval && (retval != MMC_ERROR_CRC)) { DEBUG(0,": unable to ALL_SEND_CID error=%d (%s)\n", retval, mmc_result_to_string(retval)); return mmc_cim_default_state; } slot->state = CARD_STATE_IDENT; if(slot->sd) { mmc_simple_cmd(dev, MMC_SET_RELATIVE_ADDR, 0, RESPONSE_R6); } else { mmc_simple_cmd(dev, MMC_SET_RELATIVE_ADDR, ID_TO_RCA(slot->id) << 16, RESPONSE_R1); } break; case MMC_SET_RELATIVE_ADDR: if (slot->sd) { retval = mmc_unpack_r6(&dev->request, &r1, slot->state, &slot->rca); slot->rca = slot->rca << 16; DEBUG(2, ": Get RCA from SD: 0x%04x Status: %x\n", slot->rca, r1.status); } else { retval = mmc_unpack_r1(&dev->request,&r1,slot->state); slot->rca = ID_TO_RCA(slot->id) << 16; } if ( retval ) { DEBUG(0, ": unable to SET_RELATIVE_ADDR error=%d (%s)\n", retval, mmc_result_to_string(retval)); return mmc_cim_default_state; } slot->state = CARD_STATE_STBY; mmc_simple_cmd(dev, MMC_SEND_CSD, slot->rca, RESPONSE_R2_CSD); break; case MMC_SEND_CSD: retval = mmc_unpack_csd(&dev->request, &slot->csd); /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */ if ( retval && (retval != MMC_ERROR_CRC)) { DEBUG(0, ": unable to SEND_CSD error=%d (%s)\n", retval, mmc_result_to_string(retval)); return mmc_cim_default_state; } if ( slot->csd.dsr_imp ) { DEBUG(0, ": driver doesn't support setting DSR\n"); // mmc_simple_cmd(dev, MMC_SET_DSR, 0, RESPONSE_NONE); } mmc_configure_card( dev, 0 ); return mmc_cim_default_state; default: DEBUG(0, ": error! Illegal last cmd %d\n", dev->request.cmd); return mmc_cim_default_state; } return NULL;}/* CIM_INIT_STACK (frequency at 400 kHz) 1. GO_IDLE_STATE (CMD0) 2. Do CIM_SINGLE_CARD_ACQ*/static void * mmc_cim_init_stack( struct mmc_dev *dev, int first ){ DEBUG(2,"\n"); if ( first ) { mmc_simple_cmd(dev, MMC_CIM_RESET, 0, RESPONSE_NONE); return NULL; } switch (dev->request.cmd) { case MMC_CIM_RESET: if ( dev->slot[0].state == CARD_STATE_EMPTY ) return mmc_cim_default_state; dev->slot[0].state = CARD_STATE_IDLE; return mmc_cim_single_card_acq; default: DEBUG(0,": invalid state %d\n", dev->request.cmd); break; } return NULL;}/****************************************************************** * Default state - start here ******************************************************************/static void * mmc_cim_default_state( struct mmc_dev *dev, int first ){ DEBUG(2,"\n"); mmc_check_eject(dev); if (mmc_check_insert(dev)) return mmc_cim_init_stack; else if (mmc_has_valid_request(dev)) {//#ifdef CONFIG_ARCH_EZX_E680 /* add by w20598 */ if (!mmc_slot_enable) { if (MMC_IO_READ == dev->io_request->cmd) mmc_media_transfer_done(dev->io_request,0); else mmc_media_transfer_done(dev->io_request,1); dev->io_request = NULL; return mmc_cim_default_state; } else /* add end *///#endif return mmc_cim_handle_request; } return NULL;}/****************************************************************** * State function handler ******************************************************************/typedef void *(*state_func_t)(struct mmc_dev *, int);static state_func_t g_single_card = &mmc_cim_default_state;void mmc_protocol_single_card( struct mmc_dev *dev, int state_flags ){ state_func_t sf; sf = g_single_card(dev,0); while ( sf ) { g_single_card = sf; sf = g_single_card(dev,1); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -