scatter/gether的知识点 struct scatterlist

来源:互联网 发布:ubuntu cuda 安装 编辑:程序博客网 时间:2024/06/05 10:02
struct scatterlist *sglist {
    unsigned long page_link;//page 位置,大约就是虚拟地址page的位置
    unsigned int offset;//偏移量
    unsigned int length;//长度
    dma_addr_t dma_address;//dma的地址,应该就是总线地址
    unsigned int dma_length;
}

我们有几个分散的内存内容要传送,需要调用
int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum_dma_direction direction);
nents是传入分散表的数量。返回值是要发送的dma缓冲的数目,它可能小于nents。(就是分散表中的一些元素可能是物理地址相邻的,就会被映射成一个内存块)如果返回0表示失败

int i, count;
struct scatterlist *sg;

count = dma_map_sg(dev, sglist, nents, direction);

for_each_sg(sglist, sg, count, i) {
    hw_address[i] = sg_dma_address(sg);
    hw_len[i] = sg_dma_len(sg);
}

sg_init_table(i2c->sg_io, 2);
sg_set_buf(&i2c->sg_io, &i2c->addr_data, 1);
sg_set_buf(&i2c->sg_io, msg->buf, msg->len);

dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);


sg_init_one(data.sg, idata->buf, idata->buf_bytes);

void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);

这个函数的返回值为申请到的DMA缓冲区的虚拟地址。此外,该函数还通过参数handle返回DMA缓冲区的总线地址。与之对应的释放函数为:

void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle);
dma_addr_t dma_map_single(struct device *dev, void *buffer, size_t size, enum dma_data_direction direction);  如果映射成功,返回的是总线地址,否则返回NULL.最后一个参数DMA的方向,可能取DMA_TO_DEVICE, DMA_FORM_DEVICE, DMA_BIDIRECTIONAL和DMA_NONE;



Linux内核还提供了PCI设备申请DMA缓冲区的函数pci_alloc_consistent(),原型为:

void *pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_addrp);  对应的释放函数为:
void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr, dma_addr_t dma_addr);.顺便补充下总线地址和物理地址1) 物理地址是与CPU相关的。在CPU的地址信号线上产生的就是物理地址。在程序指令中的虚拟地址经过段映射和页面映射后,就生成了物理地址,这个物理地址被放到CPU的地址线上。(从CPU端看)
2) 总线地址,顾名思义,是与总线相关的,就是总线的地址线或在地址周期上产生的信号。外设使用的是总线地址。(从设备端看)
3) 物理地址与总线地址之间的关系由系统的设计决定的。在x86平台上,物理地址与PCI总线地址是相同的。在其他平台上,也许会有某种转换,通常是线性的转换。

比如:CPU需要访问物理地址是0xfa000的单元,那么在x86平台上,会产生一个PCI总线上对0xfa000地址的访问。这个单元或者是内存中,或者是某个卡上的存储单元,甚至可能这个地址上没有对应的存储器。而在另外一个平台上,或许在PCI总线上产生的访问是针对地址为0x1fa000的单元。

0 0
原创粉丝点击