in core/ms_block.c [1000:1077]
static int msb_write_block(struct msb_data *msb,
u16 pba, u32 lba, struct scatterlist *sg, int offset)
{
int error, current_try = 1;
BUG_ON(sg->length < msb->page_size);
if (msb->read_only)
return -EROFS;
if (pba == MS_BLOCK_INVALID) {
pr_err(
"BUG: write: attempt to write MS_BLOCK_INVALID block");
return -EINVAL;
}
if (pba >= msb->block_count || lba >= msb->logical_block_count) {
pr_err(
"BUG: write: attempt to write beyond the end of device");
return -EINVAL;
}
if (msb_get_zone_from_lba(lba) != msb_get_zone_from_pba(pba)) {
pr_err("BUG: write: lba zone mismatch");
return -EINVAL;
}
if (pba == msb->boot_block_locations[0] ||
pba == msb->boot_block_locations[1]) {
pr_err("BUG: write: attempt to write to boot blocks!");
return -EINVAL;
}
while (1) {
if (msb->read_only)
return -EROFS;
msb->regs.param.cp = MEMSTICK_CP_BLOCK;
msb->regs.param.page_address = 0;
msb->regs.param.block_address = cpu_to_be16(pba);
msb->regs.extra_data.management_flag = 0xFF;
msb->regs.extra_data.overwrite_flag = 0xF8;
msb->regs.extra_data.logical_address = cpu_to_be16(lba);
msb->current_sg = sg;
msb->current_sg_offset = offset;
msb->current_page = 0;
error = msb_run_state_machine(msb, h_msb_write_block);
/* Sector we just wrote to is assumed erased since its pba
* was erased. If it wasn't erased, write will succeed
* and will just clear the bits that were set in the block
* thus test that what we have written,
* matches what we expect.
* We do trust the blocks that we erased
*/
if (!error && (verify_writes ||
!test_bit(pba, msb->erased_blocks_bitmap)))
error = msb_verify_block(msb, pba, sg, offset);
if (!error)
break;
if (current_try > 1 || msb_reset(msb, true))
break;
pr_err("write failed, trying to erase the pba %d", pba);
error = msb_erase_block(msb, pba);
if (error)
break;
current_try++;
}
return error;
}