struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_data_direction direction,
unsigned long flags)
{
struct pl08x_txd *local_txd;
unsigned int reg = 0;
int i;
/*
* Current implementation ASSUMES only one sg
*/
if (sg_len != 1)
BUG();
local_txd = kmalloc(sizeof(struct pl08x_txd), GFP_KERNEL);
if (!local_txd) {
dev_err(&pd.dmac->dev, "%s - no local_txd\n", __func__);
return NULL;
} else {
struct pl08x_dma_chan *local_chan =
container_of(chan, struct pl08x_dma_chan, chan);
dma_async_tx_descriptor_init(&local_txd->tx, chan);
if (direction == DMA_TO_DEVICE) {
local_txd->srcbus.addr = sgl->dma_address;
local_txd->dstbus.addr =
reg = local_chan->slave->tx_reg;
} else if (direction == DMA_FROM_DEVICE) {
local_txd->srcbus.addr =
reg = local_chan->slave->rx_reg;
local_txd->dstbus.addr = sgl->dma_address;
} else {
dev_err(&pd.dmac->dev,
"%s - direction unsupported\n", __func__);
return NULL;
}
/*
* Find the device array entry for this txd
* so that the txd has access to the peripheral data
*/
for (i = 0; i < PL08X_DMA_SIGNALS; i++) {
if (reg == (((unsigned int)(pd.pd->sd[i].io_addr))))
break;
}
local_txd->pcd = &pd.pd->sd[i];
local_txd->tx.tx_submit = pl08x_tx_submit;
local_txd->len = sgl->length;
INIT_LIST_HEAD(&local_txd->txd_list);
}
return &local_txd->tx;
}
| 上层程序调用此函数,对提出的DMA请求和scatter/gather list 信息进行预处理,其实主要就是根据你当前的一些参数,包括设备的DMA的地址进行匹配,找到合适的配置参数,用于以后的DMA各个参数的设置 |
| 找到和自己的匹配的那个参数,这些参数是之前在amba设备注册时候,已经设置和初始化好的一堆设置参数 |