📄 sd_protocol.c
字号:
if (ret) return ret; ret = sd_unpack_r1(cmd, &r1, sd_card); if (ret) return ret; ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SET_BUS_WIDTH, 0x2, MSS_RESPONSE_R1, 0); if (ret) return ret; ret = sd_unpack_r1(cmd, &r1, sd_card); if (ret) return ret; card->bus_width = MSS_BUSWIDTH_4BIT; } } memset(llreq, 0x0, sizeof(struct mss_ll_request)); memset(cmd, 0x0, sizeof(struct mss_cmd)); memset(data, 0x0, sizeof(struct mss_data)); memcpy(&ios, &host->ios, sizeof(struct mss_ios)); if ((sd_card->ocr & SD_OCR_CCS) && host->high_capacity) { ios.access_mode = MSS_ACCESS_MODE_SECTOR; cmdarg = arg->block; blklen = 512; } else { if (arg->block_len != sd_card->block_len) { ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SET_BLOCKLEN, arg->block_len, MSS_RESPONSE_R1, 0); if (ret) return ret; ret = sd_unpack_r1(cmd, &r1, sd_card); if (ret) return ret; sd_card->block_len = arg->block_len; } cmdarg = arg->block * arg->block_len; blklen = arg->block_len; } ios.clock = sd_tran_speed(sd_card->csd.tran_speed); host->ops->set_ios(host, &ios); read_write_entry: memset(llreq, 0x0, sizeof(struct mss_ll_request)); memset(cmd, 0x0, sizeof(struct mss_cmd)); memset(data, 0x0, sizeof(struct mss_data)); llreq->cmd = cmd; llreq->data = data; if (arg->nob > 1) { if (action == MSS_READ_MEM) { opcode = SD_READ_MULTIPLE_BLOCK; flags = MSS_DATA_READ | MSS_DATA_MULTI; } else { opcode = SD_WRITE_MULTIPLE_BLOCK; flags = MSS_DATA_WRITE | MSS_DATA_MULTI; } MSS_INIT_CMD(cmd, opcode, cmdarg, 0, MSS_RESPONSE_R1); MSS_INIT_DATA(data, arg->nob, blklen, flags, arg->sg_len, arg->sg, 0); ret = mss_send_ll_req(host, llreq); if (!ret) ret = sd_unpack_r1(cmd, &r1, sd_card); sd_card->state = (action == MSS_WRITE_MEM) ? CARD_STATE_RCV : CARD_STATE_DATA; if (ret) { mss_send_simple_ll_req(host, llreq, cmd, SD_STOP_TRANSMISSION, 0, (action == MSS_WRITE_MEM) ? MSS_RESPONSE_R1B : MSS_RESPONSE_R1, 0); sd_card->state = CARD_STATE_TRAN; if (--retries) { clock = host->ios.clock; clock = clock >> 1; if (clock < SD_CARD_CLOCK_SLOW && retries == 1) clock = SD_CARD_CLOCK_SLOW; mss_set_clock(host, clock); goto read_write_entry; } return ret; } ret = mss_send_simple_ll_req(host, llreq, cmd, SD_STOP_TRANSMISSION, 0, (action == MSS_WRITE_MEM) ? MSS_RESPONSE_R1B : MSS_RESPONSE_R1, 0); if (ret) return ret; ret = sd_unpack_r1(cmd, &r1, sd_card); sd_card->state = CARD_STATE_TRAN; if (ret && (sd_card->errno != SD_ERROR_OUT_OF_RANGE)) return ret; ret = MSS_ERROR_NONE; } else { if (action == MSS_READ_MEM) { opcode = SD_READ_SINGLE_BLOCK; flags = MSS_DATA_READ; } else { opcode = SD_WRITE_BLOCK; flags = MSS_DATA_WRITE; } MSS_INIT_CMD(cmd, opcode, cmdarg, 0, MSS_RESPONSE_R1); MSS_INIT_DATA(data, arg->nob, blklen, flags, arg->sg_len, arg->sg, 0); ret = mss_send_ll_req(host, llreq); if (!ret) ret = sd_unpack_r1(cmd, &r1, sd_card); if (ret) { if (--retries) { clock = host->ios.clock; clock = clock >> 1; if (clock < SD_CARD_CLOCK_SLOW && retries == 1) clock = SD_CARD_CLOCK_SLOW; mss_set_clock(host, clock); goto read_write_entry; } return ret; } } /* Deselect the card */ /*mmc_simple_ll_req(host, mmc_card, MMC_SELECT_CARD, 0, MSS_RESPONSE_NONE, 0); if (ret) return ret; ret = mmc_unpack_r1(&mmc_card->cmd, &r1, mmc_card); mmc_card->state = CARD_STATE_STBY;*/ if (ret) return ret; result->bytes_xfered = data->bytes_xfered; return MSS_ERROR_NONE;}#if 0static enum mss_result sd_lock_unlock_entry(struct mss_card_device *dev){ struct mss_io_request *t = dev->io_request; struct sd_response_r1 r1; u8 *buffer; int status = 0; int retval; int cmd_backup; buffer = NULL; if ((retval = sd_get_status(dev, &status))) { printk(KERN_INFO "can not get card status"); retval = MSS_LOCK_FAILED; goto lock_error; } if(status & CARD_STATUS_WP) { printk(KERN_INFO "card is write protection\n"); retval = MSS_WRITE_PROTECTED; goto lock_error; } if (dev->state == CARD_STATE_STBY) { mss_simple_cmd( dev, SD_SELECT_CARD, (dev->slot->rca) << 16, RESPONSE_R1B, buffer ); if ((retval = sd_unpack_r1(dev->io_request, &r1, dev->state))) goto lock_error; } dev->state = CARD_STATE_TRAN; mss_simple_cmd(dev, SD_SET_BLOCKLEN, t->block_len, RESPONSE_R1, buffer); if ((retval = sd_unpack_r1(dev->io_request, &r1, dev->state))) goto lock_error; cmd_backup = dev->cmd_flag; dev->cmd_flag = MSS_WRITE; mss_send_cmd(dev, SD_LOCK_UNLOCK, 0, 1, t->block_len, RESPONSE_R1B, dev->io_request->buffer); if ((retval = sd_unpack_r1(dev->io_request, &r1, dev->state) )) { dev->flags |= MSS_SLOT_FLAG_LOCK_FAILED; goto lock_error; } dev->cmd_flag = cmd_backup; mss_simple_cmd(dev, SD_SEND_STATUS, (dev->slot->rca) << 16, RESPONSE_R1, buffer); if ((retval = sd_unpack_r1(dev->io_request, &r1, dev->state))) goto lock_error; dev->flags &= ~MSS_SLOT_FLAG_LOCK_FAILED; if ( r1.status & R1_CARD_IS_LOCKED ) dev->flags |= MSS_SLOT_FLAG_LOCKED; else dev->flags &= ~MSS_SLOT_FLAG_LOCKED; mss_finish_io_request(dev, 1); return MSS_SUCCESS;lock_error: dev->flags |= MSS_SLOT_FLAG_LOCK_FAILED; mss_finish_io_request(dev, 0); return retval; }#endifstatic int sd_query_function(struct mss_card *card, struct io_swfunc_request *r, struct sw_func_status *status){ struct sd_card *sd_card = card->prot_card; int i; u32 arg = 0; if (card->slot->host->sd_spec != MSS_SD_SPEC_20 || sd_card->ver != MSS_SD_SPEC_20) return MSS_ERROR_ACTION_UNSUPPORTED; for (i = 5; i > 0; i--) { arg |= ((r->args[i] & 0xF) << (i << 2)); } return sd_send_cmd6(card, status, 0, arg);}static int sd_sw_function(struct mss_card *card, struct io_swfunc_request *r){ int ret, i; u32 arg = 0; struct sw_func_status status; struct sd_card *sd_card = card->prot_card; if (card->slot->host->sd_spec != MSS_SD_SPEC_20 || sd_card->ver != MSS_SD_SPEC_20) return MSS_ERROR_ACTION_UNSUPPORTED; for (i = 0; i < 6; i++) { if (r->args[i] >= 0xF) { goto switch_err; } } /* Step 1: CMD6(mode = 0, func = 0xF(Don't Care) */ ret = sd_send_cmd6(card, &status, 0, 0xFFFFFF); if (ret) goto switch_err; /* Step 2: Any Switch ? */ for (i = 0; i < 6; i++) { if (!((status.func_support[i]) & (0x1 << (r->args[i])))) goto switch_err; } for (i = 0; i < 6; i++) { if (status.group_status[i] != r->args[i]) { break; } } if (i == 6) return 0; /* Step 3: CMD6(mode = 0, func= funcX */ for (i = 5; i > 0; i--) { arg |= ((r->args[i]) << (i << 2)); } ret = sd_send_cmd6(card, &status, 0, arg); if (ret) goto switch_err; if (status.current_consumption > r->current_acceptable) { goto switch_err; } for (i = 0; i < 6; i++) { if (status.group_status[i] != r->args[i]) { goto switch_err; } } ret = sd_send_cmd6(card, &status, 1, arg); if (ret) goto switch_err; for (i = 0; i < 6; i++) { if (status.group_status[i] != r->args[i]) { goto switch_err; } } return 0;switch_err: sd_card->errno = SD_ERROR_SWFUNC; return MSS_ERROR_ACTION_UNSUPPORTED;}/* count by 512 bytes */static int sd_get_capacity(struct mss_card *card, u32 *size){ struct sd_card *sd_card = card->prot_card; int c_size = 0; int c_size_mult = 0; int blk_len = 0; if (sd_card->csd.csd_structure == 0) { c_size = sd_card->csd.csd.csd1.c_size; c_size_mult = sd_card->csd.csd.csd1.c_size_mult; blk_len = sd_card->csd.read_bl_len - 9; } /* (csize + 1) * 512 * 1024 bytes */ else if (sd_card->csd.csd_structure == 1) { c_size = sd_card->csd.csd.csd2.c_size; c_size_mult = 7; blk_len = 1; } *size = (c_size + 1) << (2 + c_size_mult + blk_len); dbg("capacity is :0x%x\n", *size); return MSS_ERROR_NONE;}/***************************************************************************** * * protocol driver interface functions * ****************************************************************************/static int sd_prot_entry(struct mss_card *card, unsigned int action, void *arg, void *result){ int ret; u32 status; if (action != MSS_RECOGNIZE_CARD && card->card_type != MSS_SD_CARD) return MSS_ERROR_WRONG_CARD_TYPE; switch (action) { case MSS_RECOGNIZE_CARD: ret = sd_recognize_card(card); break; case MSS_INIT_CARD: ret = sd_card_init(card); break; case MSS_READ_MEM: case MSS_WRITE_MEM: if (!arg || !result) return -EINVAL; ret = sd_read_write_entry(card, action, arg, result); break; /* case MSS_LOCK_UNLOCK: ret = sd_lock_unlock_entry(dev); break; */ case MSS_SD_QUERY_FUNC: if (!arg || !result) return -EINVAL; ret = sd_query_function(card, arg, result); break; case MSS_SD_SW_FUNC: if (!arg) return -EINVAL; ret = sd_sw_function(card, arg); break; case MSS_QUERY_CARD: ret = sd_get_status(card, &status); break; case MSS_GET_CAPACITY: ret = sd_get_capacity(card, result); break; default: ret = MSS_ERROR_ACTION_UNSUPPORTED; break; } return ret;}static int sd_prot_attach_card(struct mss_card *card){ struct sd_card *sd_card;#define ALIGN32(x) (((x) + 31) & (~31)) sd_card = kzalloc(ALIGN32(ALIGN32(sizeof(struct sd_card))) + 512, GFP_KERNEL); card->prot_card = sd_card; if (sd_card) { sd_card->buf = (char *)ALIGN32((unsigned int)&sd_card[1]); return 0; } return -ENOMEM;}static void sd_prot_detach_card(struct mss_card *card){ kfree(card->prot_card);}static int sd_prot_get_errno(struct mss_card *card){ struct sd_card *sd_card = card->prot_card; return sd_card->errno;}static struct mss_prot_driver sd_protocol = { .name = SD_PROTOCOL, .prot_entry = sd_prot_entry, .attach_card = sd_prot_attach_card, .detach_card = sd_prot_detach_card, .get_errno = sd_prot_get_errno,};/***************************************************************************** * * module init and exit functions * ****************************************************************************/static int sd_protocol_init(void){ register_mss_prot_driver(&sd_protocol); return 0;}static void sd_protocol_exit(void){ unregister_mss_prot_driver(&sd_protocol);}module_init(sd_protocol_init);module_exit(sd_protocol_exit);MODULE_AUTHOR("Bridge Wu");MODULE_LICENSE("MIT");MODULE_DESCRIPTION("SD protocol driver");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -