📄 patch-2.4.19-mmc.txt
字号:
+ csd->taac = buf[2];+ csd->nsac = buf[3];+ csd->tran_speed = buf[4];+ csd->ccc = (((u16)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4);+ csd->read_bl_len = buf[6] & 0x0f;+ csd->read_bl_partial = (buf[7] & 0x80) ? 1 : 0;+ csd->write_blk_misalign = (buf[7] & 0x40) ? 1 : 0;+ csd->read_blk_misalign = (buf[7] & 0x20) ? 1 : 0;+ csd->dsr_imp = (buf[7] & 0x10) ? 1 : 0;+ csd->c_size = ((((u16)buf[7]) & 0x03) << 10) | (((u16)buf[8]) << 2) | (((u16)buf[9]) & 0xc0) >> 6;+ csd->vdd_r_curr_min = (buf[9] & 0x38) >> 3;+ csd->vdd_r_curr_max = buf[9] & 0x07;+ csd->vdd_w_curr_min = (buf[10] & 0xe0) >> 5;+ csd->vdd_w_curr_max = (buf[10] & 0x1c) >> 2;+ csd->c_size_mult = ((buf[10] & 0x03) << 1) | ((buf[11] & 0x80) >> 7);+ switch ( csd->csd_structure ) {+ case CSD_STRUCT_VER_1_0:+ case CSD_STRUCT_VER_1_1:+ csd->erase.v22.sector_size = (buf[11] & 0x7c) >> 2;+ csd->erase.v22.erase_grp_size = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5);+ break;+ case CSD_STRUCT_VER_1_2:+ default:+ csd->erase.v31.erase_grp_size = (buf[11] & 0x7c) >> 2;+ csd->erase.v31.erase_grp_mult = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5);+ break;+ }+ csd->wp_grp_size = buf[12] & 0x1f;+ csd->wp_grp_enable = (buf[13] & 0x80) ? 1 : 0;+ csd->default_ecc = (buf[13] & 0x60) >> 5;+ csd->r2w_factor = (buf[13] & 0x1c) >> 2;+ csd->write_bl_len = ((buf[13] & 0x03) << 2) | ((buf[14] & 0xc0) >> 6);+ csd->write_bl_partial = (buf[14] & 0x20) ? 1 : 0;+ csd->file_format_grp = (buf[15] & 0x80) ? 1 : 0;+ csd->copy = (buf[15] & 0x40) ? 1 : 0;+ csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0;+ csd->tmp_write_protect = (buf[15] & 0x10) ? 1 : 0;+ csd->file_format = (buf[15] & 0x0c) >> 2;+ csd->ecc = buf[15] & 0x03;++ DEBUG(2," csd_structure=%d spec_vers=%d taac=%02x nsac=%02x tran_speed=%02x\n"+ " ccc=%04x read_bl_len=%d read_bl_partial=%d write_blk_misalign=%d\n"+ " read_blk_misalign=%d dsr_imp=%d c_size=%d vdd_r_curr_min=%d\n"+ " vdd_r_curr_max=%d vdd_w_curr_min=%d vdd_w_curr_max=%d c_size_mult=%d\n"+ " wp_grp_size=%d wp_grp_enable=%d default_ecc=%d r2w_factor=%d\n"+ " write_bl_len=%d write_bl_partial=%d file_format_grp=%d copy=%d\n"+ " perm_write_protect=%d tmp_write_protect=%d file_format=%d ecc=%d\n",+ csd->csd_structure, csd->spec_vers, + csd->taac, csd->nsac, csd->tran_speed,+ csd->ccc, csd->read_bl_len, + csd->read_bl_partial, csd->write_blk_misalign,+ csd->read_blk_misalign, csd->dsr_imp, + csd->c_size, csd->vdd_r_curr_min,+ csd->vdd_r_curr_max, csd->vdd_w_curr_min, + csd->vdd_w_curr_max, csd->c_size_mult,+ csd->wp_grp_size, csd->wp_grp_enable,+ csd->default_ecc, csd->r2w_factor, + csd->write_bl_len, csd->write_bl_partial,+ csd->file_format_grp, csd->copy, + csd->perm_write_protect, csd->tmp_write_protect,+ csd->file_format, csd->ecc);+ switch (csd->csd_structure) {+ case CSD_STRUCT_VER_1_0:+ case CSD_STRUCT_VER_1_1:+ DEBUG(2," V22 sector_size=%d erase_grp_size=%d\n", + csd->erase.v22.sector_size, + csd->erase.v22.erase_grp_size);+ break;+ case CSD_STRUCT_VER_1_2:+ default:+ DEBUG(2," V31 erase_grp_size=%d erase_grp_mult=%d\n", + csd->erase.v31.erase_grp_size,+ csd->erase.v31.erase_grp_mult);+ break;+ + }++ if ( buf[0] != 0x3f ) return MMC_ERROR_HEADER_MISMATCH;++ return 0;+}++int mmc_unpack_r1( struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state )+{+ u8 *buf = request->response;++ if ( request->result ) return request->result;++ r1->cmd = buf[0];+ r1->status = PARSE_U32(buf,1);++ DEBUG(2," cmd=%d status=%08x\n", r1->cmd, r1->status);++ if (R1_STATUS(r1->status)) {+ if ( r1->status & R1_OUT_OF_RANGE ) return MMC_ERROR_OUT_OF_RANGE;+ if ( r1->status & R1_ADDRESS_ERROR ) return MMC_ERROR_ADDRESS;+ if ( r1->status & R1_BLOCK_LEN_ERROR ) return MMC_ERROR_BLOCK_LEN;+ if ( r1->status & R1_ERASE_SEQ_ERROR ) return MMC_ERROR_ERASE_SEQ;+ if ( r1->status & R1_ERASE_PARAM ) return MMC_ERROR_ERASE_PARAM;+ if ( r1->status & R1_WP_VIOLATION ) return MMC_ERROR_WP_VIOLATION;+ if ( r1->status & R1_CARD_IS_LOCKED ) return MMC_ERROR_CARD_IS_LOCKED;+ if ( r1->status & R1_LOCK_UNLOCK_FAILED ) return MMC_ERROR_LOCK_UNLOCK_FAILED;+ if ( r1->status & R1_COM_CRC_ERROR ) return MMC_ERROR_COM_CRC;+ if ( r1->status & R1_ILLEGAL_COMMAND ) return MMC_ERROR_ILLEGAL_COMMAND;+ if ( r1->status & R1_CARD_ECC_FAILED ) return MMC_ERROR_CARD_ECC_FAILED;+ if ( r1->status & R1_CC_ERROR ) return MMC_ERROR_CC;+ if ( r1->status & R1_ERROR ) return MMC_ERROR_GENERAL;+ if ( r1->status & R1_UNDERRUN ) return MMC_ERROR_UNDERRUN;+ if ( r1->status & R1_OVERRUN ) return MMC_ERROR_OVERRUN;+ if ( r1->status & R1_CID_CSD_OVERWRITE ) return MMC_ERROR_CID_CSD_OVERWRITE;+ }++ if ( buf[0] != request->cmd ) return MMC_ERROR_HEADER_MISMATCH;++ /* This should be last - it's the least dangerous error */+ if ( R1_CURRENT_STATE(r1->status) != state ) return MMC_ERROR_STATE_MISMATCH;++ return 0;+}++int mmc_unpack_cid( struct mmc_request *request, struct mmc_cid *cid )+{+ u8 *buf = request->response;+ int i;++ if ( request->result ) return request->result;++ cid->mid = buf[1];+ cid->oid = PARSE_U16(buf,2);+ for ( i = 0 ; i < 6 ; i++ )+ cid->pnm[i] = buf[4+i];+ cid->pnm[6] = 0;+ cid->prv = buf[10];+ cid->psn = PARSE_U32(buf,11);+ cid->mdt = buf[15];+ + DEBUG(2," mid=%d oid=%d pnm=%s prv=%d.%d psn=%08x mdt=%d/%d\n",+ cid->mid, cid->oid, cid->pnm, + (cid->prv>>4), (cid->prv&0xf), + cid->psn, (cid->mdt>>4), (cid->mdt&0xf)+1997);++ if ( buf[0] != 0x3f ) return MMC_ERROR_HEADER_MISMATCH;+ return 0;+}++int mmc_unpack_r3( struct mmc_request *request, struct mmc_response_r3 *r3 )+{+ u8 *buf = request->response;++ if ( request->result ) return request->result;++ r3->ocr = PARSE_U32(buf,1);+ DEBUG(2," ocr=%08x\n", r3->ocr);++ if ( buf[0] != 0x3f ) return MMC_ERROR_HEADER_MISMATCH;+ return 0;+}++/**************************************************************************/++#define KBPS 1+#define MBPS 1000++static u32 ts_exp[] = { 100*KBPS, 1*MBPS, 10*MBPS, 100*MBPS, 0, 0, 0, 0 };+static u32 ts_mul[] = { 0, 1000, 1200, 1300, 1500, 2000, 2500, 3000, + 3500, 4000, 4500, 5000, 5500, 6000, 7000, 8000 };++u32 mmc_tran_speed( u8 ts )+{+ u32 rate = ts_exp[(ts & 0x7)] * ts_mul[(ts & 0x78) >> 3];++ if ( rate <= 0 ) {+ DEBUG(0, ": error - unrecognized speed 0x%02x\n", ts);+ return 1;+ }++ return rate;+}++/**************************************************************************/++void mmc_send_cmd( struct mmc_dev *dev, int cmd, u32 arg, + u16 nob, u16 block_len, enum mmc_rsp_t rtype )+{+ dev->request.cmd = cmd;+ dev->request.arg = arg;+ dev->request.rtype = rtype;+ dev->request.nob = nob;+ dev->request.block_len = block_len;+ dev->request.buffer = NULL;+ if ( nob && dev->io_request )+ dev->request.buffer = dev->io_request->buffer;++ dev->state |= STATE_CMD_ACTIVE;+ dev->sdrive->send_cmd(&dev->request);+}++void mmc_finish_io_request( struct mmc_dev *dev, int result )+{+ struct mmc_io_request *t = dev->io_request;+ struct mmc_slot *slot = dev->slot + t->id;++ dev->io_request = NULL; // Remove the old request (the media driver may requeue)+ if ( slot->media_driver )+ slot->media_driver->io_request_done( t, result );+}+++/* Only call this when there is no pending request - it unloads the media driver */+int mmc_check_eject( struct mmc_dev *dev )+{+ unsigned long flags;+ int state;+ int i;++ DEBUG(2," dev state=%x\n", dev->state);++ local_irq_save(flags);+ state = dev->state;+ dev->state = state & ~STATE_EJECT;+ local_irq_restore(flags);++ if ( !(state & STATE_EJECT) )+ return 0;++ for ( i = 0 ; i < dev->num_slots ; i++ ) {+ struct mmc_slot *slot = dev->slot + i;++ if ( slot->flags & MMC_SLOT_FLAG_EJECT ) {+ slot->state = CARD_STATE_EMPTY;+ if ( slot->media_driver ) {+ slot->media_driver->unload( slot );+ slot->media_driver = NULL;+ }+ slot->flags &= ~MMC_SLOT_FLAG_EJECT;+ run_sbin_mmc_hotplug(dev,i,0);+ }+ }+ return 1;+}++int mmc_check_insert( struct mmc_dev *dev )+{+ unsigned long flags;+ int state;+ int i;+ int card_count = 0;++ DEBUG(2," dev state=%x\n", dev->state);++ local_irq_save(flags);+ state = dev->state;+ dev->state = state & ~STATE_INSERT;+ local_irq_restore(flags);++ if ( !(state & STATE_INSERT) ) + return 0;++ for ( i = 0 ; i < dev->num_slots ; i++ ) {+ struct mmc_slot *slot = dev->slot + i;++ if ( slot->flags & MMC_SLOT_FLAG_INSERT ) {+ if (!dev->sdrive->is_empty(i)) {+ slot->state = CARD_STATE_IDLE;+ card_count++;+ }+ slot->flags &= ~MMC_SLOT_FLAG_INSERT;+ }+ }+ return card_count;+}++/******************************************************************+ *+ * Hotplug callback card insertion/removal+ *+ ******************************************************************/++#ifdef CONFIG_HOTPLUG++extern char hotplug_path[];+extern int call_usermodehelper(char *path, char **argv, char **envp);++static void run_sbin_hotplug(struct mmc_dev *dev, int id, int insert)+{+ int i;+ char *argv[3], *envp[8];+ char media[64], slotnum[16];++ if (!hotplug_path[0])+ return;++ DEBUG(0,": hotplug_path=%s id=%d insert=%d\n", hotplug_path, id, insert);++ i = 0;+ argv[i++] = hotplug_path;+ argv[i++] = "mmc";+ argv[i] = 0;++ /* minimal command environment */+ i = 0;+ envp[i++] = "HOME=/";+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";+ + /* other stuff we want to pass to /sbin/hotplug */+ sprintf(slotnum, "SLOT=%d", id );+ if ( dev->slot[id].media_driver && dev->slot[id].media_driver->name )+ sprintf(media, "MEDIA=%s", dev->slot[id].media_driver->name );+ else+ sprintf(media, "MEDIA=unknown");++ envp[i++] = slotnum;+ envp[i++] = media;++ if (insert)+ envp[i++] = "ACTION=add";+ else+ envp[i++] = "ACTION=remove";+ envp[i] = 0;++ call_usermodehelper (argv [0], argv, envp);+}++static void mmc_hotplug_task_handler( void *nr )+{+ int insert = ((int) nr) & 0x01;+ int id = ((int) nr) >> 1;+ DEBUG(2," id=%d insert=%d\n", id, insert );+ run_sbin_hotplug(&g_mmc_dev, id, insert );+}++static struct tq_struct mmc_hotplug_task = {+ routine: mmc_hotplug_task_handler+};++void run_sbin_mmc_hotplug(struct mmc_dev *dev, int id, int insert )+{+ mmc_hotplug_task.data = (void *) ((id << 1) | insert);+ schedule_task( &mmc_hotplug_task );+}++#else+void run_sbin_mmc_hotplug(struct sleeve_dev *sdev, int insert) { }+#endif /* CONFIG_HOTPLUG */+++/******************************************************************+ * Common processing tasklet+ * Everything gets serialized through this+ ******************************************************************/++static void mmc_tasklet_action(unsigned long data)+{+ struct mmc_dev *dev = (struct mmc_dev *)data;+ unsigned long flags;+ int state;++ DEBUG(2,": dev=%p flags=%02x\n", dev, dev->state);++ /* Grab the current working state */+ local_irq_save(flags);+ state = dev->state;+ if ( state & STATE_CMD_DONE )+ dev->state = state & ~(STATE_CMD_DONE | STATE_CMD_ACTIVE);+ local_irq_restore(flags);++ /* If there is an active command, don't do anything */+ if ( (state & STATE_CMD_ACTIVE) && !(state & STATE_CMD_DONE) )+ return;++ if ( dev->protocol )+ dev->protocol(dev,state);+}++/******************************************************************+ * Callbacks from low-level driver+ * These run at interrupt time+ ******************************************************************/++void mmc_cmd_complete(struct mmc_request *request)+{+ DEBUG(2,": request=%p retval=%d\n", request, request->result);+ g_mmc_dev.state |= STATE_CMD_DONE;+ if ( !g_mmc_dev.suspended )+ tasklet_schedule(&g_mmc_dev.task);+}++void mmc_insert(int slot)+{+ DEBUG(2,": %d\n", slot);+ g_mmc_dev.state |= STATE_INSERT;+ g_mmc_dev.slot[slot].flags |= MMC_SLOT_FLAG_INSERT;+ if ( !g_mmc_dev.suspended )+ tasklet_schedule(&g_mmc_dev.task);+}++void mmc_eject(int slot)+{+ DEBUG(2,": %d\n", slot);+ g_mmc_dev.state |= STATE_EJECT;+ g_mmc_dev.slot[slot].flags |= MMC_SLOT_FLAG_EJECT;+ if ( !g_mmc_dev.suspended )+ tasklet_schedule(&g_mmc_dev.task);+}++EXPORT_SYMBOL(mmc_cmd_complete);+EXPORT_SYMBOL(mmc_insert);+EXPORT_SYMBOL(mmc_eject);++/******************************************************************+ * Called from the media handler+ ******************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -