ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, const void *src) #endif { #ifdef CONFIG_BLK struct blk_desc *block_dev = dev_get_uclass_platdata(dev); #endif int dev_num = block_dev->devnum; lbaint_t cur, blocks_todo = blkcnt; int err; struct mmc *mmc = find_mmc_device(dev_num); if (!mmc) return 0; err = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_num, block_dev->hwpart); if (err < 0) return 0; if (mmc_set_blocklen(mmc, mmc->write_bl_len)) return 0; do { cur = (blocks_todo > mmc->cfg->b_max) ? mmc->cfg->b_max : blocks_todo; if (mmc_write_blocks(mmc, start, cur, src) != cur) return 0; blocks_todo -= cur; start += cur; src += cur * mmc->write_bl_len; } while (blocks_todo > 0); return blkcnt; }
unsigned long mmc_bread(int dev_num, unsigned long start, unsigned blkcnt, void *dst) { unsigned cur, blocks_todo = blkcnt; struct mmc *mmc = find_mmc_device(dev_num); if (blkcnt == 0) return 0; if (!mmc) return 0; if ((start + blkcnt) > mmc->lba) { mmcdbg("MMC: block number 0x%x exceeds max(0x%x)\n", start + blkcnt, mmc->lba); return 0; } if (mmc_set_blocklen(mmc, mmc->read_bl_len)) return 0; do { cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo; if(mmc_read_blocks(mmc, dst, start, cur) != cur) return 0; blocks_todo -= cur; start += cur; // dst += cur * mmc->read_bl_len; dst = (char*)dst + cur * mmc->read_bl_len; } while (blocks_todo > 0); return blkcnt; }
unsigned long mmc_bwrite(int dev_num, unsigned long start, unsigned blkcnt, const void*src) { unsigned cur, blocks_todo = blkcnt; struct mmc *mmc = find_mmc_device(dev_num); if (blkcnt == 0) return 0; if (!mmc) return 0; if (mmc_set_blocklen(mmc, mmc->write_bl_len)) return 0; do { cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo; if(mmc_write_blocks(mmc, start, cur, src) != cur) return 0; blocks_todo -= cur; start += cur; // src += cur * mmc->write_bl_len; src = (char*)src + cur * mmc->write_bl_len; } while (blocks_todo > 0); return blkcnt; }
ulong skymedi_write_file(struct mmc * mmc, lbaint_t start, char *name, u32 timeout_ms) { unsigned char *buffer = (unsigned char *)Bulk_out_buf; //??? file_header_t *header = get_file_header(buffer, BULK_OUT_BUF_SIZE, name); if (header == NULL) { printf("can't find file %s\n", name); return 0; } u32 size = header->size; void *src = buffer + header->offset; lbaint_t blkcnt = (size - 1) / 512 + 1; lbaint_t cur, blocks_todo = blkcnt; if (mmc_set_blocklen(mmc, mmc->write_bl_len)) return 0; do { cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo; if (skymedi_write_blocks(mmc, start, cur, src, timeout_ms) != cur) return 0; blocks_todo -= cur; start += cur; src += cur * mmc->write_bl_len; } while (blocks_todo > 0); return blkcnt; }
unsigned long mmc_bread(int dev_num, unsigned long start, unsigned blkcnt, void *dst) { unsigned cur, blocks_todo = blkcnt; struct mmc *mmc = find_mmc_device(dev_num); if (blkcnt == 0){ mmcinfo("mmc %d blkcnt should not be 0\n",mmc->control_num); return 0; } if (!mmc){ mmcinfo("Can not find mmc dev %d\n",dev_num); return 0; } if ((start + blkcnt) > mmc->lba) { mmcinfo("mmc %d: block number 0x%x exceeds max(0x%x)\n",mmc->control_num, start + blkcnt, mmc->lba); return 0; } if (mmc_set_blocklen(mmc, mmc->read_bl_len)){ mmcinfo("mmc %d Set block len failed\n",mmc->control_num); return 0; } do { cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo; if(mmc_read_blocks(mmc, dst, start, cur) != cur){ mmcinfo("mmc %d block read failed\n",mmc->control_num); return 0; } blocks_todo -= cur; start += cur; // dst += cur * mmc->read_bl_len; dst = (char*)dst + cur * mmc->read_bl_len; } while (blocks_todo > 0); return blkcnt; }
unsigned long mmc_bwrite(int dev_num, unsigned long start, unsigned blkcnt, const void*src) { unsigned cur, blocks_todo = blkcnt; struct mmc *mmc = find_mmc_device(dev_num); if (blkcnt == 0){ mmcinfo("mmc %d blkcnt should not be 0\n",dev_num); return 0; } if (!mmc){ mmcinfo("Can not found device %d\n",dev_num); return 0; } if (mmc_set_blocklen(mmc, mmc->write_bl_len)){ mmcinfo("mmc %d set block len failed\n",mmc->control_num); // sunxi_mmc_exit(dev_num); // if(sunxi_mmc_init(dev_num,4)<0){ // mmcinfo("re init failed\n"); // return 0; // } return 0; } do { cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo; if(mmc_write_blocks(mmc, start, cur, src) != cur){ mmcinfo("mmc %d write block failed\n",mmc->control_num); return 0; } blocks_todo -= cur; start += cur; // src += cur * mmc->write_bl_len; src = (char*)src + cur * mmc->write_bl_len; } while (blocks_todo > 0); return blkcnt; }
int mmc_lock_unlock_by_buf(struct mmc_card *card, u8* key_buf,int key_len, int mode) { int err, data_size; int max_buf_size ; u8 *data_buf; max_buf_size = 32; data_size = 1; //max password(16byte) max_key = max_password(old) + max_password(new) + 0xFF + 0xFF = 34 if(key_len > 30) { return -EINVAL; } if (!(mode & MMC_LOCK_MODE_ERASE)) { // data_size = key_len ; data_size = max_buf_size; } data_buf = kzalloc(max_buf_size, GFP_KERNEL); if (!data_buf) { printk("%s kzalloc failed\n",__func__); return -ENOMEM; } memset(data_buf, 0, max_buf_size); data_buf[0] |= mode; if (mode & MMC_LOCK_MODE_UNLOCK) data_buf[0] &= ~MMC_LOCK_MODE_UNLOCK; if (!(mode & MMC_LOCK_MODE_ERASE)) { data_buf[1] = key_len-2; //exclude end 2 chars (0xFF 0xFF) memcpy(data_buf + 2, key_buf, key_len); } else { data_buf[1] =0xff; data_buf[2] = 0xff; } /*-----------Set mmc Status Command-----------------------------*/ err = sd_send_status(card); if(err) { goto out; } printk("[SDLOCK] %s STATUS data_size=%d\r\n",__func__,data_size); /*------------Set Block Length Command--------------------------*/ err = sd_send_blocklen(card,data_size); if(err) { goto out; } printk("[SDLOCK] %s MMC_SET_BLOCKLEN \r\n",__func__); /*-----------Set Lock/Unlock Command---------------------------*/ err = sd_send_lock_unlock_cmd(card,data_buf,data_size,max_buf_size); if(err) { goto out; } printk("[SDLOCK] %s MMC_LOCK_UNLOCK \r\n",__func__); /*-------------Set mmc Status Command--------------------*/ err = sd_wait_lock_unlock_cmd(card,mode); if(err) { mmc_set_blocklen(card, 512); goto out; } err = mmc_set_blocklen(card, 512); out: kfree(data_buf); return err; }
int mmc_gen_cmd(struct mmc_card *card, void *buf, u8 index, u8 arg1, u8 arg2, u8 mode) { struct mmc_request mrq; struct mmc_command cmd; struct mmc_data data; struct mmc_command stop; struct scatterlist sg; void *data_buf; mmc_set_blocklen(card, 512); data_buf = kmalloc(512, GFP_KERNEL); if (data_buf == NULL) return -ENOMEM; memset(&mrq, 0, sizeof(struct mmc_request)); memset(&cmd, 0, sizeof(struct mmc_command)); memset(&data, 0, sizeof(struct mmc_data)); memset(&stop, 0, sizeof(struct mmc_command)); mrq.cmd = &cmd; mrq.data = &data; mrq.stop = &stop; cmd.opcode = MMC_GEN_CMD; cmd.arg = (arg2 << 16) | (arg1 << 8) | (index << 1) | mode; cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; data.blksz = 512; data.blocks = 1; data.flags = MMC_DATA_READ; data.sg = &sg; data.sg_len = 1; stop.opcode = MMC_STOP_TRANSMISSION; stop.arg = 0; stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; sg_init_one(&sg, data_buf, 512); mmc_set_data_timeout(&data, card); mmc_claim_host(card->host); mmc_wait_for_req(card->host, &mrq); mmc_release_host(card->host); memcpy(buf, data_buf, 512); kfree(data_buf); if (cmd.error) return cmd.error; if (data.error) return data.error; if (stop.error) return stop.error; return 0; }
void mmc_command(struct doorbell_command_t *dbc) { /* See sandbox_mmc.c for the command_data[] layout. */ int fd; unsigned command = dbc->command_data[0]; fd = open_mmc_file(get_mmc_device(dbc)); if (fd == -1) { fprintf(stderr, "Unable to open/create '%s'\n", mmc_file[get_mmc_device(dbc)]); command_failure(dbc, dbc->device_id); return; } mmc_clear_results(dbc); switch (command) { case MMC_CMD_GO_IDLE_STATE: /* NOP */ break; case MMC_CMD_SEND_OP_COND: mmc_send_op_cond(dbc); break; case MMC_CMD_ALL_SEND_CID: mmc_send_cid_register(dbc); break; case MMC_CMD_SET_RELATIVE_ADDR: /* SD_CMD_SEND_RELATIVE_ADDR */ dbc->command_data[8] = 0x500; break; case MMC_CMD_SWITCH: /* NOP */ break; case MMC_CMD_SELECT_CARD: dbc->command_data[8] = MMC_STATUS_RDY_FOR_DATA | MMC_STATUS; break; case MMC_CMD_SEND_EXT_CSD: if (dbc->command_data[4] == 0) /* SD_CMD_SEND_IF_COND */ command_timeout(dbc, dbc->device_id); else /* MMC_CMD_SEND_EXT_CSD */ mmc_send_ext_csd_register(dbc); break; case MMC_CMD_SEND_CSD: mmc_send_csd_register(dbc); break; case MMC_CMD_STOP_TRANSMISSION: verbose("%s: ignored '%d' command\n", __func__, command); break; case MMC_CMD_SEND_STATUS: dbc->command_data[8] = MMC_STATUS_RDY_FOR_DATA | MMC_STATUS; break; case MMC_CMD_SET_BLOCKLEN: mmc_set_blocklen(dbc, dbc->command_data[2]); break; case MMC_CMD_READ_SINGLE_BLOCK: { const unsigned start = dbc->command_data[2]; void *buf = (void *)(uintptr_t)dbc->command_data[4]; mmc_read_block(dbc, fd, start, 1, buf); break; } case MMC_CMD_READ_MULTIPLE_BLOCK: { const unsigned start = dbc->command_data[2]; void *buf = (void *)(uintptr_t)dbc->command_data[4]; const unsigned len = dbc->command_data[6]; mmc_read_block(dbc, fd, start, len, buf); break; } case MMC_CMD_WRITE_SINGLE_BLOCK: { const unsigned start = dbc->command_data[2]; void *buf = (void *)(uintptr_t)dbc->command_data[4]; mmc_write_block(dbc, fd, start, 1, buf); break; } case MMC_CMD_WRITE_MULTIPLE_BLOCK: { const unsigned start = dbc->command_data[2]; void *buf = (void *)(uintptr_t)dbc->command_data[4]; const unsigned len = dbc->command_data[6]; mmc_write_block(dbc, fd, start, len, buf); break; } case MMC_CMD_ERASE_GROUP_START: mmc_erase_group_start(dbc, dbc->command_data[2]); break; case MMC_CMD_ERASE_GROUP_END: mmc_erase_group_end(dbc, dbc->command_data[2]); break; case MMC_CMD_ERASE: mmc_erase_group(dbc, fd, mmc_erase_group_start_block, mmc_erase_group_end_block); break; case SD_CMD_APP_SEND_OP_COND: dbc->command_data[8] = 0; command_timeout(dbc, dbc->device_id); break; case SD_CMD_APP_SEND_SCR: /* Do not support higher clock speeds */ command_failure(dbc, dbc->device_id); break; case MMC_CMD_APP_CMD: dbc->command_data[8] = OCR_BUSY | OCR_HCS; break; default: mmc_unknown_command(dbc, command); break; } close(fd); }