Deleted Added
full compact
busdma_bounce.c (143284) busdma_bounce.c (143293)
1/*-
2 * Copyright (c) 1997, 1998 Justin T. Gibbs.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1997, 1998 Justin T. Gibbs.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/i386/i386/busdma_machdep.c 143284 2005-03-08 11:18:14Z mux $");
28__FBSDID("$FreeBSD: head/sys/i386/i386/busdma_machdep.c 143293 2005-03-08 14:44:33Z mux $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/malloc.h>
33#include <sys/bus.h>
34#include <sys/interrupt.h>
35#include <sys/kernel.h>
36#include <sys/ktr.h>

--- 183 unchanged lines hidden (view full) ---

220 maxsegsz = boundary;
221
222 /* Return a NULL tag on failure */
223 *dmat = NULL;
224
225 newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF,
226 M_ZERO | M_NOWAIT);
227 if (newtag == NULL) {
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/malloc.h>
33#include <sys/bus.h>
34#include <sys/interrupt.h>
35#include <sys/kernel.h>
36#include <sys/ktr.h>

--- 183 unchanged lines hidden (view full) ---

220 maxsegsz = boundary;
221
222 /* Return a NULL tag on failure */
223 *dmat = NULL;
224
225 newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF,
226 M_ZERO | M_NOWAIT);
227 if (newtag == NULL) {
228 CTR3(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
228 CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
229 __func__, newtag, 0, error);
230 return (ENOMEM);
231 }
232
233 newtag->parent = parent;
234 newtag->alignment = alignment;
235 newtag->boundary = boundary;
236 newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);

--- 65 unchanged lines hidden (view full) ---

302 newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
303 }
304
305 if (error != 0) {
306 free(newtag, M_DEVBUF);
307 } else {
308 *dmat = newtag;
309 }
229 __func__, newtag, 0, error);
230 return (ENOMEM);
231 }
232
233 newtag->parent = parent;
234 newtag->alignment = alignment;
235 newtag->boundary = boundary;
236 newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);

--- 65 unchanged lines hidden (view full) ---

