FreeBSD/sys/powerpc/powerpc/busdma_machdep.c
/*
 * Allocate a device specific dma_tag.
 */
Allocate a device specific dma_tag.
Allocate a device specific dma_tag .
int
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 = 0;
	if (boundary != 0 && boundary < maxsegsz)
		maxsegsz = boundary;
	if (maxsegsz == 0) {
		return (EINVAL);
	}
	*dmat = NULL;
	newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF,
	    M_ZERO | M_NOWAIT);
	if (newtag == NULL) {
		CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
		    __func__, newtag, 0, error);
		return (ENOMEM);
	}
	newtag->parent = parent;
	newtag->alignment = alignment;
	newtag->boundary = boundary;
	newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);
	newtag->highaddr = trunc_page((vm_paddr_t)highaddr) + (PAGE_SIZE - 1);
	newtag->filter = filter;
	newtag->filterarg = filterarg;
	newtag->maxsize = maxsize;
	newtag->nsegments = nsegments;
	newtag->maxsegsz = maxsegsz;
	newtag->flags = flags;
	newtag->ref_count = 1; 
	newtag->map_count = 0;
	if (lockfunc != NULL) {
		newtag->lockfunc = lockfunc;
		newtag->lockfuncarg = lockfuncarg;
	} else {
		newtag->lockfunc = dflt_lock;
		newtag->lockfuncarg = NULL;
	}
	if (parent != NULL) {
		newtag->lowaddr = MIN(parent->lowaddr, newtag->lowaddr);
		newtag->highaddr = MAX(parent->highaddr, newtag->highaddr);
		if (newtag->boundary == 0)
			newtag->boundary = parent->boundary;
		else if (parent->boundary != 0)
			newtag->boundary = MIN(parent->boundary,
					       newtag->boundary);
		if (newtag->filter == NULL) {
			newtag->filter = parent->filter;
			newtag->filterarg = parent->filterarg;
			newtag->parent = parent->parent;
		}
		if (newtag->parent != NULL)
			atomic_add_int(&parent->ref_count, 1);
		newtag->iommu = parent->iommu;
		newtag->iommu_cookie = parent->iommu_cookie;
	}
	if (newtag->lowaddr < ptoa((vm_paddr_t)Maxmem) && newtag->iommu == NULL)
		newtag->flags |= BUS_DMA_COULD_BOUNCE;
	if (newtag->alignment > 1)
		newtag->flags |= BUS_DMA_COULD_BOUNCE;
	if (((newtag->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->flags |= BUS_DMA_MIN_ALLOC_COMP;
	}
	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->flags : 0), error);
	return (error);
}
int 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 = 0 ; if ( boundary != 0 && boundary < maxsegsz ) maxsegsz = boundary ; if ( maxsegsz == 0 ) { return ( EINVAL ) ; } * dmat = NULL ; newtag = ( bus_dma_tag_t ) malloc ( sizeof ( * newtag ) , M_DEVBUF , M_ZERO | M_NOWAIT ) ; if ( newtag == NULL ) { CTR4 ( KTR_BUSDMA , " " , __func__ , newtag , 0 , error ) ; return ( ENOMEM ) ; } newtag -> parent = parent ; newtag -> alignment = alignment ; newtag -> boundary = boundary ; newtag -> lowaddr = trunc_page ( ( vm_paddr_t ) lowaddr ) + ( PAGE_SIZE - 1 ) ; newtag -> highaddr = trunc_page ( ( vm_paddr_t ) highaddr ) + ( PAGE_SIZE - 1 ) ; newtag -> filter = filter ; newtag -> filterarg = filterarg ; newtag -> maxsize = maxsize ; newtag -> nsegments = nsegments ; newtag -> maxsegsz = maxsegsz ; newtag -> flags = flags ; newtag -> ref_count = 1 ; newtag -> map_count = 0 ; if ( lockfunc != NULL ) { newtag -> lockfunc = lockfunc ; newtag -> lockfuncarg = lockfuncarg ; } else { newtag -> lockfunc = dflt_lock ; newtag -> lockfuncarg = NULL ; } if ( parent != NULL ) { newtag -> lowaddr = MIN ( parent -> lowaddr , newtag -> lowaddr ) ; newtag -> highaddr = MAX ( parent -> highaddr , newtag -> highaddr ) ; if ( newtag -> boundary == 0 ) newtag -> boundary = parent -> boundary ; else if ( parent -> boundary != 0 ) newtag -> boundary = MIN ( parent -> boundary , newtag -> boundary ) ; if ( newtag -> filter == NULL ) { newtag -> filter = parent -> filter ; newtag -> filterarg = parent -> filterarg ; newtag -> parent = parent -> parent ; } if ( newtag -> parent != NULL ) atomic_add_int ( & parent -> ref_count , 1 ) ; newtag -> iommu = parent -> iommu ; newtag -> iommu_cookie = parent -> iommu_cookie ; } if ( newtag -> lowaddr < ptoa ( ( vm_paddr_t ) Maxmem ) && newtag -> iommu == NULL ) newtag -> flags |= BUS_DMA_COULD_BOUNCE ; if ( newtag -> alignment > 1 ) newtag -> flags |= BUS_DMA_COULD_BOUNCE ; if ( ( ( newtag -> 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 -> flags |= BUS_DMA_MIN_ALLOC_COMP ; } if ( error != 0 ) { free ( newtag , M_DEVBUF ) ; } else { * dmat = newtag ; } CTR4 ( KTR_BUSDMA , " " , __func__ , newtag , ( newtag != NULL ? newtag -> flags : 0 ) , error ) ; return ( error ) ; }
Allocate a device specific dma_tag.
Allocate a device specific dma_tag .
/* Basic sanity checking */ /* Return a NULL tag on failure */ /* Count ourself */ /* Take into account any restrictions imposed by our parent tag */ /*
			 * Short circuit looking at our parent directly
			 * since we have encapsulated all of its information
			 */ /* Must bounce */ /* Add pages to our bounce pool */ /* Performed initial allocation */