[vortex] User level DMA

Ricardo Luis Kulzer kulzer@inf.ufsm.br
Mon, 18 Dec 2000 20:19:03 -0200 (BRST)


    I would like to write a driver for a specifica apllication using
Vortex chip. In my case, I want to allocate a buffer in the driver (kernel
segment), map this buffer to user process memory using mmap and
remap_page_range, and send the buffer to NIC using ioctl. Does anybody
have already write anything in this way?
    I am trying, but I have not many experience, and I have some basics
doubts. I dont achieve success in remaping a skbuffer->data to a user
process. I wrote for example, the code below for the driver, user process
and testing. I load the driver, alloc a sk_buff, and put a initial string
"_INITIAL:__STRCPY TO SBUFFER_DATA______". I use a user process to map a
user process variable, str, to skbuffer->data, and copy "______TEST:STRCPY
TO STR______" to str (I think to skbuffer->data, because str is mapped in
skbuffer->data).
    At clanup_module, I print skbuffer->data, but it didn't change the
initial data, "_INITIAL:__STRCPY TO SBUFFER_DATA______".
    Whats wrong? Can I do user level DMA in this way?
    Thanks?

	R. Kulzer

/*########################################################################*/
/*############### mmaptest.c: the module ##################################*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/fs.h>
#include <linux/wrapper.h>
#include <asm/io.h>
#include <linux/skbuff.h>
#define MMT_BUF_SIZE 8024

static struct sk_buff *sbuffer;

static int mmaptest_mmap(struct file *filp, struct vm_area_struct *vma){
unsigned long page,pos;
unsigned long start = (unsigned long)vma->vm_start;
unsigned long size = (unsigned long)(vma->vm_end-vma->vm_start);
        if (size>MMT_BUF_SIZE)
                return -EINVAL;
        pos=(unsigned long) sbuffer->data;
        printk("\n<1>FROM KERNEL - Remaping str to buffer\n");
        while (size > 0) {
                page = virt_to_phys((void *)pos);
                if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
                        return -EAGAIN;
                start+=PAGE_SIZE;
                pos+=PAGE_SIZE;
                size-=PAGE_SIZE;
        }
        return 0;
}

void cleanup_module(void){
        printk("\n<1>CLEANUP FROM KERNEL - sbuffer->data:%s\n",sbuffer->data);	
	kfree_skb(sbuffer);
	unregister_chrdev(187,"mmaptest");
	return;
}

static int mmaptest_open(struct inode *inode, struct file *filp){
	MOD_INC_USE_COUNT;
	return 0;
}
		
static int mmaptest_release(struct inode *inode, struct file *filp){
	MOD_DEC_USE_COUNT;
	return 0;
}	

static struct file_operations mmaptest_fops = {
	mmap: 		mmaptest_mmap,
        open: 		mmaptest_open,
	release: 	mmaptest_release,	
};

int init_module(void) {
struct page *page;
int i;
char *s="_INITIAL:__STRCPY TO SBUFFER_DATA______";
	register_chrdev(187,"mmaptest",&mmaptest_fops);
	sbuffer=alloc_skb(MMT_BUF_SIZE,GFP_KERNEL);
        skb_reserve(sbuffer, 2);
        skb_put(sbuffer,strlen(s)+1);
        strcpy(sbuffer->data,s);
	return 0;
}

/*########################################################################*/
/*############### mmapdriver.c: the user process #####################*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>

int main (int argc, char *argv[])
{
char *str;
int fd;
        system("rm -f  /dev/mmaptest0");
        system("mknod /dev/mmaptest0 c 187 0");

	fd = open("/dev/mmaptest0",O_RDONLY);

	str = (char *)mmap(NULL,1024,PROT_WRITE,MAP_PRIVATE,fd,0);
	if (str==MAP_FAILED) {
			puts("Error!");
			return 1;
	};
	strcpy(str,"______TEST:STRCPY TO STR______");
	printf("\nFROM PROCESS: Coping <%s> to STR\n",str);
	munmap(str, 4096);
	close(fd);
	return 0;
}

/*########################################################################*/
/*###############  Makefile  #####################*/
all: mmaptest.o mmapdriver

KCFLAGS=-D__KERNEL__ -w  -Wstrict-prototypes -O2  -DMODULE
CFLAGS= -Wstrict-prototypes -w  -O2 -pipe

mmaptest.o: mmaptest.c
	gcc $(KCFLAGS) -c -o $@ $<

mmapdriver: mmapdriver.c
	gcc $(CFLAGS) -o $@ $<

test:
	insmod ./mmaptest.o
	./mmapdriver /dev/mmaptest0
	rmmod mmaptest

clean:
	rm -f mmapdriver mmaptest.o core   		
	rmmod mmaptest