302 newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
303 }
304
305 if (error != 0) {
306 free(newtag, M_DEVBUF);
307 } else {
308 *dmat = newtag;
309 }
310 CTR3(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
310 CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
311 __func__, newtag, (newtag != NULL ? newtag->flags : 0), error);
312 return (error);
313}
314
315int
316bus_dma_tag_destroy(bus_dma_tag_t dmat)
317{
318 bus_dma_tag_t dmat_copy;

--- 24 unchanged lines hidden (view full) ---

343 * count on our parent.
344 */
345 dmat = parent;
346 } else
347 dmat = NULL;
348 }
349 }
350out:
311 __func__, newtag, (newtag != NULL ? newtag->flags : 0), error);
312 return (error);
313}
314
315int
316bus_dma_tag_destroy(bus_dma_tag_t dmat)
317{
318 bus_dma_tag_t dmat_copy;

--- 24 unchanged lines hidden (view full) ---

343 * count on our parent.
344 */
345 dmat = parent;
346 } else
347 dmat = NULL;
348 }
349 }
350out:
351 CTR2(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error);
351 CTR3(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error);
352 return (error);
353}
354
355/*
356 * Allocate a handle for mapping from kva/uva/physical
357 * address space into bus device space.
358 */
359int
360bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
361{
362 int error;
363
364 error = 0;
365
366 if (dmat->segments == NULL) {
367 dmat->segments = (bus_dma_segment_t *)malloc(
368 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
369 M_NOWAIT);
370 if (dmat->segments == NULL) {
352 return (error);
353}
354
355/*
356 * Allocate a handle for mapping from kva/uva/physical
357 * address space into bus device space.
358 */
359int
360bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
361{
362 int error;
363
364 error = 0;
365
366 if (dmat->segments == NULL) {
367 dmat->segments = (bus_dma_segment_t *)malloc(
368 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
369 M_NOWAIT);
370 if (dmat->segments == NULL) {
371 CTR2(KTR_BUSDMA, "%s: tag %p error %d",
371 CTR3(KTR_BUSDMA, "%s: tag %p error %d",
372 __func__, dmat, ENOMEM);
373 return (ENOMEM);
374 }
375 }
376
377 /*
378 * Bouncing might be required if the driver asks for an active
379 * exclusion region, a data alignment that is stricter than 1, and/or

--- 7 unchanged lines hidden (view full) ---

387 if (dmat->bounce_zone == NULL) {
388 if ((error = alloc_bounce_zone(dmat)) != 0)
389 return (error);
390 }
391
392 *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF,
393 M_NOWAIT | M_ZERO);
394 if (*mapp == NULL) {
372 __func__, dmat, ENOMEM);
373 return (ENOMEM);
374 }
375 }
376
377 /*
378 * Bouncing might be required if the driver asks for an active
379 * exclusion region, a data alignment that is stricter than 1, and/or

--- 7 unchanged lines hidden (view full) ---

387 if (dmat->bounce_zone == NULL) {
388 if ((error = alloc_bounce_zone(dmat)) != 0)
389 return (error);
390 }
391
392 *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF,
393 M_NOWAIT | M_ZERO);
394 if (*mapp == NULL) {
395 CTR2(KTR_BUSDMA, "%s: tag %p error %d",
395 CTR3(KTR_BUSDMA, "%s: tag %p error %d",
396 __func__, dmat, ENOMEM);
397 return (ENOMEM);
398 }
399
400 /* Initialize the new map */
401 STAILQ_INIT(&((*mapp)->bpages));
402
403 /*

--- 17 unchanged lines hidden (view full) ---

421 error = 0;
422 }
423 }
424 } else {
425 *mapp = NULL;
426 }
427 if (error == 0)
428 dmat->map_count++;
396 __func__, dmat, ENOMEM);
397 return (ENOMEM);
398 }
399
400 /* Initialize the new map */
401 STAILQ_INIT(&((*mapp)->bpages));
402
403 /*

--- 17 unchanged lines hidden (view full) ---

421 error = 0;
422 }
423 }
424 } else {
425 *mapp = NULL;
426 }
427 if (error == 0)
428 dmat->map_count++;
429 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
429 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
430 __func__, dmat, dmat->flags, error);
431 return (error);
432}
433
434/*
435 * Destroy a handle for mapping from kva/uva/physical
436 * address space into bus device space.
437 */
438int
439bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
440{
441 if (map != NULL && map != &nobounce_dmamap) {
442 if (STAILQ_FIRST(&map->bpages) != NULL) {
430 __func__, dmat, dmat->flags, error);
431 return (error);
432}
433
434/*
435 * Destroy a handle for mapping from kva/uva/physical
436 * address space into bus device space.
437 */
438int
439bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
440{
441 if (map != NULL && map != &nobounce_dmamap) {
442 if (STAILQ_FIRST(&map->bpages) != NULL) {
443 CTR2(KTR_BUSDMA, "%s: tag %p error %d",
443 CTR3(KTR_BUSDMA, "%s: tag %p error %d",
444 __func__, dmat, EBUSY);
445 return (EBUSY);
446 }
447 free(map, M_DEVBUF);
448 }
449 dmat->map_count--;
444 __func__, dmat, EBUSY);
445 return (EBUSY);
446 }
447 free(map, M_DEVBUF);
448 }
449 dmat->map_count--;
450 CTR1(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat);
450 CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat);
451 return (0);
452}
453
454
455/*
456 * Allocate a piece of memory that can be efficiently mapped into
457 * bus device space based on the constraints lited in the dma tag.
458 * A dmamap to for use with dmamap_load is also allocated.

--- 14 unchanged lines hidden (view full) ---

473 /* If we succeed, no mapping/bouncing will be required */
474 *mapp = NULL;
475
476 if (dmat->segments == NULL) {
477 dmat->segments = (bus_dma_segment_t *)malloc(
478 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
479 M_NOWAIT);
480 if (dmat->segments == NULL) {
451 return (0);
452}
453
454
455/*
456 * Allocate a piece of memory that can be efficiently mapped into
457 * bus device space based on the constraints lited in the dma tag.
458 * A dmamap to for use with dmamap_load is also allocated.

--- 14 unchanged lines hidden (view full) ---

473 /* If we succeed, no mapping/bouncing will be required */
474 *mapp = NULL;
475
476 if (dmat->segments == NULL) {
477 dmat->segments = (bus_dma_segment_t *)malloc(
478 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
479 M_NOWAIT);
480 if (dmat->segments == NULL) {
481 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
481 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
482 __func__, dmat, dmat->flags, ENOMEM);
483 return (ENOMEM);
484 }
485 }
486
487 if ((dmat->maxsize <= PAGE_SIZE) &&
488 dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) {
489 *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);

--- 4 unchanged lines hidden (view full) ---

494 * multi-seg allocations yet though.
495 * XXX Certain AGP hardware does.
496 */
497 *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
498 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul,
499 dmat->boundary);
500 }
501 if (*vaddr == NULL) {
482 __func__, dmat, dmat->flags, ENOMEM);
483 return (ENOMEM);
484 }
485 }
486
487 if ((dmat->maxsize <= PAGE_SIZE) &&
488 dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) {
489 *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);

