Subject: question about mmap
To: None <tech-kern@netbsd.org>
From: Chan-youn Park <phygeeks@gmail.com>
List: tech-kern
Date: 03/09/2005 17:12:30
Hi. I'm developing a device driver on PowerPC/Sandpoint platform. 

What I want to do is to implement an mmap interface in the device
driver. The device driver is for a DSP, and the DSP had its own
internal RAM which can be seen through PCI bus.

I've succeeded in seeing the memory space in the kernel, but when I
tried to see it using the mmap I've implemented, it does not work.

Well, below is the mmap code I've written.
----
paddr_t
tdspmmap(dev_t dev, off_t off, int prot)
{
        struct tdsp_softc *sc;
        char *name;
        paddr_t paddr;

        sc = device_lookup(&tdsp_cd, TDSPUNIT(dev));
        if (sc == NULL){
                ERROR("NULL sc is returned: "
                    "cannot proceed tdspmmap() anymore.\n");
                return (ENXIO);
        }
        name = sc->sc_dev.dv_xname;

        if (off >= TDSP_PMEM_MASK || off < 0){
                ERROR("%s: Offset is out of range.\n", name);
                return -1;
        }

        DEBUGF("%s: sc_pmema = 0x%08x, off = 0x%08x\n", name, sc->sc_pmema,
            (int)off);
        paddr = bus_space_mmap(sc->sc_pmemt, sc->sc_pmema, off, prot,
            BUS_SPACE_MAP_LINEAR);
        DEBUGF("%s: return value of bus_space_mmap = 0x%08x\n", name,
            (u_int32_t)paddr);
        return paddr;
}
----
here, pmemt and pmema is the tag and physical address of the DSP
memory space which are get using pci_mapreg_info.

And below is a part of a test application program to see the DSP memory space.
----
tdsph = open("/dev/tdsp", O_RDWR, 0);
sram.addr = mmap(0, sram.len, PROT_READ, MAP_SHARED, tdsph,
            (off_t)sram.offset);
 while(i < sram.len){
                addr = (u_int8_t*)sram.addr + i;
                printf("0x%08x: 0x%02x\n", (u_int32_t)addr, (u_int8_t)(*addr));
                i++;
        }
----
The printed results were meaningless data.

So I studied UVM a little bit, and found that udv_fault() calls the
device mmap function. So I checked what is happening in the middle of
udv_fault() by printing some parameters.
---
 printf("phygeeks: "
                    "MAPPING: device: pm=0x%x, va=0x%x, pa=0x%lx, at=%d",
                    (int)ufi->orig_map->pmap,
                    (int)curr_va,
                    (long)paddr,
                    (int)mapprot);
---
when I checked the result, it was that virtual memory was correctly
pointed from the userland application, and correct physical memory
page was given to pmap_enter through paddr, and mapprot had the value
of 1(which I think is not relevant to this problem).

Therefore I think my d_mmap code is doing the right thing, because it
gives udv_fault a correct page of the desired physical memory. But
when I try to see the content of it from the userland, what I see is
only meaningless data.

What should I check to see what is wrong? And in addition, is there a
good simple code that I can study the usage of device mmap function?