помогите завести пример, взятый из книжки Олега Цилюрика. Падает на pci_map_single и dma_pool_create, что с моей точки зрения не удивительно - указатели на pci_dev передаются нулевые, но dma_alloc_coherent это проглатывает...
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#define pool_size 1024
#define pool_align 8
// int direction = PCI_DMA_TODEVICE ;
// int direction = PCI_DMA_FROMDEVICE ;
static int direction = PCI_DMA_BIDIRECTIONAL;
//int direction = PCI_DMA_NONE;
static void output(char *kbuf, dma_addr_t handle, size_t size, char *string);
static int __init my_init(void)
{
char *kbuf;
dma_addr_t handle;
size_t size = (10 * PAGE_SIZE);
struct dma_pool *mypool;
/* dma_alloc_coherent method */
kbuf = dma_alloc_coherent(NULL, size, &handle, GFP_KERNEL);
output(kbuf, handle, size, "This is the dma_alloc_coherent() string");
dma_free_coherent(NULL, size, kbuf, handle);
goto out;
/* dma_map/unmap_single */
kbuf = kzalloc(size, GFP_KERNEL);
if (!kbuf) {
printk("error: no memory\n");
goto out;
}
handle = pci_map_single(NULL, kbuf, size, direction);
if(dma_mapping_error(NULL, handle)) {
printk("dma_map_single error");
kfree(kbuf);
}
output( kbuf, handle, size, "This is the dma_map_single() string" );
dma_unmap_single( NULL, handle, size, direction );
kfree( kbuf );
/* dma_pool method */
mypool = dma_pool_create("mypool", NULL, pool_size, pool_align, 0);
kbuf = dma_pool_alloc(mypool, GFP_KERNEL, &handle);
output(kbuf, handle, size, "This is the dma_pool_alloc() string");
dma_pool_free(mypool, kbuf, handle);
dma_pool_destroy(mypool);
goto out;
out:
return -1;
}
module_init(my_init);
MODULE_AUTHOR("Jerry Cooperstein");
MODULE_AUTHOR("Oleg Tsiliuric");
MODULE_DESCRIPTION("LDD:1.0 s_23/lab1_dma.c");
MODULE_LICENSE("GPL v2");
#define MARK "=> "
static void output(char *kbuf, dma_addr_t handle, size_t size, char *string)
{
unsigned long long diff;
diff = (unsigned long long)kbuf - handle;
printk(KERN_INFO MARK "kbuf=%p, handle=%p, size = %d\n", kbuf,
(void *)(unsigned long long)handle, (int)size);
printk(KERN_INFO MARK
"(kbuf-handle)= %p, %llu, PAGE_OFFSET=%lu, compare=%llu\n",
(void *)diff, diff, PAGE_OFFSET, diff - PAGE_OFFSET);
strcpy(kbuf, string);
printk(KERN_INFO MARK "string written was, %s\n", kbuf);
}
upd: ядро 3.9/3.10