--- 4 unchanged lines hidden (view full) ---

494 * multi-seg allocations yet though.
495 * XXX Certain AGP hardware does.
496 */
497 *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
498 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul,
499 dmat->boundary);
500 }
501 if (*vaddr == NULL) {
502 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
502 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
503 __func__, dmat, dmat->flags, ENOMEM);
504 return (ENOMEM);
505 }
503 __func__, dmat, dmat->flags, ENOMEM);
504 return (ENOMEM);
505 }
506 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
506 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
507 __func__, dmat, dmat->flags, ENOMEM);
508 return (0);
509}
510
511/*
512 * Free a piece of memory and it's allociated dmamap, that was allocated
513 * via bus_dmamem_alloc. Make the same choice for free/contigfree.
514 */

--- 7 unchanged lines hidden (view full) ---

522 if (map != NULL)
523 panic("bus_dmamem_free: Invalid map freed\n");
524 if ((dmat->maxsize <= PAGE_SIZE)
525 && dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem))
526 free(vaddr, M_DEVBUF);
527 else {
528 contigfree(vaddr, dmat->maxsize, M_DEVBUF);
529 }
507 __func__, dmat, dmat->flags, ENOMEM);
508 return (0);
509}
510
511/*
512 * Free a piece of memory and it's allociated dmamap, that was allocated
513 * via bus_dmamem_alloc. Make the same choice for free/contigfree.
514 */

--- 7 unchanged lines hidden (view full) ---

522 if (map != NULL)
523 panic("bus_dmamem_free: Invalid map freed\n");
524 if ((dmat->maxsize <= PAGE_SIZE)
525 && dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem))
526 free(vaddr, M_DEVBUF);
527 else {
528 contigfree(vaddr, dmat->maxsize, M_DEVBUF);
529 }
530 CTR2(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
530 CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
531}
532
533/*
534 * Utility function to load a linear buffer. lastaddrp holds state
535 * between invocations (for multiple-buffer loads). segp contains
536 * the starting segment on entrace, and the ending segment on exit.
537 * first indicates if this is the first invocation of this function.
538 */

--- 152 unchanged lines hidden (view full) ---

691 map->callback = callback;
692 map->callback_arg = callback_arg;
693 }
694
695 error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, NULL, flags,
696 &lastaddr, dmat->segments, &nsegs, 1);
697
698 if (error == EINPROGRESS) {
531}
532
533/*
534 * Utility function to load a linear buffer. lastaddrp holds state
535 * between invocations (for multiple-buffer loads). segp contains
536 * the starting segment on entrace, and the ending segment on exit.
537 * first indicates if this is the first invocation of this function.
538 */

--- 152 unchanged lines hidden (view full) ---

691 map->callback = callback;
692 map->callback_arg = callback_arg;
693 }
694
695 error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, NULL, flags,
696 &lastaddr, dmat->segments, &nsegs, 1);
697
698 if (error == EINPROGRESS) {
699 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
699 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
700 __func__, dmat, dmat->flags, error);
701 return (error);
702 }
703
704 if (error)
705 (*callback)(callback_arg, dmat->segments, 0, error);
706 else
707 (*callback)(callback_arg, dmat->segments, nsegs + 1, 0);
708
700 __func__, dmat, dmat->flags, error);
701 return (error);
702 }
703
704 if (error)
705 (*callback)(callback_arg, dmat->segments, 0, error);
706 else
707 (*callback)(callback_arg, dmat->segments, nsegs + 1, 0);
708
709 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error 0 nsegs %d",
709 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error 0 nsegs %d",
710 __func__, dmat, dmat->flags, nsegs + 1);
711 return (0);
712}
713
714
715/*
716 * Like _bus_dmamap_load(), but for mbufs.
717 */

