scatter/gether的知识点 struct scatterlist
2016-12-27 17:17
1106 查看
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);
这个函数的返回值为申请到的DMA缓冲区的虚拟地址。此外,该函数还通过参数handle返回DMA缓冲区的总线地址。与之对应的释放函数为:
Linux内核还提供了PCI设备申请DMA缓冲区的函数pci_alloc_consistent(),原型为:
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的单元。
相关文章推荐
- 集散序列,散集序列?的使用。 struct scatterlist,scatter/gather散布表
- 集散序列,散集序列?的使用。 struct scatterlist,scatter/gather散布表
- struct scatterlist 使用
- 集散序列,散集序列?的使用。 struct scatterlist,scatter/gather散布表
- 战30天C++入门极限-C/C++中结构体(struct)知识点强化(5)
- Swift开发第五篇——四个知识点(Struct Mutable方法&Tuple&autoclosure&Optional Chain)
- "分散-聚集DMA"以及"scatterlist"
- 内核定时器struct timer_list
- LinkedList 以及Set知识点概括
- Java 面试高频提问知识点之:Set、List 和 Map 的区别
- member access within misaligned address 0x000000000031 for type 'struct ListNode', which requires 8 byte alignment
- C++中容易忘的知识点——list和forward_list(四)
- Data Struct \ list - insert - re…
- C/C++中结构体(struct)知识点强化
- linux内核数据结构之双向循环链表struct list_head(一)
- 战30天C++入门极限-C/C++中结构体(struct)知识点强化(6)
- hadoop 知识点list
- Java 面试高频提问知识点之:Set、List 和 Map 的区别
- Linux内核Crypto接口整理之一:Scatterlist Cryptographic API
- SD/MMC 中的scatterlist