FreeBSD/sys/x86/x86/busdma_bounce.c
/*
 * Allocate a device specific dma_tag.
 */
Allocate a device specific dma_tag.
Allocate a device specific dma_tag .
static int
bounce_bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
    bus_addr_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr,
    bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize,
    int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
    void *lockfuncarg, bus_dma_tag_t *dmat)
{
	bus_dma_tag_t newtag;
	int error;
	*dmat = NULL;
	error = common_bus_dma_tag_create(parent != NULL ? &parent->common :
	    NULL, alignment, boundary, lowaddr, highaddr, filter, filterarg,
	    maxsize, nsegments, maxsegsz, flags, lockfunc, lockfuncarg,
	    sizeof (struct bus_dma_tag), (void **)&newtag);
	if (error != 0)
		return (error);
	newtag->common.impl = &bus_dma_bounce_impl;
	newtag->map_count = 0;
	newtag->segments = NULL;
	if (parent != NULL && ((newtag->common.filter != NULL) ||
	    ((parent->bounce_flags & BUS_DMA_COULD_BOUNCE) != 0)))
		newtag->bounce_flags |= BUS_DMA_COULD_BOUNCE;
	if (newtag->common.lowaddr < ptoa((vm_paddr_t)Maxmem) ||
	    newtag->common.alignment > 1)
		newtag->bounce_flags |= BUS_DMA_COULD_BOUNCE;
	if (((newtag->bounce_flags & BUS_DMA_COULD_BOUNCE) != 0) &&
	    (flags & BUS_DMA_ALLOCNOW) != 0) {
		struct bounce_zone *bz;
		if ((error = alloc_bounce_zone(newtag)) != 0) {
			free(newtag, M_DEVBUF);
			return (error);
		}
		bz = newtag->bounce_zone;
		if (ptoa(bz->total_bpages) < maxsize) {
			int pages;
			pages = atop(maxsize) - bz->total_bpages;
			if (alloc_bounce_pages(newtag, pages) < pages)
				error = ENOMEM;
		}
		newtag->bounce_flags |= BUS_DMA_MIN_ALLOC_COMP;
	} else
		error = 0;
	if (error != 0)
		free(newtag, M_DEVBUF);
	else
		*dmat = newtag;
	CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
	    __func__, newtag, (newtag != NULL ? newtag->common.flags : 0),
	    error);
	return (error);
}
static int bounce_bus_dma_tag_create ( bus_dma_tag_t parent , bus_size_t alignment , bus_addr_t boundary , bus_addr_t lowaddr , bus_addr_t highaddr , bus_dma_filter_t * filter , void * filterarg , bus_size_t maxsize , int nsegments , bus_size_t maxsegsz , int flags , bus_dma_lock_t * lockfunc , void * lockfuncarg , bus_dma_tag_t * dmat ) { bus_dma_tag_t newtag ; int error ; * dmat = NULL ; error = common_bus_dma_tag_create ( parent != NULL ? & parent -> common : NULL , alignment , boundary , lowaddr , highaddr , filter , filterarg , maxsize , nsegments , maxsegsz , flags , lockfunc , lockfuncarg , sizeof ( struct bus_dma_tag ) , ( void * * ) & newtag ) ; if ( error != 0 ) return ( error ) ; newtag -> common . impl = & bus_dma_bounce_impl ; newtag -> map_count = 0 ; newtag -> segments = NULL ; if ( parent != NULL && ( ( newtag -> common . filter != NULL ) || ( ( parent -> bounce_flags & BUS_DMA_COULD_BOUNCE ) != 0 ) ) ) newtag -> bounce_flags |= BUS_DMA_COULD_BOUNCE ; if ( newtag -> common . lowaddr < ptoa ( ( vm_paddr_t ) Maxmem ) || newtag -> common . alignment > 1 ) newtag -> bounce_flags |= BUS_DMA_COULD_BOUNCE ; if ( ( ( newtag -> bounce_flags & BUS_DMA_COULD_BOUNCE ) != 0 ) && ( flags & BUS_DMA_ALLOCNOW ) != 0 ) { struct bounce_zone * bz ; if ( ( error = alloc_bounce_zone ( newtag ) ) != 0 ) { free ( newtag , M_DEVBUF ) ; return ( error ) ; } bz = newtag -> bounce_zone ; if ( ptoa ( bz -> total_bpages ) < maxsize ) { int pages ; pages = atop ( maxsize ) - bz -> total_bpages ; if ( alloc_bounce_pages ( newtag , pages ) < pages ) error = ENOMEM ; } newtag -> bounce_flags |= BUS_DMA_MIN_ALLOC_COMP ; } else error = 0 ; if ( error != 0 ) free ( newtag , M_DEVBUF ) ; else * dmat = newtag ; CTR4 ( KTR_BUSDMA , " " , __func__ , newtag , ( newtag != NULL ? newtag -> common . flags : 0 ) , error ) ; return ( error ) ; }
Allocate a device specific dma_tag.
Allocate a device specific dma_tag .
/* Must bounce */ /* Add pages to our bounce pool */ /* Performed initial allocation */