--- 30 unchanged lines hidden (view full) ---

748
749 if (error) {
750 /* force "no valid mappings" in callback */
751 (*callback)(callback_arg, dmat->segments, 0, 0, error);
752 } else {
753 (*callback)(callback_arg, dmat->segments,
754 nsegs+1, m0->m_pkthdr.len, error);
755 }
710 __func__, dmat, dmat->flags, nsegs + 1);
711 return (0);
712}
713
714
715/*
716 * Like _bus_dmamap_load(), but for mbufs.
717 */

--- 30 unchanged lines hidden (view full) ---

748
749 if (error) {
750 /* force "no valid mappings" in callback */
751 (*callback)(callback_arg, dmat->segments, 0, 0, error);
752 } else {
753 (*callback)(callback_arg, dmat->segments,
754 nsegs+1, m0->m_pkthdr.len, error);
755 }
756 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
756 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
757 __func__, dmat, dmat->flags, error, nsegs + 1);
758 return (error);
759}
760
761int
762bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map,
763 struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs,
764 int flags)

--- 20 unchanged lines hidden (view full) ---

785 }
786 }
787 } else {
788 error = EINVAL;
789 }
790
791 /* XXX FIXME: Having to increment nsegs is really annoying */
792 ++*nsegs;
757 __func__, dmat, dmat->flags, error, nsegs + 1);
758 return (error);
759}
760
761int
762bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map,
763 struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs,
764 int flags)

--- 20 unchanged lines hidden (view full) ---

785 }
786 }
787 } else {
788 error = EINVAL;
789 }
790
791 /* XXX FIXME: Having to increment nsegs is really annoying */
792 ++*nsegs;
793 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
793 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
794 __func__, dmat, dmat->flags, error, *nsegs);
795 return (error);
796}
797
798/*
799 * Like _bus_dmamap_load(), but for uios.
800 */
801int

--- 43 unchanged lines hidden (view full) ---

845
846 if (error) {
847 /* force "no valid mappings" in callback */
848 (*callback)(callback_arg, dmat->segments, 0, 0, error);
849 } else {
850 (*callback)(callback_arg, dmat->segments,
851 nsegs+1, uio->uio_resid, error);
852 }
794 __func__, dmat, dmat->flags, error, *nsegs);
795 return (error);
796}
797
798/*
799 * Like _bus_dmamap_load(), but for uios.
800 */
801int

--- 43 unchanged lines hidden (view full) ---

845
846 if (error) {
847 /* force "no valid mappings" in callback */
848 (*callback)(callback_arg, dmat->segments, 0, 0, error);
849 } else {
850 (*callback)(callback_arg, dmat->segments,
851 nsegs+1, uio->uio_resid, error);
852 }
853 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
853 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
854 __func__, dmat, dmat->flags, error, nsegs + 1);
855 return (error);
856}
857
858/*
859 * Release the mapping held by map.
860 */
861void

--- 14 unchanged lines hidden (view full) ---

876
877 if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
878 /*
879 * Handle data bouncing. We might also
880 * want to add support for invalidating
881 * the caches on broken hardware
882 */
883 dmat->bounce_zone->total_bounced++;
854 __func__, dmat, dmat->flags, error, nsegs + 1);
855 return (error);
856}
857
858/*
859 * Release the mapping held by map.
860 */
861void

--- 14 unchanged lines hidden (view full) ---

876
877 if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
878 /*
879 * Handle data bouncing. We might also
880 * want to add support for invalidating
881 * the caches on broken hardware
882 */
883 dmat->bounce_zone->total_bounced++;
884 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
884 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
885 "performing bounce", __func__, op, dmat, dmat->flags);
886
887 if (op & BUS_DMASYNC_PREWRITE) {
888 while (bpage != NULL) {
889 bcopy((void *)bpage->datavaddr,
890 (void *)bpage->vaddr,
891 bpage->datacount);
892 bpage = STAILQ_NEXT(bpage, links);

--- 255 unchanged lines hidden ---
885 "performing bounce", __func__, op, dmat, dmat->flags);
886
887 if (op & BUS_DMASYNC_PREWRITE) {
888 while (bpage != NULL) {
889 bcopy((void *)bpage->datavaddr,
890 (void *)bpage->vaddr,
891 bpage->datacount);
892 bpage = STAILQ_NEXT(bpage, links);

--- 255 unchanged lines hidden ---