Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 09 Oct 2001 19:00:46 -0700
From:      Mike Smith <msmith@freebsd.org>
To:        "Eugene M. Kim" <gene@nttmcl.com>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: VM question (I hate Intel 810/815 chipsets...) 
Message-ID:  <200110100200.f9A20kI06030@mass.dis.org>
In-Reply-To: Message from "Eugene M. Kim" <gene@nttmcl.com>  of "Tue, 09 Oct 2001 16:57:35 PDT." <20011009165735.A22544@alicia.nttmcl.com> 

next in thread | previous in thread | raw e-mail | index | archive | help
> 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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200110100200.f9A20kI06030>