in core/ms_block.c [585:652]
static int h_msb_send_command(struct memstick_dev *card,
struct memstick_request **out_mrq)
{
struct msb_data *msb = memstick_get_drvdata(card);
struct memstick_request *mrq = *out_mrq = &card->current_mrq;
u8 intreg;
if (mrq->error) {
dbg("send_command: unknown error");
return msb_exit_state_machine(msb, mrq->error);
}
again:
switch (msb->state) {
/* HACK: see h_msb_write_block */
case MSB_SC_SEND_WRITE_PARAMS: /* write param register*/
if (!msb_write_regs(msb,
offsetof(struct ms_register, param),
sizeof(struct ms_param_register),
&msb->regs.param))
return 0;
msb->state = MSB_SC_SEND_WRITE_OOB;
return 0;
case MSB_SC_SEND_WRITE_OOB:
if (!msb->command_need_oob) {
msb->state = MSB_SC_SEND_COMMAND;
goto again;
}
if (!msb_write_regs(msb,
offsetof(struct ms_register, extra_data),
sizeof(struct ms_extra_data_register),
&msb->regs.extra_data))
return 0;
msb->state = MSB_SC_SEND_COMMAND;
return 0;
case MSB_SC_SEND_COMMAND:
memstick_init_req(mrq, MS_TPC_SET_CMD, &msb->command_value, 1);
msb->state = MSB_SC_SEND_INT_REQ;
return 0;
case MSB_SC_SEND_INT_REQ:
msb->state = MSB_SC_RECEIVE_INT_REQ;
if (msb_read_int_reg(msb, -1))
return 0;
fallthrough;
case MSB_SC_RECEIVE_INT_REQ:
intreg = mrq->data[0];
if (intreg & MEMSTICK_INT_CMDNAK)
return msb_exit_state_machine(msb, -EIO);
if (intreg & MEMSTICK_INT_ERR)
return msb_exit_state_machine(msb, -EBADMSG);
if (!(intreg & MEMSTICK_INT_CED)) {
msb->state = MSB_SC_SEND_INT_REQ;
goto again;
}
return msb_exit_state_machine(msb, 0);
}
BUG();
}