diff --git a/share/man/man9/bus_dma.9 b/share/man/man9/bus_dma.9 index dd6fd2233a55..e72c57dc735b 100644 --- a/share/man/man9/bus_dma.9 +++ b/share/man/man9/bus_dma.9 @@ -60,6 +60,9 @@ .Nm bus_dma , .Nm bus_dma_tag_create , .Nm bus_dma_tag_destroy , +.Nm bus_dma_template_init , +.Nm bus_dma_template_tag , +.Nm bus_dma_template_clone , .Nm bus_dmamap_create , .Nm bus_dmamap_destroy , .Nm bus_dmamap_load , @@ -83,6 +86,21 @@ "void *lockfuncarg" "bus_dma_tag_t *dmat" .Ft int .Fn bus_dma_tag_destroy "bus_dma_tag_t dmat" +.Ft void +.Fo bus_dma_template_init +.Fa "bus_dma_template_t template" +.Fa "bus_dma_tag_t parent" +.Fc +.Ft int +.Fo bus_dma_template_tag +.Fa "bus_dma_template_t template" +.Fa "bus_dma_tag_t *dmat" +.Fc +.Ft void +.Fo bus_dma_template_clone +.Fa "bus_dma_template_t template" +.Fa "bus_dma_tag_t dmat" +.Fc .Ft int .Fn bus_dmamap_create "bus_dma_tag_t dmat" "int flags" "bus_dmamap_t *mapp" .Ft int @@ -282,6 +300,34 @@ DMA tags are organized into a hierarchy, with each child tag inheriting the restrictions of its parent. This allows all devices along the path of DMA transactions to contribute to the constraints of those transactions. +.It Vt bus_dma_template_t +A template structure for creating a +.Fa bus_dma_tag_t +from a set of defaults. +Once initialized with +.Fn bus_dma_template_init , +a driver can over-ride individual fields to suit its needs. +The following fields have the indicated values: +.Bd -literal + alignment 1 + boundary 0 + lowaddr BUS_SPACE_MAXADDR + highaddr BUS_SPACE_MAXADDR + maxsize BUS_SPACE_MAXSIZE + nsegments BUS_SPACE_UNRESTRICTED + maxsegsize BUS_SPACE_MAXSIZE + flags 0 + lockfunc NULL + lockfuncarg NULL +.Ed +.Pp +Descriptions of each field are documented with +.Fn bus_dma_tag_create . +Note that the +.Fa filtfunc +and +.Fa filtfuncarg +attributes of the DMA tag are not supported with templates. .It Vt bus_dma_filter_t Client specified address filter having the format: .Bl -tag -width indent @@ -633,6 +679,25 @@ if any DMA maps remain associated with or .Ql 0 on success. +.It Fn bus_dma_template_init "*template" "parent" +Initializes a +.Fa bus_dma_template_t +structure and associates it with an optional +.Fa parent . +The +.Fa parent +argument may be NULL. +.It Fn bus_dma_template_tag "*template" "*dmat" +Unpacks a template into a tag, and returns the tag via the +.Fa dmat . +All return values are identical to +.Fn bus_dma_tag_create . +.It Fn bus_dma_template_clone "*template" "dmat" +Clones the fields from a tag to a template. +This is useful for cloning tags when paired with +.Fn bus_dma_template_tag . +A template that is filled in as a clone does not need to be initialized +first. .It Fn bus_dmamap_create "dmat" "flags" "*mapp" Allocates and initializes a DMA map. Arguments are as follows: diff --git a/sys/arm/arm/busdma_machdep-v4.c b/sys/arm/arm/busdma_machdep-v4.c index 649ce05fdb38..6c1fd6a9e999 100644 --- a/sys/arm/arm/busdma_machdep-v4.c +++ b/sys/arm/arm/busdma_machdep-v4.c @@ -501,6 +501,57 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, return (error); } +void +bus_dma_template_init(bus_dma_tag_template_t *t, bus_dma_tag_t parent) +{ + + if (t == NULL) + return; + + t->parent = parent; + t->alignment = 1; + t->boundary = 0; + t->lowaddr = t->highaddr = BUS_SPACE_MAXADDR; + t->maxsize = t->maxsegsize = BUS_SPACE_MAXSIZE; + t->nsegments = BUS_SPACE_UNRESTRICTED; + t->lockfunc = NULL; + t->lockfuncarg = NULL; + t->flags = 0; +} + +int +bus_dma_template_tag(bus_dma_tag_template_t *t, bus_dma_tag_t *dmat) +{ + + if (t == NULL || dmat == NULL) + return (EINVAL); + + return (bus_dma_tag_create(t->parent, t->alignment, t->boundary, + t->lowaddr, t->highaddr, NULL, NULL, t->maxsize, + t->nsegments, t->maxsegsize, t->flags, t->lockfunc, t->lockfuncarg, + dmat)); +} + +void +bus_dma_template_clone(bus_dma_tag_template_t *t, bus_dma_tag_t dmat) +{ + + if (t == NULL || dmat == NULL) + return; + + t->parent = dmat->parent; + t->alignment = dmat->alignment; + t->boundary = dmat->boundary; + t->lowaddr = dmat->lowaddr; + t->highaddr = dmat->highaddr; + t->maxsize = dmat->maxsize; + t->nsegments = dmat->nsegments; + t->maxsegsize = dmat->maxsegsz; + t->flags = dmat->flags; + t->lockfunc = dmat->lockfunc; + t->lockfuncarg = dmat->lockfuncarg; +} + int bus_dma_tag_set_domain(bus_dma_tag_t dmat, int domain) { diff --git a/sys/arm/arm/busdma_machdep-v6.c b/sys/arm/arm/busdma_machdep-v6.c index fa79b1d913d0..6e2fb4a0d8f6 100644 --- a/sys/arm/arm/busdma_machdep-v6.c +++ b/sys/arm/arm/busdma_machdep-v6.c @@ -575,6 +575,57 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, return (error); } +void +bus_dma_template_init(bus_dma_tag_template_t *t, bus_dma_tag_t parent) +{ + + if (t == NULL) + return; + + t->parent = parent; + t->alignment = 1; + t->boundary = 0; + t->lowaddr = t->highaddr = BUS_SPACE_MAXADDR; + t->maxsize = t->maxsegsize = BUS_SPACE_MAXSIZE; + t->nsegments = BUS_SPACE_UNRESTRICTED; + t->lockfunc = NULL; + t->lockfuncarg = NULL; + t->flags = 0; +} + +int +bus_dma_template_tag(bus_dma_tag_template_t *t, bus_dma_tag_t *dmat) +{ + + if (t == NULL || dmat == NULL) + return (EINVAL); + + return (bus_dma_tag_create(t->parent, t->alignment, t->boundary, + t->lowaddr, t->highaddr, NULL, NULL, t->maxsize, + t->nsegments, t->maxsegsize, t->flags, t->lockfunc, t->lockfuncarg, + dmat)); +} + +void +bus_dma_template_clone(bus_dma_tag_template_t *t, bus_dma_tag_t dmat) +{ + + if (t == NULL || dmat == NULL) + return; + + t->parent = dmat->parent; + t->alignment = dmat->alignment; + t->boundary = dmat->boundary; + t->lowaddr = dmat->lowaddr; + t->highaddr = dmat->highaddr; + t->maxsize = dmat->maxsize; + t->nsegments = dmat->nsegments; + t->maxsegsize = dmat->maxsegsz; + t->flags = dmat->flags; + t->lockfunc = dmat->lockfunc; + t->lockfuncarg = dmat->lockfuncarg; +} + int bus_dma_tag_set_domain(bus_dma_tag_t dmat, int domain) { diff --git a/sys/arm64/arm64/busdma_machdep.c b/sys/arm64/arm64/busdma_machdep.c index 6abd213ccc9d..1a5ac67a2a4f 100644 --- a/sys/arm64/arm64/busdma_machdep.c +++ b/sys/arm64/arm64/busdma_machdep.c @@ -214,6 +214,60 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, return (error); } +void +bus_dma_template_init(bus_dma_tag_template_t *t, bus_dma_tag_t parent) +{ + + if (t == NULL) + return; + + t->parent = parent; + t->alignment = 1; + t->boundary = 0; + t->lowaddr = t->highaddr = BUS_SPACE_MAXADDR; + t->maxsize = t->maxsegsize = BUS_SPACE_MAXSIZE; + t->nsegments = BUS_SPACE_UNRESTRICTED; + t->lockfunc = NULL; + t->lockfuncarg = NULL; + t->flags = 0; +} + +int +bus_dma_template_tag(bus_dma_tag_template_t *t, bus_dma_tag_t *dmat) +{ + + if (t == NULL || dmat == NULL) + return (EINVAL); + + return (bus_dma_tag_create(t->parent, t->alignment, t->boundary, + t->lowaddr, t->highaddr, NULL, NULL, t->maxsize, + t->nsegments, t->maxsegsize, t->flags, t->lockfunc, t->lockfuncarg, + dmat)); +} + +void +bus_dma_template_clone(bus_dma_tag_template_t *t, bus_dma_tag_t dmat) +{ + struct bus_dma_tag_common *common; + + if (t == NULL || dmat == NULL) + return; + + common = (struct bus_dma_tag_common *)dmat; + + t->parent = (bus_dma_tag_t)common->parent; + t->alignment = common->alignment; + t->boundary = common->boundary; + t->lowaddr = common->lowaddr; + t->highaddr = common->highaddr; + t->maxsize = common->maxsize; + t->nsegments = common->nsegments; + t->maxsegsize = common->maxsegsz; + t->flags = common->flags; + t->lockfunc = common->lockfunc; + t->lockfuncarg = common->lockfuncarg; +} + int bus_dma_tag_destroy(bus_dma_tag_t dmat) { diff --git a/sys/mips/mips/busdma_machdep.c b/sys/mips/mips/busdma_machdep.c index 94c3eb8f5d37..ca7816d12952 100644 --- a/sys/mips/mips/busdma_machdep.c +++ b/sys/mips/mips/busdma_machdep.c @@ -476,6 +476,57 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, return (error); } +void +bus_dma_template_init(bus_dma_tag_template_t *t, bus_dma_tag_t parent) +{ + + if (t == NULL) + return; + + t->parent = parent; + t->alignment = 1; + t->boundary = 0; + t->lowaddr = t->highaddr = BUS_SPACE_MAXADDR; + t->maxsize = t->maxsegsize = BUS_SPACE_MAXSIZE; + t->nsegments = BUS_SPACE_UNRESTRICTED; + t->lockfunc = NULL; + t->lockfuncarg = NULL; + t->flags = 0; +} + +int +bus_dma_template_tag(bus_dma_tag_template_t *t, bus_dma_tag_t *dmat) +{ + + if (t == NULL || dmat == NULL) + return (EINVAL); + + return (bus_dma_tag_create(t->parent, t->alignment, t->boundary, + t->lowaddr, t->highaddr, NULL, NULL, t->maxsize, + t->nsegments, t->maxsegsize, t->flags, t->lockfunc, t->lockfuncarg, + dmat)); +} + +void +bus_dma_template_clone(bus_dma_tag_template_t *t, bus_dma_tag_t dmat) +{ + + if (t == NULL || dmat == NULL) + return; + + t->parent = dmat->parent; + t->alignment = dmat->alignment; + t->boundary = dmat->boundary; + t->lowaddr = dmat->lowaddr; + t->highaddr = dmat->highaddr; + t->maxsize = dmat->maxsize; + t->nsegments = dmat->nsegments; + t->maxsegsize = dmat->maxsegsz; + t->flags = dmat->flags; + t->lockfunc = dmat->lockfunc; + t->lockfuncarg = dmat->lockfuncarg; +} + int bus_dma_tag_set_domain(bus_dma_tag_t dmat, int domain) { diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c index 46fffad5712d..43196bc2eb2a 100644 --- a/sys/powerpc/powerpc/busdma_machdep.c +++ b/sys/powerpc/powerpc/busdma_machdep.c @@ -340,6 +340,57 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, return (error); } +void +bus_dma_template_init(bus_dma_tag_template_t *t, bus_dma_tag_t parent) +{ + + if (t == NULL) + return; + + t->parent = parent; + t->alignment = 1; + t->boundary = 0; + t->lowaddr = t->highaddr = BUS_SPACE_MAXADDR; + t->maxsize = t->maxsegsize = BUS_SPACE_MAXSIZE; + t->nsegments = BUS_SPACE_UNRESTRICTED; + t->lockfunc = NULL; + t->lockfuncarg = NULL; + t->flags = 0; +} + +int +bus_dma_template_tag(bus_dma_tag_template_t *t, bus_dma_tag_t *dmat) +{ + + if (t == NULL || dmat == NULL) + return (EINVAL); + + return (bus_dma_tag_create(t->parent, t->alignment, t->boundary, + t->lowaddr, t->highaddr, NULL, NULL, t->maxsize, + t->nsegments, t->maxsegsize, t->flags, t->lockfunc, t->lockfuncarg, + dmat)); +} + +void +bus_dma_template_clone(bus_dma_tag_template_t *t, bus_dma_tag_t dmat) +{ + + if (t == NULL || dmat == NULL) + return; + + t->parent = dmat->parent; + t->alignment = dmat->alignment; + t->boundary = dmat->boundary; + t->lowaddr = dmat->lowaddr; + t->highaddr = dmat->highaddr; + t->maxsize = dmat->maxsize; + t->nsegments = dmat->nsegments; + t->maxsegsize = dmat->maxsegsz; + t->flags = dmat->flags; + t->lockfunc = dmat->lockfunc; + t->lockfuncarg = dmat->lockfuncarg; +} + int bus_dma_tag_set_domain(bus_dma_tag_t dmat, int domain) { diff --git a/sys/riscv/riscv/busdma_machdep.c b/sys/riscv/riscv/busdma_machdep.c index 531371f5dda9..dc678bc166d1 100644 --- a/sys/riscv/riscv/busdma_machdep.c +++ b/sys/riscv/riscv/busdma_machdep.c @@ -214,6 +214,60 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, return (error); } +void +bus_dma_template_init(bus_dma_tag_template_t *t, bus_dma_tag_t parent) +{ + + if (t == NULL) + return; + + t->parent = parent; + t->alignment = 1; + t->boundary = 0; + t->lowaddr = t->highaddr = BUS_SPACE_MAXADDR; + t->maxsize = t->maxsegsize = BUS_SPACE_MAXSIZE; + t->nsegments = BUS_SPACE_UNRESTRICTED; + t->lockfunc = NULL; + t->lockfuncarg = NULL; + t->flags = 0; +} + +int +bus_dma_template_tag(bus_dma_tag_template_t *t, bus_dma_tag_t *dmat) +{ + + if (t == NULL || dmat == NULL) + return (EINVAL); + + return (bus_dma_tag_create(t->parent, t->alignment, t->boundary, + t->lowaddr, t->highaddr, NULL, NULL, t->maxsize, + t->nsegments, t->maxsegsize, t->flags, t->lockfunc, t->lockfuncarg, + dmat)); +} + +void +bus_dma_template_clone(bus_dma_tag_template_t *t, bus_dma_tag_t dmat) +{ + struct bus_dma_tag_common *common; + + if (t == NULL || dmat == NULL) + return; + + common = (struct bus_dma_tag_common *)dmat; + + t->parent = (bus_dma_tag_t)common->parent; + t->alignment = common->alignment; + t->boundary = common->boundary; + t->lowaddr = common->lowaddr; + t->highaddr = common->highaddr; + t->maxsize = common->maxsize; + t->nsegments = common->nsegments; + t->maxsegsize = common->maxsegsz; + t->flags = common->flags; + t->lockfunc = common->lockfunc; + t->lockfuncarg = common->lockfuncarg; +} + int bus_dma_tag_destroy(bus_dma_tag_t dmat) { diff --git a/sys/sparc64/sparc64/bus_machdep.c b/sys/sparc64/sparc64/bus_machdep.c index bdc965f0acbe..c887e264e2a0 100644 --- a/sys/sparc64/sparc64/bus_machdep.c +++ b/sys/sparc64/sparc64/bus_machdep.c @@ -250,6 +250,57 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, return (0); } +void +bus_dma_template_init(bus_dma_tag_template_t *t, bus_dma_tag_t parent) +{ + + if (t == NULL) + return; + + t->parent = parent; + t->alignment = 1; + t->boundary = 0; + t->lowaddr = t->highaddr = BUS_SPACE_MAXADDR; + t->maxsize = t->maxsegsize = BUS_SPACE_MAXSIZE; + t->nsegments = BUS_SPACE_UNRESTRICTED; + t->lockfunc = NULL; + t->lockfuncarg = NULL; + t->flags = 0; +} + +int +bus_dma_template_tag(bus_dma_tag_template_t *t, bus_dma_tag_t *dmat) +{ + + if (t == NULL || dmat == NULL) + return (EINVAL); + + return (bus_dma_tag_create(t->parent, t->alignment, t->boundary, + t->lowaddr, t->highaddr, NULL, NULL, t->maxsize, + t->nsegments, t->maxsegsize, t->flags, t->lockfunc, t->lockfuncarg, + dmat)); +} + +void +bus_dma_template_clone(bus_dma_tag_template_t *t, bus_dma_tag_t dmat) +{ + + if (t == NULL || dmat == NULL) + return; + + t->parent = dmat->dt_parent; + t->alignment = dmat->dt_alignment; + t->boundary = dmat->dt_boundary; + t->lowaddr = dmat->dt_lowaddr; + t->highaddr = dmat->dt_highaddr; + t->maxsize = dmat->dt_maxsize; + t->nsegments = dmat->dt_nsegments; + t->maxsegsize = dmat->dt_maxsegsz; + t->flags = dmat->dt_flags; + t->lockfunc = dmat->dt_lockfunc; + t->lockfuncarg = dmat->dt_lockfuncarg; +} + int bus_dma_tag_destroy(bus_dma_tag_t dmat) { diff --git a/sys/sys/bus_dma.h b/sys/sys/bus_dma.h index e99d8ecebe11..f70a8bb2b9ad 100644 --- a/sys/sys/bus_dma.h +++ b/sys/sys/bus_dma.h @@ -179,6 +179,24 @@ int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, void *lockfuncarg, bus_dma_tag_t *dmat); +/* Functions for creating and cloning tags via a template */ +typedef struct { + bus_dma_tag_t parent; + bus_size_t alignment; + bus_addr_t boundary; + bus_addr_t lowaddr; + bus_addr_t highaddr; + bus_size_t maxsize; + int nsegments; + bus_size_t maxsegsize; + int flags; + bus_dma_lock_t *lockfunc; + void *lockfuncarg; +} bus_dma_tag_template_t; +void bus_dma_template_init(bus_dma_tag_template_t *t, bus_dma_tag_t parent); +int bus_dma_template_tag(bus_dma_tag_template_t *t, bus_dma_tag_t *dmat); +void bus_dma_template_clone(bus_dma_tag_template_t *t, bus_dma_tag_t dmat); + /* * Set the memory domain to be used for allocations. * diff --git a/sys/x86/x86/busdma_machdep.c b/sys/x86/x86/busdma_machdep.c index 152fec591417..36c8d1f78315 100644 --- a/sys/x86/x86/busdma_machdep.c +++ b/sys/x86/x86/busdma_machdep.c @@ -238,6 +238,60 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, return (error); } +void +bus_dma_template_init(bus_dma_tag_template_t *t, bus_dma_tag_t parent) +{ + + if (t == NULL) + return; + + t->parent = parent; + t->alignment = 1; + t->boundary = 0; + t->lowaddr = t->highaddr = BUS_SPACE_MAXADDR; + t->maxsize = t->maxsegsize = BUS_SPACE_MAXSIZE; + t->nsegments = BUS_SPACE_UNRESTRICTED; + t->lockfunc = NULL; + t->lockfuncarg = NULL; + t->flags = 0; +} + +int +bus_dma_template_tag(bus_dma_tag_template_t *t, bus_dma_tag_t *dmat) +{ + + if (t == NULL || dmat == NULL) + return (EINVAL); + + return (bus_dma_tag_create(t->parent, t->alignment, t->boundary, + t->lowaddr, t->highaddr, NULL, NULL, t->maxsize, + t->nsegments, t->maxsegsize, t->flags, t->lockfunc, t->lockfuncarg, + dmat)); +} + +void +bus_dma_template_clone(bus_dma_tag_template_t *t, bus_dma_tag_t dmat) +{ + struct bus_dma_tag_common *common; + + if (t == NULL || dmat == NULL) + return; + + common = (struct bus_dma_tag_common *)dmat; + + t->parent = (bus_dma_tag_t)common->parent; + t->alignment = common->alignment; + t->boundary = common->boundary; + t->lowaddr = common->lowaddr; + t->highaddr = common->highaddr; + t->maxsize = common->maxsize; + t->nsegments = common->nsegments; + t->maxsegsize = common->maxsegsz; + t->flags = common->flags; + t->lockfunc = common->lockfunc; + t->lockfuncarg = common->lockfuncarg; +} + int bus_dma_tag_destroy(bus_dma_tag_t dmat) {