1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include <stdint.h>
21 #include <string.h>
22 #include <DA1469xAB.h>
23 #include <shm.h>
24 #include <mbox.h>
25
26 #define min(a, b) (((a) < (b)) ? (a) : (b))
27
28 static struct cmac_shm_mbox *
mbox_src_get(uint16_t * size)29 mbox_src_get(uint16_t *size)
30 {
31 *size = g_cmac_shm.config->mbox_c2s_size;
32
33 return g_cmac_shm.mbox_c2s;
34 }
35
36 static struct cmac_shm_mbox *
mbox_dst_get(uint16_t * size)37 mbox_dst_get(uint16_t *size)
38 {
39 *size = g_cmac_shm.config->mbox_s2c_size;
40
41 return g_cmac_shm.mbox_s2c;
42 }
43
44 int
cmac_mbox_has_data(void)45 cmac_mbox_has_data(void)
46 {
47 volatile struct cmac_shm_mbox *mbox;
48 uint16_t mbox_size;
49
50 mbox = mbox_src_get(&mbox_size);
51
52 return mbox->rd_off != mbox->wr_off;
53 }
54
55 int
cmac_mbox_read(void * data,uint16_t len)56 cmac_mbox_read(void *data, uint16_t len)
57 {
58 volatile struct cmac_shm_mbox *mbox;
59 uint16_t mbox_size;
60 uint8_t *mbox_buf;
61 uint16_t rd_off;
62 uint16_t wr_off;
63 uint16_t chunk_len;
64 uint16_t rem_len;
65
66 mbox = mbox_src_get(&mbox_size);
67 /* no need for volatile on data buffer */
68 mbox_buf = (void *)mbox->data;
69
70 rem_len = len;
71
72 do {
73 rd_off = mbox->rd_off;
74 wr_off = mbox->wr_off;
75
76 if (rd_off <= wr_off) {
77 chunk_len = wr_off - rd_off;
78 } else {
79 chunk_len = mbox_size - rd_off;
80 }
81
82 chunk_len = min(chunk_len, rem_len);
83
84 memcpy(data, &mbox_buf[rd_off], chunk_len);
85
86 data = (uint8_t *)data + chunk_len;
87 rem_len -= chunk_len;
88 rd_off += chunk_len;
89
90 mbox->rd_off = rd_off == mbox_size ? 0 : rd_off;
91 } while ((mbox->rd_off != mbox->wr_off) && (rem_len > 0));
92
93 return len - rem_len;
94 }
95
96 int
cmac_mbox_write(const void * data,uint16_t len)97 cmac_mbox_write(const void *data, uint16_t len)
98 {
99 volatile struct cmac_shm_mbox *mbox;
100 uint16_t mbox_size;
101 uint8_t *mbox_buf;
102 uint16_t rd_off;
103 uint16_t wr_off;
104 uint16_t max_wr;
105 uint16_t chunk;
106
107 mbox = mbox_dst_get(&mbox_size);
108 /* no need for volatile on data buffer */
109 mbox_buf = (void *)mbox->data;
110
111 while (len) {
112 rd_off = mbox->rd_off;
113 wr_off = mbox->wr_off;
114
115 /*
116 * Calculate maximum length to write, i.e. up to end of buffer or stop
117 * before rd_off to be able to detect full queue.
118 */
119 if (rd_off > wr_off) {
120 /*
121 * |0|1|2|3|4|5|6|7|
122 * | | | |W| | |R| |
123 * `---^
124 */
125 max_wr = rd_off - wr_off - 1;
126 } else if (rd_off == 0) {
127 /*
128 * |0|1|2|3|4|5|6|7|
129 * |R| | |W| | | | |
130 * `-------^
131 */
132 max_wr = mbox_size - wr_off - 1;
133 } else {
134 /*
135 * |0|1|2|3|4|5|6|7|
136 * | |R| |W| | | | |
137 * `---------^
138 */
139 max_wr = mbox_size - wr_off;
140 }
141
142 chunk = min(len, max_wr);
143
144 if (chunk == 0) {
145 continue;
146 }
147
148 memcpy(&mbox_buf[wr_off], data, chunk);
149
150 wr_off += chunk;
151 mbox->wr_off = wr_off == mbox_size ? 0 : wr_off;
152
153 cmac_signal();
154
155 len -= chunk;
156 data = (uint8_t *)data + chunk;
157 }
158
159 return 0;
160 }
161