memory map driveru

Michl Ladislav xmichl03 na stud.fee.vutbr.cz
Středa Duben 18 08:01:34 CEST 2001


On Wed, 18 Apr 2001, Míla Kuchta wrote:

[snip]
> Lado, pokud chcete ziskat presnejsi odpoved a usetrit nam trochu casu
> za vesteni, neskolilo by, kdyby jste, pokud to neni tajemstvim, lepe
> specifikoval Vas zamer. Za prve mi neni uplne jasne, k cemu to ma
> slouzit, zda jde o zarizeni blokove ci znakove, I/O mapper atd.

diky za odpoved.

jde o VINO (specifikace na ftp://oss.sgi.com/pub/linux/mips/doc/indy/vino/)
a chtel bych k nemu napsat video4linux driver. odtud ty naroky na pamet,
umi 768x576 a to pri 24bit palete (ve skutecnosti RGBA 32bit) dava 1769472
byte, tj. pokud chci jen dva snimky, potrebuju 864 deskriptoru.

jak zarizeni funguje? do cache descriptoru natahne prvni ctverici. pote co
povolim DMA, zacne sypat data do systemove pameti, urcene prvnim
deskriptorem. kdyz zaplni celou stranku (4 kB), vezme dalsi deskriptor
atd. po vycerpani vsech 4 deskriptoru v cachi (nebo kesi - miluju cestinu
:-)) natahne dalsi ctverici atd.

> //spolecne
>
> int init_module(void)
> {
> 	...
> 	buffer = (char *) __get_free_page(GFP_KERNEL|GFP_DMA);
                          ^^^^^^^^^^^^^^^
a tohle mi da _jednu_ stranku. taky jste me trochu zmatl, budu se muset
podivat na rozdil mezi __get_free_page a get_free_page...
o teto funkci vim, to je prvni zpusob, ktery jsem popisoval, jen nevim,
jak takto ziskane pole deskriptoru namapovat do prostoru aplikace.

>         if (buffer == NULL)
> 	        return -ENOMEM;
>
> 	mem_map_reserve(MAP_NR(buffer));
> 	...
> }
>
> void cleanup_module(void)
> {
> 	...
> 	mem_map_unreserve(MAP_NR(buffer));
> 	free_page((unsigned long) buffer);
> 	...
> }
>
> 1) mmap
>
> //tohle zajisti namapovani prostoru ovladace do prostoru aplikace.
> //js. implementace mmap(2)u nad souborem zarizeni.
>
> static int zkouska_mmap(struct file *file, struct vm_area_struct *vma)
> {
> 	...
> 	if (remap_page_range(vma->vm_start, virt_to_phys(buffer), size,
> 			vma->vm_page_prot))
tohle bych videl na
        if (remap_page_range(vma->vm_start, virt_to_phys(buffer),
			PAGE_SIZE, vma->vm_page_prot))
tj. pokud by to byl adresovy prostor ziskany nejakou alloc funkci, tak
nejak takhle
        unsigned long start = (unsigned long)adr; /* sem se bude mapovat */
        unsigned long pos;

        pos = (unsigned long)buffer;
        while (size>0) {
                unsigned long 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 -EAGAIN;
> 	...
> }
>
> //non-blocking read/write
>
> static ssize_t zkouska_read/write(struct file *file, const char
> *bufer2, size_t count, loff_t *offset)
> {
> 	if (copy_to/from_user(bufer2/bufer, buffer/buffer2, count))
            ^^^^^^^^^^^^^^^^^ tak tohle je dobre akorat na ioctl (v mem
pripade), protoze Indy ma rychle DMA kanaly (60 MB/sec) a docela pomaly,
byt 64bit, procesor. jediny rozumny zpusob jak dostat obsah bufferu ven je
mmap.

> 		return -EFAULT;
> }

krasne rano,
ladislav michl




Další informace o konferenci Linux