From owner-freebsd-hackers Tue Oct 9 18:50:26 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from mass.dis.org (mass.dis.org [216.240.45.41]) by hub.freebsd.org (Postfix) with ESMTP id 39BE737B409 for ; Tue, 9 Oct 2001 18:50:21 -0700 (PDT) Received: from mass.dis.org (localhost [127.0.0.1]) by mass.dis.org (8.11.6/8.11.3) with ESMTP id f9A20kI06030; Tue, 9 Oct 2001 19:00:54 -0700 (PDT) (envelope-from msmith@mass.dis.org) Message-Id: <200110100200.f9A20kI06030@mass.dis.org> To: "Eugene M. Kim" Cc: freebsd-hackers@freebsd.org Subject: Re: VM question (I hate Intel 810/815 chipsets...) In-Reply-To: Message from "Eugene M. Kim" of "Tue, 09 Oct 2001 16:57:35 PDT." <20011009165735.A22544@alicia.nttmcl.com> Date: Tue, 09 Oct 2001 19:00:46 -0700 From: Mike Smith Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG > What would be the best way to allocate: > > 1) a VM page whose physical address falls within a certain boundary, and > 2) a VM object whose pages are contiguous in physical address space? > > Background: > The !@*%^*!&#^%*&!#^$!@ Intel 810/815 graphics controller requires its > instruction and hardware cursor buffers to reside within first 32MB and > 512MB of *physical* memory space respectively. :( :( ;( The XFree86 > driver assumes the Linux memory model (virtual addr == physical addr), > so it runs on Linux, but not always on FreeBSD. You want to write a device driver to match this particular chip, which uses the bus_dmamem functions to allocate a conforming memory region, and then allow the userland process to mmap this region through your device node. It's nasty, but this sort of thing is just not normally done like this in the *nix world. Here's a sample to give you an idea of what I'm talking about wrt. allocating the memory. size_t size; /* size of region */ bus_dma_tag_t tag; /* busdma goo */ bus_dma_map_t map; void *mem; /* virtual pointer to region */ vm_offset_t physmem; /* physical pointer to region */ /* create a tag describing the memory you want */ bus_dma_tag_create( NULL, /* inherit from nobody */ 1, 0, /* alignment, boundary */ 0, /* low address */ (32 * 1024 * 1024), /* high address */ NULL, NULL, /* filter and argument */ size, /* size of region */ 1, /* maximum physical frags */ 0, /* flags */ &tag); /* allocate memory conforming to the tag */ mem = bus_dmamem_alloc(tag, &mem, BUS_DMA_NOWAIT, &map); /* map the memory into bus-visible space */ bus_dmamap_load(tag, map, mem, size, helper, (void *)&physmem, 0); ... /* unmap/free memory, free tag */ bus_dmamap_unload(tag, map); bus_dmamam_free(tag, mem, map); bus_dma_tag_destroy(tag); /* save the physical address of the region */ void helper(void *arg, bus_dma_segment_t *segs, int nseg, int error) { *(vm_offset_t *)arg = segs->ds_addr; } Note that this is the *only* correct way to do this (modulo bugs in what I've just written here). Contigmalloc() is the wrong API, and you should not use it. Regards, Mike To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message