FreeBSD/sys/x86/x86/busdma_bounce.c
/*
 * Utility function to load a linear buffer.  segp contains
 * the starting segment on entrace, and the ending segment on exit.
 */
Utility function to load a linear buffer.  segp contains
the starting segment on entrace, and the ending segment on exit.
Utility function to load a linear buffer . segp contains the starting segment on entrace and the ending segment on exit .
static int
bounce_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
    bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs,
    int *segp)
{
	bus_size_t sgsize, max_sgsize;
	bus_addr_t curaddr;
	vm_offset_t kvaddr, vaddr;
	int error;
	if (map == NULL)
		map = &nobounce_dmamap;
	if (segs == NULL)
		segs = dmat->segments;
	if ((dmat->bounce_flags & BUS_DMA_COULD_BOUNCE) != 0) {
		_bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags);
		if (map->pagesneeded != 0) {
			error = _bus_dmamap_reserve_pages(dmat, map, flags);
			if (error)
				return (error);
		}
	}
	vaddr = (vm_offset_t)buf;
	while (buflen > 0) {
		if (pmap == kernel_pmap) {
			curaddr = pmap_kextract(vaddr);
			kvaddr = vaddr;
		} else {
			curaddr = pmap_extract(pmap, vaddr);
			kvaddr = 0;
		}
		max_sgsize = MIN(buflen, dmat->common.maxsegsz);
		sgsize = PAGE_SIZE - (curaddr & PAGE_MASK);
		if (((dmat->bounce_flags & BUS_DMA_COULD_BOUNCE) != 0) &&
		    map->pagesneeded != 0 &&
		    bus_dma_run_filter(&dmat->common, curaddr)) {
			sgsize = roundup2(sgsize, dmat->common.alignment);
			sgsize = MIN(sgsize, max_sgsize);
			curaddr = add_bounce_page(dmat, map, kvaddr, curaddr, 0,
			    sgsize);
		} else {
			sgsize = MIN(sgsize, max_sgsize);
		}
		sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
		    segp);
		if (sgsize == 0)
			break;
		vaddr += sgsize;
		buflen -= sgsize;
	}
	return (buflen != 0 ? EFBIG : 0); 
}
static int bounce_bus_dmamap_load_buffer ( bus_dma_tag_t dmat , bus_dmamap_t map , void * buf , bus_size_t buflen , pmap_t pmap , int flags , bus_dma_segment_t * segs , int * segp ) { bus_size_t sgsize , max_sgsize ; bus_addr_t curaddr ; vm_offset_t kvaddr , vaddr ; int error ; if ( map == NULL ) map = & nobounce_dmamap ; if ( segs == NULL ) segs = dmat -> segments ; if ( ( dmat -> bounce_flags & BUS_DMA_COULD_BOUNCE ) != 0 ) { _bus_dmamap_count_pages ( dmat , map , pmap , buf , buflen , flags ) ; if ( map -> pagesneeded != 0 ) { error = _bus_dmamap_reserve_pages ( dmat , map , flags ) ; if ( error ) return ( error ) ; } } vaddr = ( vm_offset_t ) buf ; while ( buflen > 0 ) { if ( pmap == kernel_pmap ) { curaddr = pmap_kextract ( vaddr ) ; kvaddr = vaddr ; } else { curaddr = pmap_extract ( pmap , vaddr ) ; kvaddr = 0 ; } max_sgsize = MIN ( buflen , dmat -> common . maxsegsz ) ; sgsize = PAGE_SIZE - ( curaddr & PAGE_MASK ) ; if ( ( ( dmat -> bounce_flags & BUS_DMA_COULD_BOUNCE ) != 0 ) && map -> pagesneeded != 0 && bus_dma_run_filter ( & dmat -> common , curaddr ) ) { sgsize = roundup2 ( sgsize , dmat -> common . alignment ) ; sgsize = MIN ( sgsize , max_sgsize ) ; curaddr = add_bounce_page ( dmat , map , kvaddr , curaddr , 0 , sgsize ) ; } else { sgsize = MIN ( sgsize , max_sgsize ) ; } sgsize = _bus_dmamap_addseg ( dmat , map , curaddr , sgsize , segs , segp ) ; if ( sgsize == 0 ) break ; vaddr += sgsize ; buflen -= sgsize ; } return ( buflen != 0 ? EFBIG : 0 ) ; }
Utility function to load a linear buffer.
Utility function to load a linear buffer .
/*
		 * Get the physical address for this segment.
		 */ /*
		 * Compute the segment size, and adjust counts.
		 */ /*
	 * Did we fit?
	 */ /* XXX better return value here? */