1/* 2 * Copyright (c) 2014, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, CAB F.78, Universitaetstr 6, CH-8092 Zurich. 8 */ 9 10#include <barrelfish/barrelfish.h> 11#include <bench/bench.h> 12 13#include <thc/thc.h> 14 15#include <if/omap_sdma_defs.h> 16#include <if/omap_sdma_thc.h> 17 18#include <string.h> 19 20#define MAX_FRAME_SIZE (32UL*1024*1024) 21 22static struct capref src_frame, dst_frame; 23static uint8_t *src_buf, *dst_buf; 24 25extern char logo_data[101200]; 26 27static void allocate_and_map_frames(void) 28{ 29 errval_t err; 30 size_t retbytes; 31 32 err = frame_alloc(&src_frame, MAX_FRAME_SIZE, &retbytes); 33 assert(err_is_ok(err)); 34 assert(retbytes >= MAX_FRAME_SIZE); 35 36 err = frame_alloc(&dst_frame, MAX_FRAME_SIZE, &retbytes); 37 assert(err_is_ok(err)); 38 assert(retbytes >= MAX_FRAME_SIZE); 39 40 err = vspace_map_one_frame_attr((void**)&src_buf, MAX_FRAME_SIZE, src_frame, 41 VREGION_FLAGS_READ_WRITE_NOCACHE, 42 NULL, NULL); 43 assert(err_is_ok(err)); 44 45 err = vspace_map_one_frame_attr((void**)&dst_buf, MAX_FRAME_SIZE, dst_frame, 46 VREGION_FLAGS_READ_WRITE_NOCACHE, 47 NULL, NULL); 48 assert(err_is_ok(err)); 49} 50 51static void fill_mem(void *buf, size_t bytesize, bool iterate, uint32_t val) 52{ 53 assert(buf); 54 assert(bytesize % sizeof(uint32_t) == 0); 55 56 uint32_t *fillbuf = buf; 57 size_t size = bytesize / sizeof(uint32_t); 58 59 for(size_t i=0; i<size; i++) { 60 fillbuf[i] = (iterate) ? i : val; 61 } 62} 63 64static void test_mem(void *buf, size_t bytesize, bool iterate, uint32_t val) 65{ 66 assert(buf); 67 assert(bytesize % sizeof(uint32_t) == 0); 68 69 uint32_t *fillbuf = buf; 70 size_t size = bytesize / sizeof(uint32_t); 71 72 for(size_t i=0; i<size; i++) { 73 uint32_t expected = (iterate) ? i : val; 74 if(fillbuf[i] != expected) { 75 USER_PANIC("Invalid word 0x%08x at offset %zu, expected 0x%08x\n", 76 fillbuf[i], i, expected); 77 } 78 } 79} 80 81static void rotate_16bit_image(uint16_t *dst, uint16_t *src, 82 omap_sdma_addr_2d_t addr, 83 omap_sdma_count_2d_t count) 84{ 85 assert(dst && src); 86 assert(count.pixel_size == omap_sdma_DATA_TYPE_16BIT); 87 88 dst += addr.x_start + (count.y_count * addr.y_start); 89 for (size_t y = 1; y <= count.y_count; y++) { 90 for (size_t x = 1; x <= count.x_count; x++) { 91 *dst = *(src++); 92 if (x < count.x_count) { 93 // within the frame 94 dst += addr.x_modify; 95 } else { 96 // at the end of a frame 97 dst += addr.y_modify; 98 } 99 } 100 } 101} 102 103static void transcopy_16bit_image(uint16_t *dst, uint16_t *src, 104 omap_sdma_count_2d_t count, 105 uint16_t color, uint32_t replacement) 106{ 107 assert(dst && src); 108 assert(count.pixel_size == omap_sdma_DATA_TYPE_16BIT); 109 110 for (size_t y = 1; y <= count.y_count; y++) { 111 for (size_t x = 1; x <= count.x_count; x++) { 112 *(dst) = (*src != color) ? *src : replacement; 113 114 dst++; src++; 115 } 116 } 117} 118 119static void run_client(struct omap_sdma_thc_client_binding_t *cl) 120{ 121 errval_t err; 122 123 debug_printf("mem_copy test\n"); 124 125 ////////// Test simple memory copying of whole frame ////////// 126 127 fill_mem(src_buf, MAX_FRAME_SIZE, true, 0); 128 fill_mem(dst_buf, MAX_FRAME_SIZE, false, 0); 129 cl->call_seq.mem_copy(cl, dst_frame, src_frame, &err); 130 if(err_is_fail(err)) { 131 USER_PANIC_ERR(err, "omap mem_copy"); 132 } 133 test_mem(dst_buf, MAX_FRAME_SIZE, true, 0); 134 135 ////////// Test simple memory filling of whole frame ////////// 136 137 debug_printf("mem_fill test\n"); 138 139 cl->call_seq.mem_fill(cl, dst_frame, 0xAB, &err); 140 if(err_is_fail(err)) { 141 USER_PANIC_ERR(err, "omap mem_fill"); 142 } 143 test_mem(dst_buf, MAX_FRAME_SIZE, false, 0xABABABAB); 144 145 ////////// 2D Simple Transfer Test ////////// 146 147 debug_printf("mem_copy_2d test\n"); 148 149 STATIC_ASSERT(MAX_FRAME_SIZE >= sizeof(logo_data), "frame too small"); 150 memcpy(src_buf, logo_data, sizeof(logo_data)); 151 152 omap_sdma_count_2d_t count_2d = { 153 .pixel_size = omap_sdma_DATA_TYPE_16BIT, 154 .x_count = 230, 155 .y_count = 220, 156 }; 157 158 omap_sdma_addr_2d_t src_addr = { 159 .cap = src_frame, 160 .x_start = 0, 161 .y_start = 0, 162 .x_modify = 1, 163 .y_modify = 1, 164 }; 165 166 omap_sdma_addr_2d_t dst_addr = src_addr; 167 dst_addr.cap = dst_frame; 168 169 cl->call_seq.mem_copy_2d(cl, dst_addr, src_addr, count_2d, false, 0, &err); 170 if(err_is_fail(err)) { 171 USER_PANIC_ERR(err, "omap mem_copy_2d"); 172 } else if (memcmp(dst_buf, logo_data, sizeof(logo_data)) != 0) { 173 USER_PANIC("dst buffer did not match image\n"); 174 } 175 176 ////////// 2D Rotation Test ////////// 177 178 debug_printf("mem_copy_2d rotation test\n"); 179 180 dst_addr.cap = dst_frame; 181 dst_addr.x_start = count_2d.y_count-1; // start in top right conrner 182 dst_addr.y_start = 0; 183 dst_addr.x_modify = count_2d.y_count; // jump down one row 184 dst_addr.y_modify = -((count_2d.x_count-1) * count_2d.y_count + 1); 185 186 cl->call_seq.mem_copy_2d(cl, dst_addr, src_addr, count_2d, false, 0, &err); 187 188 // rotate image in software for comparision 189 uint16_t *rot_data = malloc(sizeof(logo_data)); 190 rotate_16bit_image(rot_data, (uint16_t*)logo_data, dst_addr, count_2d); 191 192 if(err_is_fail(err)) { 193 USER_PANIC_ERR(err, "omap mem_copy_2d"); 194 } else if (memcmp(dst_buf, rot_data, sizeof(logo_data)) != 0) { 195 USER_PANIC("dst buffer did not match image\n"); 196 } 197 198 free(rot_data); 199 200 ////////// 2D Constant Fill ////////// 201 202 debug_printf("mem_fill_2d test\n"); 203 204 // reset destination addressing mode 205 dst_addr = src_addr; 206 dst_addr.cap = dst_frame; 207 208 cl->call_seq.mem_fill_2d(cl, dst_addr, 0x4242, count_2d, &err); 209 if(err_is_fail(err)) { 210 USER_PANIC_ERR(err, "omap mem_fill_2d"); 211 } 212 test_mem(dst_buf, sizeof(logo_data), false, 0x42424242); 213 214 ////////// 2D Transparent Copy ////////// 215 216 debug_printf("mem_copy_2d transparent copy test\n"); 217 218 dst_addr = src_addr; 219 dst_addr.cap = dst_frame; 220 221 cl->call_seq.mem_copy_2d(cl, dst_addr, src_addr, 222 count_2d, true, 0xFFFF, &err); 223 224 // perform transparent copy in software for comparision 225 uint16_t *trans_data = malloc(sizeof(logo_data)); 226 transcopy_16bit_image(trans_data, (uint16_t*)logo_data, 227 count_2d, 0xFFFF, 0x4242); 228 229 if(err_is_fail(err)) { 230 USER_PANIC_ERR(err, "omap mem_copy_2d"); 231 } else if (memcmp(dst_buf, trans_data, sizeof(logo_data)) != 0) { 232 USER_PANIC("dst buffer did not match image\n"); 233 } 234 235 free(trans_data); 236 237 ////////// Invalid Capability Test ////////// 238 239 debug_printf("mem_copy invalid cap test\n"); 240 241 cl->call_seq.mem_fill(cl, NULL_CAP, 0, &err); 242 if (err_no(err) != OMAP_SDMA_ERR_CAP_LOOKUP) { 243 USER_PANIC_ERR(err, "invalid capability lookup\n"); 244 } 245 246 ////////// Invalid Address Modifier Test ////////// 247 248 debug_printf("mem_copy_2d invalid address modifier test\n"); 249 250 dst_addr.x_modify = 0x10000; 251 dst_addr.y_modify = 1; 252 253 cl->call_seq.mem_copy_2d(cl, dst_addr, src_addr, count_2d, false, 0, &err); 254 if (err_no(err) != OMAP_SDMA_ERR_HARDWARE_LIMIT_ADDR) { 255 USER_PANIC_ERR(err, "oversized x_modify was not detected\n"); 256 } 257 258 dst_addr.x_modify = 1; 259 dst_addr.y_modify = INT32_MIN; 260 261 cl->call_seq.mem_copy_2d(cl, dst_addr, src_addr, count_2d, false, 0, &err); 262 if (err_no(err) != OMAP_SDMA_ERR_HARDWARE_LIMIT_ADDR) { 263 USER_PANIC_ERR(err, "invalid dst y_modify was not detected\n"); 264 } 265 266 src_addr.x_modify = 1; 267 src_addr.y_modify = INT32_MAX; 268 269 cl->call_seq.mem_copy_2d(cl, dst_addr, src_addr, count_2d, false, 0, &err); 270 if (err_no(err) != OMAP_SDMA_ERR_HARDWARE_LIMIT_ADDR) { 271 USER_PANIC_ERR(err, "invalid src y_modify was not detected\n"); 272 } 273 274 ////////// Invalid Frame Size Test ////////// 275 276 debug_printf("mem_copy_2d invalid frame size test\n"); 277 278 src_addr.x_modify = src_addr.y_modify = 1; 279 dst_addr.x_modify = dst_addr.y_modify = 1; 280 281 count_2d.x_count = 0x1000000; 282 count_2d.y_count = 1; 283 284 cl->call_seq.mem_copy_2d(cl, dst_addr, src_addr, count_2d, false, 0, &err); 285 if (err_no(err) != OMAP_SDMA_ERR_HARDWARE_LIMIT_SIZE) { 286 USER_PANIC_ERR(err, "invalid x_count was not detected\n"); 287 } 288 289 count_2d.y_count = 0x10000; 290 count_2d.x_count = 1; 291 292 cl->call_seq.mem_copy_2d(cl, dst_addr, src_addr, count_2d, false, 0, &err); 293 if (err_no(err) != OMAP_SDMA_ERR_HARDWARE_LIMIT_SIZE) { 294 USER_PANIC_ERR(err, "invalid y_count was not detected\n"); 295 } 296 297 count_2d.y_count = -1; 298 count_2d.x_count = -1; 299 300 cl->call_seq.mem_copy_2d(cl, dst_addr, src_addr, count_2d, false, 0, &err); 301 if (err_no(err) != OMAP_SDMA_ERR_HARDWARE_LIMIT_SIZE) { 302 USER_PANIC_ERR(err, "negative count was not detected\n"); 303 } 304 305 ////////// Out of Bounds Access Test ////////// 306 307 debug_printf("mem_copy_2d out of bounds test\n"); 308 309 count_2d.pixel_size = omap_sdma_DATA_TYPE_32BIT; 310 count_2d.x_count = MAX_FRAME_SIZE / 1024 / 4; 311 count_2d.y_count = 1024 + 1; 312 313 cl->call_seq.mem_copy_2d(cl, dst_addr, src_addr, count_2d, false, 0, &err); 314 if (err_no(err) != OMAP_SDMA_ERR_OUT_OF_BOUNDS) { 315 USER_PANIC_ERR(err, "out of bound access was not detected\n"); 316 } 317 318 count_2d.pixel_size = omap_sdma_DATA_TYPE_8BIT; 319 count_2d.x_count = MAX_FRAME_SIZE / 1024; 320 count_2d.y_count = 1024; 321 322 dst_addr.x_modify = dst_addr.y_modify = -1; 323 324 cl->call_seq.mem_copy_2d(cl, dst_addr, src_addr, count_2d, false, 0, &err); 325 if (err_no(err) != OMAP_SDMA_ERR_OUT_OF_BOUNDS) { 326 USER_PANIC_ERR(err, "out of bound access was not detected\n"); 327 } 328 329 debug_printf("finished all tests successfully\n"); 330} 331 332static void start_client(void) 333{ 334 errval_t err; 335 336 struct omap_sdma_binding *b; 337 struct omap_sdma_thc_client_binding_t *cl; 338 339 err = omap_sdma_thc_connect_by_name("sdma", 340 get_default_waitset(), 341 IDC_BIND_FLAGS_DEFAULT, 342 &b); 343 if (err_is_fail(err)) { 344 USER_PANIC_ERR(err, "could not bind (thc)"); 345 } 346 347 cl = malloc(sizeof(struct omap_sdma_thc_client_binding_t)); 348 assert(cl != NULL); 349 350 err = omap_sdma_thc_init_client(cl, b, b); 351 if (err_is_fail(err)) { 352 USER_PANIC_ERR(err, "could not init client (thc)"); 353 } 354 355 run_client(cl); 356 357 free(cl); 358} 359 360int main(int argc, char *argv[]) 361{ 362 allocate_and_map_frames(); 363 start_client(); 364 365 return 0; 366} 367