in host/jmb38x_ms.c [299:364]
static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)
{
unsigned int length;
unsigned int off;
unsigned int t_size, p_cnt;
unsigned char *buf;
struct page *pg;
unsigned long flags = 0;
if (host->req->long_data) {
length = host->req->sg.length - host->block_pos;
off = host->req->sg.offset + host->block_pos;
} else {
length = host->req->data_len - host->block_pos;
off = 0;
}
while (length) {
unsigned int p_off;
if (host->req->long_data) {
pg = nth_page(sg_page(&host->req->sg),
off >> PAGE_SHIFT);
p_off = offset_in_page(off);
p_cnt = PAGE_SIZE - p_off;
p_cnt = min(p_cnt, length);
local_irq_save(flags);
buf = kmap_atomic(pg) + p_off;
} else {
buf = host->req->data + host->block_pos;
p_cnt = host->req->data_len - host->block_pos;
}
if (host->req->data_dir == WRITE)
t_size = !(host->cmd_flags & REG_DATA)
? jmb38x_ms_write_data(host, buf, p_cnt)
: jmb38x_ms_write_reg_data(host, buf, p_cnt);
else
t_size = !(host->cmd_flags & REG_DATA)
? jmb38x_ms_read_data(host, buf, p_cnt)
: jmb38x_ms_read_reg_data(host, buf, p_cnt);
if (host->req->long_data) {
kunmap_atomic(buf - p_off);
local_irq_restore(flags);
}
if (!t_size)
break;
host->block_pos += t_size;
length -= t_size;
off += t_size;
}
if (!length && host->req->data_dir == WRITE) {
if (host->cmd_flags & REG_DATA) {
writel(host->io_word[0], host->addr + TPC_P0);
writel(host->io_word[1], host->addr + TPC_P1);
} else if (host->io_pos) {
writel(host->io_word[0], host->addr + DATA);
}
}
return length;
}