coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
bouncebuf.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Generic bounce buffer implementation
4  */
5 
6 #include <arch/cache.h>
7 #include "bouncebuf.h"
8 #include "storage.h"
9 #include <string.h>
10 #include <commonlib/stdlib.h>
11 
12 static int addr_aligned(struct bounce_buffer *state)
13 {
14  const uint32_t align_mask = ARCH_DMA_MINALIGN - 1;
15 
16  // Check if start is aligned
17  if ((uintptr_t)state->user_buffer & align_mask) {
18  sdhc_debug("Unaligned buffer address %p\n", state->user_buffer);
19  return 0;
20  }
21 
22  // Check if length is aligned
23  if (state->len != state->len_aligned) {
24  sdhc_debug("Unaligned buffer length %zd\n", state->len);
25  return 0;
26  }
27 
28  // Aligned
29  return 1;
30 }
31 
32 int bounce_buffer_start(struct bounce_buffer *state, void *data,
33  size_t len, unsigned int flags)
34 {
35  state->user_buffer = data;
36  state->bounce_buffer = data;
37  state->len = len;
38  state->len_aligned = ROUND(len, ARCH_DMA_MINALIGN);
39  state->flags = flags;
40 
41  if (!addr_aligned(state)) {
42  state->bounce_buffer = memalign(ARCH_DMA_MINALIGN,
43  state->len_aligned);
44  if (!state->bounce_buffer)
45  return -1;
46 
47  if (state->flags & GEN_BB_READ)
48  memcpy(state->bounce_buffer, state->user_buffer,
49  state->len);
50  }
51 
52  /*
53  * Flush data to RAM so DMA reads can pick it up,
54  * and any CPU writebacks don't race with DMA writes
55  */
57  state->len_aligned);
58  return 0;
59 }
60 
62 {
63  if (state->flags & GEN_BB_WRITE) {
64  // Invalidate cache so that CPU can see any newly DMA'd data
65  dcache_invalidate_by_mva(state->bounce_buffer,
66  state->len_aligned);
67  }
68 
69  if (state->bounce_buffer == state->user_buffer)
70  return 0;
71 
72  if (state->flags & GEN_BB_WRITE)
73  memcpy(state->user_buffer, state->bounce_buffer, state->len);
74 
75  free(state->bounce_buffer);
76 
77  return 0;
78 }
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
int bounce_buffer_start(struct bounce_buffer *state, void *data, size_t len, unsigned int flags)
bounce_buffer_start() – Start the bounce buffer session state: stores state passed between bounce_buf...
Definition: bouncebuf.c:32
int bounce_buffer_stop(struct bounce_buffer *state)
bounce_buffer_stop() – Finish the bounce buffer session state: stores state passed between bounce_buf...
Definition: bouncebuf.c:61
static int addr_aligned(struct bounce_buffer *state)
Definition: bouncebuf.c:12
#define ARCH_DMA_MINALIGN
Definition: bouncebuf.h:81
#define GEN_BB_READ
Definition: bouncebuf.h:20
#define GEN_BB_WRITE
Definition: bouncebuf.h:28
#define ROUND(a, b)
Definition: bouncebuf.h:75
void * memalign(size_t boundary, size_t size)
Definition: malloc.c:20
void free(void *ptr)
Definition: malloc.c:67
state
Definition: raminit.c:1787
#define sdhc_debug(format...)
Definition: sd_mmc.h:64
unsigned int uint32_t
Definition: stdint.h:14
unsigned long uintptr_t
Definition: stdint.h:21
#define dcache_invalidate_by_mva(addr, len)
Definition: storage.h:17
#define dcache_clean_invalidate_by_mva(addr, len)
Definition: storage.h:18