in core/mspro_block.c [574:659]
static int h_mspro_block_transfer_data(struct memstick_dev *card,
struct memstick_request **mrq)
{
struct mspro_block_data *msb = memstick_get_drvdata(card);
unsigned char t_val = 0;
struct scatterlist t_sg = { 0 };
size_t t_offset;
if ((*mrq)->error)
return mspro_block_complete_req(card, (*mrq)->error);
switch ((*mrq)->tpc) {
case MS_TPC_WRITE_REG:
memstick_init_req(*mrq, MS_TPC_SET_CMD, &msb->transfer_cmd, 1);
(*mrq)->need_card_int = 1;
return 0;
case MS_TPC_SET_CMD:
t_val = (*mrq)->int_reg;
memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1);
if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT)
goto has_int_reg;
return 0;
case MS_TPC_GET_INT:
t_val = (*mrq)->data[0];
has_int_reg:
if (t_val & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) {
t_val = MSPRO_CMD_STOP;
memstick_init_req(*mrq, MS_TPC_SET_CMD, &t_val, 1);
card->next_request = h_mspro_block_default;
return 0;
}
if (msb->current_page
== (msb->req_sg[msb->current_seg].length
/ msb->page_size)) {
msb->current_page = 0;
msb->current_seg++;
if (msb->current_seg == msb->seg_count) {
if (t_val & MEMSTICK_INT_CED) {
return mspro_block_complete_req(card,
0);
} else {
card->next_request
= h_mspro_block_wait_for_ced;
memstick_init_req(*mrq, MS_TPC_GET_INT,
NULL, 1);
return 0;
}
}
}
if (!(t_val & MEMSTICK_INT_BREQ)) {
memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1);
return 0;
}
t_offset = msb->req_sg[msb->current_seg].offset;
t_offset += msb->current_page * msb->page_size;
sg_set_page(&t_sg,
nth_page(sg_page(&(msb->req_sg[msb->current_seg])),
t_offset >> PAGE_SHIFT),
msb->page_size, offset_in_page(t_offset));
memstick_init_req_sg(*mrq, msb->data_dir == READ
? MS_TPC_READ_LONG_DATA
: MS_TPC_WRITE_LONG_DATA,
&t_sg);
(*mrq)->need_card_int = 1;
return 0;
case MS_TPC_READ_LONG_DATA:
case MS_TPC_WRITE_LONG_DATA:
msb->current_page++;
if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) {
t_val = (*mrq)->int_reg;
goto has_int_reg;
} else {
memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1);
return 0;
}
default:
BUG();
}
}