1 /* 2 * SPDX-License-Identifier: BSD-3-Clause 3 * Copyright(c) 2023 Napatech A/S 4 */ 5 6 #include <time.h> 7 8 #include "nthw_drv.h" 9 #include "nthw_register.h" 10 #include "nthw_fpga_model.h" 11 #include "nthw_rac.h" 12 #include "ntlog.h" 13 14 /* 15 * NOTE: this needs to be (manually) synced with enum nthw_fpga_bus_type 16 */ 17 static const char *const sa_nthw_fpga_bus_type_str[] = { 18 "ERR", /* NTHW_FPGA_BUS_TYPE_UNKNOWN, */ 19 "BAR", /* NTHW_FPGA_BUS_TYPE_BAR, */ 20 "PCI", /* NTHW_FPGA_BUS_TYPE_PCI, */ 21 "CCIP", /* NTHW_FPGA_BUS_TYPE_CCIP, */ 22 "RAB0", /* NTHW_FPGA_BUS_TYPE_RAB0, */ 23 "RAB1", /* NTHW_FPGA_BUS_TYPE_RAB1, */ 24 "RAB2", /* NTHW_FPGA_BUS_TYPE_RAB2, */ 25 "NMB", /* NTHW_FPGA_BUS_TYPE_NMB, */ 26 "NDM", /* NTHW_FPGA_BUS_TYPE_NDM, */ 27 }; 28 29 static const char *get_bus_name(int n_bus_type_id) 30 { 31 if (n_bus_type_id >= 1 && n_bus_type_id <= (int)ARRAY_SIZE(sa_nthw_fpga_bus_type_str)) 32 return sa_nthw_fpga_bus_type_str[n_bus_type_id]; 33 34 else 35 return "ERR"; 36 } 37 38 /* 39 * module name lookup by id from array 40 * Uses naive linear search as performance is not an issue here... 41 */ 42 43 static const struct { 44 const nthw_id_t a; 45 const char *b; 46 } *sa_nthw_fpga_mod_str_map; 47 48 static const char *nthw_fpga_mod_id_to_str(nthw_id_t n_fpga_mod_id) 49 { 50 int i; 51 52 if (sa_nthw_fpga_mod_str_map) { 53 for (i = 0; sa_nthw_fpga_mod_str_map[i].a && sa_nthw_fpga_mod_str_map[i].b; i++) 54 if ((nthw_id_t)sa_nthw_fpga_mod_str_map[i].a == n_fpga_mod_id) 55 return sa_nthw_fpga_mod_str_map[i].b; 56 } 57 58 return "unknown"; 59 } 60 61 static int nthw_read_data(struct fpga_info_s *p_fpga_info, bool trc, int n_bus_type_id, 62 uint32_t addr, uint32_t len, uint32_t *p_data) 63 { 64 int rc = -1; 65 66 assert(p_fpga_info); 67 assert(p_data); 68 assert(len >= 1); 69 70 switch (n_bus_type_id) { 71 case NTHW_FPGA_BUS_TYPE_BAR: 72 case NTHW_FPGA_BUS_TYPE_PCI: 73 nthw_rac_bar0_read32(p_fpga_info, addr, len, p_data); 74 rc = 0; 75 break; 76 77 case NTHW_FPGA_BUS_TYPE_RAB0: 78 assert(p_fpga_info->mp_nthw_rac); 79 rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, trc, 0, addr, len, p_data); 80 break; 81 82 case NTHW_FPGA_BUS_TYPE_RAB1: 83 assert(p_fpga_info->mp_nthw_rac); 84 rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, trc, 1, addr, len, p_data); 85 break; 86 87 case NTHW_FPGA_BUS_TYPE_RAB2: 88 assert(p_fpga_info->mp_nthw_rac); 89 rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, trc, 2, addr, len, p_data); 90 break; 91 92 default: 93 assert(false); 94 return -1; 95 } 96 97 return rc; 98 } 99 100 static int nthw_write_data(struct fpga_info_s *p_fpga_info, bool trc, int n_bus_type_id, 101 uint32_t addr, uint32_t len, const uint32_t *p_data) 102 { 103 int rc = -1; 104 105 assert(p_fpga_info); 106 assert(p_data); 107 assert(len >= 1); 108 109 switch (n_bus_type_id) { 110 case NTHW_FPGA_BUS_TYPE_BAR: 111 case NTHW_FPGA_BUS_TYPE_PCI: 112 nthw_rac_bar0_write32(p_fpga_info, addr, len, p_data); 113 rc = 0; 114 break; 115 116 case NTHW_FPGA_BUS_TYPE_RAB0: 117 assert(p_fpga_info->mp_nthw_rac); 118 rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, trc, 0, addr, len, p_data); 119 break; 120 121 case NTHW_FPGA_BUS_TYPE_RAB1: 122 assert(p_fpga_info->mp_nthw_rac); 123 rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, trc, 1, addr, len, p_data); 124 break; 125 126 case NTHW_FPGA_BUS_TYPE_RAB2: 127 assert(p_fpga_info->mp_nthw_rac); 128 rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, trc, 2, addr, len, p_data); 129 break; 130 131 default: 132 assert(false); 133 return -1; 134 } 135 136 return rc; 137 } 138 139 uint64_t nthw_fpga_read_ident(struct fpga_info_s *p_fpga_info) 140 { 141 uint64_t n_fpga_ident; 142 uint32_t n_fpga_ident_lo, n_fpga_ident_hi; 143 nthw_rac_bar0_read32(p_fpga_info, 0x0, 1, &n_fpga_ident_lo); 144 nthw_rac_bar0_read32(p_fpga_info, 0x8, 1, &n_fpga_ident_hi); 145 n_fpga_ident = (((uint64_t)n_fpga_ident_hi << 32) | n_fpga_ident_lo); 146 return n_fpga_ident; 147 } 148 149 uint32_t nthw_fpga_read_buildtime(struct fpga_info_s *p_fpga_info) 150 { 151 uint32_t n_fpga_build_time; 152 nthw_rac_bar0_read32(p_fpga_info, 0x10, 1, &n_fpga_build_time); 153 return n_fpga_build_time; 154 } 155 156 int nthw_fpga_extract_type_id(const uint64_t n_fpga_ident) 157 { 158 return (uint16_t)(n_fpga_ident >> 32) & 0xFF; 159 } 160 161 int nthw_fpga_extract_prod_id(const uint64_t n_fpga_ident) 162 { 163 return (uint16_t)(n_fpga_ident >> 16) & 0xFFFF; 164 } 165 166 int nthw_fpga_extract_ver_id(const uint64_t n_fpga_ident) 167 { 168 return (uint16_t)((n_fpga_ident >> 8) & 0xFF); 169 } 170 171 int nthw_fpga_extract_rev_id(const uint64_t n_fpga_ident) 172 { 173 return (uint16_t)(n_fpga_ident & 0xFF); 174 } 175 176 /* 177 * FpgaMgr 178 */ 179 nthw_fpga_mgr_t *nthw_fpga_mgr_new(void) 180 { 181 nthw_fpga_mgr_t *p = malloc(sizeof(nthw_fpga_mgr_t)); 182 return p; 183 } 184 185 void nthw_fpga_mgr_delete(nthw_fpga_mgr_t *p) 186 { 187 memset(p, 0, sizeof(nthw_fpga_mgr_t)); 188 free(p); 189 } 190 191 void nthw_fpga_mgr_init(nthw_fpga_mgr_t *p, struct nthw_fpga_prod_init **pa_nthw_fpga_instances, 192 const void *pa_mod_str_map) 193 { 194 size_t i = 0; 195 196 p->mpa_fpga_prod_init = pa_nthw_fpga_instances; 197 sa_nthw_fpga_mod_str_map = pa_mod_str_map; 198 199 /* Count fpga instance in array */ 200 if (pa_nthw_fpga_instances) { 201 for (i = 0;; i++) 202 if (p->mpa_fpga_prod_init[i] == NULL) 203 break; 204 } 205 206 p->mn_fpgas = (int)i; 207 } 208 209 static nthw_fpga_t *nthw_fpga_mgr_lookup_fpga(nthw_fpga_mgr_t *p, uint64_t n_fpga_id, 210 struct fpga_info_s *p_fpga_info) 211 { 212 const int n_fpga_prod_id = nthw_fpga_extract_prod_id(n_fpga_id); 213 const int n_fpga_ver = nthw_fpga_extract_ver_id(n_fpga_id); 214 const int n_fpga_rev = nthw_fpga_extract_rev_id(n_fpga_id); 215 int i; 216 217 for (i = 0; i < p->mn_fpgas; i++) { 218 nthw_fpga_prod_init_s *p_init = p->mpa_fpga_prod_init[i]; 219 220 if (p_init->fpga_product_id == n_fpga_prod_id && 221 p_init->fpga_version == n_fpga_ver && p_init->fpga_revision == n_fpga_rev) { 222 nthw_fpga_t *p_fpga = nthw_fpga_model_new(); 223 nthw_fpga_model_init(p_fpga, p_init, p_fpga_info); 224 return p_fpga; 225 } 226 } 227 228 return NULL; 229 } 230 231 nthw_fpga_t *nthw_fpga_mgr_query_fpga(nthw_fpga_mgr_t *p_fpga_mgr, uint64_t n_fpga_id, 232 struct fpga_info_s *p_fpga_info) 233 { 234 const int n_fpga_prod_id = nthw_fpga_extract_prod_id(n_fpga_id); 235 const int n_fpga_ver = nthw_fpga_extract_ver_id(n_fpga_id); 236 const int n_fpga_rev = nthw_fpga_extract_rev_id(n_fpga_id); 237 238 nthw_fpga_t *p_fpga = nthw_fpga_mgr_lookup_fpga(p_fpga_mgr, n_fpga_id, p_fpga_info); 239 240 if (p_fpga) { 241 } else { 242 NT_LOG(ERR, NTHW, "FPGA Id 0x%" PRIX64 ": %04d: %d.%d: no match found\n", 243 n_fpga_id, n_fpga_prod_id, n_fpga_ver, n_fpga_rev); 244 } 245 246 return p_fpga; 247 } 248 249 250 void nthw_fpga_mgr_log_dump(nthw_fpga_mgr_t *p) 251 { 252 int i; 253 254 NT_LOG_DBGX(DEBUG, NTHW, "fpgas=%d\n", p->mn_fpgas); 255 256 for (i = 0; i < p->mn_fpgas; i++) { 257 nthw_fpga_prod_init_s *p_init = p->mpa_fpga_prod_init[i]; 258 (void)p_init; 259 NT_LOG_DBGX(DEBUG, NTHW, "fpga=%d/%d: %04d-%02d-%02d\n", i, p->mn_fpgas, 260 p_init->fpga_product_id, p_init->fpga_version, p_init->fpga_revision); 261 } 262 } 263 264 /* 265 * Fpga 266 */ 267 nthw_fpga_t *nthw_fpga_model_new(void) 268 { 269 nthw_fpga_t *p = malloc(sizeof(nthw_fpga_t)); 270 271 if (p) 272 memset(p, 0, sizeof(nthw_fpga_t)); 273 274 return p; 275 } 276 277 void nthw_fpga_model_init(nthw_fpga_t *p, nthw_fpga_prod_init_s *p_init, 278 struct fpga_info_s *p_fpga_info) 279 { 280 int i; 281 282 p->p_fpga_info = p_fpga_info; 283 p->mp_init = p_init; 284 285 p->mn_item_id = p_init->fpga_item_id; 286 p->mn_product_id = p_init->fpga_product_id; 287 p->mn_fpga_version = p_init->fpga_version; 288 p->mn_fpga_revision = p_init->fpga_revision; 289 p->mn_fpga_patch_no = p_init->fpga_patch_no; 290 p->mn_fpga_build_no = p_init->fpga_build_no; 291 p->mn_fpga_build_time = p_init->fpga_build_time; 292 293 p->mn_params = p_init->nb_prod_params; 294 295 if (p->mn_params) { 296 p->mpa_params = malloc(p->mn_params * sizeof(nthw_param_t *)); 297 298 if (p->mpa_params) { 299 memset(p->mpa_params, 0, (p->mn_params * sizeof(nthw_param_t *))); 300 301 for (i = 0; i < p->mn_params; i++) { 302 nthw_param_t *p_param = nthw_param_new(); 303 304 nthw_param_init(p_param, p, &p_init->product_params[i]); 305 p->mpa_params[i] = p_param; 306 } 307 } 308 } 309 310 p->mn_modules = p_init->nb_modules; 311 312 if (p->mn_modules) { 313 p->mpa_modules = malloc(p_init->nb_modules * sizeof(nthw_module_t *)); 314 315 if (p->mpa_modules) { 316 memset(p->mpa_modules, 0, (p->mn_modules * sizeof(nthw_module_t *))); 317 318 for (i = 0; i < p->mn_modules; i++) { 319 nthw_module_t *p_mod = nthw_module_new(); 320 321 nthw_module_init(p_mod, p, &p_init->modules[i]); 322 p->mpa_modules[i] = p_mod; 323 } 324 } 325 } 326 } 327 328 void nthw_fpga_set_debug_mode(nthw_fpga_t *p, int debug_mode) 329 { 330 int i; 331 332 p->m_debug_mode = debug_mode; 333 334 for (i = 0; i < p->mn_modules; i++) { 335 nthw_module_t *p_mod = p->mpa_modules[i]; 336 337 if (p_mod) 338 nthw_module_set_debug_mode(p_mod, debug_mode); 339 } 340 } 341 342 static nthw_module_t *nthw_fpga_lookup_module(const nthw_fpga_t *p, nthw_id_t id, int instance) 343 { 344 int i; 345 346 for (i = 0; i < p->mn_modules; i++) { 347 nthw_module_t *p_mod = p->mpa_modules[i]; 348 349 if (p_mod->mn_mod_id == id && p_mod->mn_instance == instance) 350 return p_mod; 351 } 352 353 return NULL; 354 } 355 356 nthw_module_t *nthw_fpga_query_module(const nthw_fpga_t *p, nthw_id_t id, int instance) 357 { 358 return nthw_fpga_lookup_module(p, id, instance); 359 } 360 361 int nthw_fpga_get_product_param(const nthw_fpga_t *p, const nthw_id_t n_param_id, 362 const int n_default_value) 363 { 364 int i; 365 366 for (i = 0; i < p->mn_params; i++) { 367 nthw_param_t *p_param = p->mpa_params[i]; 368 369 if (p_param->mn_param_id == n_param_id) 370 return p_param->mn_param_value; 371 } 372 373 return n_default_value; 374 } 375 376 int nthw_fpga_get_product_id(const nthw_fpga_t *p) 377 { 378 return p->mn_product_id; 379 } 380 381 /* 382 * Param 383 */ 384 nthw_param_t *nthw_param_new(void) 385 { 386 nthw_param_t *p = malloc(sizeof(nthw_param_t)); 387 388 return p; 389 } 390 391 void nthw_param_init(nthw_param_t *p, nthw_fpga_t *p_fpga, nthw_fpga_prod_param_s *p_init) 392 { 393 p->mp_owner = p_fpga; 394 p->mp_init = p_init; 395 396 p->mn_param_id = p_init->id; 397 p->mn_param_value = p_init->value; 398 } 399 400 /* 401 * Module 402 */ 403 nthw_module_t *nthw_module_new(void) 404 { 405 nthw_module_t *p = malloc(sizeof(nthw_module_t)); 406 407 return p; 408 } 409 410 void nthw_module_init(nthw_module_t *p, nthw_fpga_t *p_fpga, nthw_fpga_module_init_s *p_init) 411 { 412 int i; 413 414 p->mp_owner = p_fpga; 415 p->mp_init = p_init; 416 417 p->mn_mod_id = p_init->id; 418 p->mn_instance = p_init->instance; 419 420 /* Copy debug mode from owner */ 421 if (p->mp_owner) 422 p->mn_debug_mode = p->mp_owner->m_debug_mode; 423 424 else 425 p->mn_debug_mode = 0; 426 427 p->mn_mod_def_id = p_init->def_id; 428 p->mn_major_version = p_init->major_version; 429 p->mn_minor_version = p_init->minor_version; 430 p->mn_bus = p_init->bus_id; 431 p->mn_addr_base = p_init->addr_base; 432 433 p->mn_registers = p_init->nb_registers; 434 435 if (p->mn_registers) { 436 p->mpa_registers = malloc(p->mn_registers * sizeof(nthw_register_t *)); 437 438 if (p->mpa_registers) { 439 memset(p->mpa_registers, 0, (p->mn_registers * sizeof(nthw_register_t *))); 440 441 for (i = 0; i < p->mn_registers; i++) { 442 nthw_register_t *p_reg = nthw_register_new(); 443 444 nthw_register_init(p_reg, p, &p_init->registers[i]); 445 p->mpa_registers[i] = p_reg; 446 } 447 } 448 } 449 } 450 451 int nthw_module_get_major_version(const nthw_module_t *p) 452 { 453 return p->mn_major_version; 454 } 455 456 int nthw_module_get_minor_version(const nthw_module_t *p) 457 { 458 return p->mn_minor_version; 459 } 460 461 uint64_t nthw_module_get_version_packed64(const nthw_module_t *p) 462 { 463 return (((uint64_t)p->mn_major_version & 0xFFFFFFFF) << 32) | 464 (p->mn_minor_version & 0xFFFFFFFF); 465 } 466 467 bool nthw_module_is_version_newer(const nthw_module_t *p, int major_version, int minor_version) 468 { 469 if (major_version == p->mn_major_version) 470 return p->mn_minor_version >= minor_version; 471 472 return p->mn_major_version >= major_version; 473 } 474 475 static nthw_register_t *nthw_module_lookup_register(nthw_module_t *p, nthw_id_t id) 476 { 477 int i; 478 nthw_register_t *p_register = NULL; 479 480 for (i = 0; i < p->mn_registers; i++) { 481 if (p->mpa_registers[i]->mn_id == id) { 482 p_register = p->mpa_registers[i]; 483 break; 484 } 485 } 486 487 return p_register; 488 } 489 490 nthw_register_t *nthw_module_query_register(nthw_module_t *p, nthw_id_t id) 491 { 492 return nthw_module_lookup_register(p, id); 493 } 494 495 nthw_register_t *nthw_module_get_register(nthw_module_t *p, nthw_id_t id) 496 { 497 nthw_register_t *p_register; 498 499 if (p == NULL) { 500 NT_LOG(ERR, NTHW, "Illegal module context for register %u\n", id); 501 return NULL; 502 } 503 504 p_register = nthw_module_lookup_register(p, id); 505 506 if (!p_register) { 507 NT_LOG(ERR, NTHW, "Register %u not found in module: %s (%u)\n", id, 508 nthw_fpga_mod_id_to_str(p->mn_mod_id), p->mn_mod_id); 509 } 510 511 return p_register; 512 } 513 514 int nthw_module_get_debug_mode(const nthw_module_t *p) 515 { 516 return p->mn_debug_mode; 517 } 518 519 void nthw_module_set_debug_mode(nthw_module_t *p, unsigned int debug_mode) 520 { 521 int i; 522 523 p->mn_debug_mode = debug_mode; 524 525 for (i = 0; i < p->mn_registers; i++) { 526 nthw_register_t *p_register = p->mpa_registers[i]; 527 528 if (p_register) 529 nthw_register_set_debug_mode(p_register, debug_mode); 530 } 531 } 532 533 int nthw_module_get_bus(const nthw_module_t *p) 534 { 535 return p->mn_bus; 536 } 537 538 /* 539 * Register 540 */ 541 nthw_register_t *nthw_register_new(void) 542 { 543 nthw_register_t *p = malloc(sizeof(nthw_register_t)); 544 545 return p; 546 } 547 548 void nthw_register_init(nthw_register_t *p, nthw_module_t *p_module, 549 nthw_fpga_register_init_s *p_init) 550 { 551 int i; 552 553 p->mp_owner = p_module; 554 555 p->mn_id = p_init->id; 556 p->mn_bit_width = p_init->bw; 557 p->mn_addr_rel = p_init->addr_rel; 558 p->mn_addr = p_module->mn_addr_base + p_init->addr_rel; 559 p->mn_type = p_init->type; 560 /* Old P200 registers have no bw at register level - default to BW=-1 */ 561 p->mn_len = ((p_init->bw != (uint16_t)-1) ? ((p_init->bw + 31) >> 5) : 1); 562 p->mn_debug_mode = p_module->mn_debug_mode; 563 564 p->mn_fields = p_init->nb_fields; 565 566 if (p->mn_fields) { 567 p->mpa_fields = malloc(p->mn_fields * sizeof(nthw_field_t *)); 568 569 if (p->mpa_fields) { 570 memset(p->mpa_fields, 0, (p->mn_fields * sizeof(nthw_field_t *))); 571 572 for (i = 0; i < p->mn_fields; i++) { 573 nthw_field_t *p_field = nthw_field_new(); 574 575 nthw_field_init(p_field, p, &p_init->fields[i]); 576 p->mpa_fields[i] = p_field; 577 } 578 579 p->mp_shadow = malloc(p->mn_len * sizeof(uint32_t)); 580 581 if (p->mp_shadow) 582 memset(p->mp_shadow, 0x00, (p->mn_len * sizeof(uint32_t))); 583 584 p->mp_dirty = malloc(p->mn_len * sizeof(bool)); 585 586 if (p->mp_dirty) 587 memset(p->mp_dirty, 0x00, (p->mn_len * sizeof(bool))); 588 } 589 } 590 } 591 592 uint32_t nthw_register_get_address(const nthw_register_t *p) 593 { 594 return p->mn_addr; 595 } 596 597 void nthw_register_reset(const nthw_register_t *p) 598 { 599 int i; 600 nthw_field_t *p_field = NULL; 601 602 for (i = 0; i < p->mn_fields; i++) { 603 p_field = p->mpa_fields[i]; 604 605 if (p_field) 606 nthw_field_reset(p_field); 607 } 608 } 609 610 static nthw_field_t *nthw_register_lookup_field(const nthw_register_t *p, nthw_id_t id) 611 { 612 int i; 613 nthw_field_t *p_field = NULL; 614 615 if (!p) 616 return NULL; 617 618 for (i = 0; i < p->mn_fields; i++) { 619 if (p->mpa_fields[i]->mn_id == id) { 620 p_field = p->mpa_fields[i]; 621 break; 622 } 623 } 624 625 return p_field; 626 } 627 628 nthw_field_t *nthw_register_query_field(const nthw_register_t *p, nthw_id_t id) 629 { 630 return nthw_register_lookup_field(p, id); 631 } 632 633 nthw_field_t *nthw_register_get_field(const nthw_register_t *p, nthw_id_t id) 634 { 635 nthw_field_t *p_field; 636 637 if (p == NULL) { 638 NT_LOG(ERR, NTHW, "Illegal register context for field %u\n", id); 639 return NULL; 640 } 641 642 p_field = nthw_register_lookup_field(p, id); 643 644 if (!p_field) { 645 NT_LOG(ERR, NTHW, "Field %u not found in module: %s (%u)\n", id, 646 nthw_fpga_mod_id_to_str(p->mp_owner->mn_mod_id), p->mp_owner->mn_mod_id); 647 } 648 649 return p_field; 650 } 651 652 int nthw_register_get_bit_width(const nthw_register_t *p) 653 { 654 return p->mn_bit_width; 655 } 656 657 int nthw_register_get_debug_mode(const nthw_register_t *p) 658 { 659 return p->mn_debug_mode; 660 } 661 662 /* 663 * NOTE: do not set debug on fields - as register operation dumps typically are enough 664 */ 665 void nthw_register_set_debug_mode(nthw_register_t *p, unsigned int debug_mode) 666 { 667 int i; 668 669 p->mn_debug_mode = debug_mode; 670 671 for (i = 0; i < p->mn_fields; i++) { 672 nthw_field_t *p_field = p->mpa_fields[i]; 673 674 if (p_field) 675 nthw_field_set_debug_mode(p_field, debug_mode); 676 } 677 } 678 679 static int nthw_register_read_data(const nthw_register_t *p) 680 { 681 int rc = -1; 682 683 const int n_bus_type_id = nthw_module_get_bus(p->mp_owner); 684 const uint32_t addr = p->mn_addr; 685 const uint32_t len = p->mn_len; 686 uint32_t *const p_data = p->mp_shadow; 687 const bool trc = (p->mn_debug_mode & NTHW_REG_TRACE_ON_READ); 688 689 struct fpga_info_s *p_fpga_info = NULL; 690 691 if (p && p->mp_owner && p->mp_owner->mp_owner) 692 p_fpga_info = p->mp_owner->mp_owner->p_fpga_info; 693 694 assert(p_fpga_info); 695 assert(p_data); 696 697 rc = nthw_read_data(p_fpga_info, trc, n_bus_type_id, addr, len, p_data); 698 return rc; 699 } 700 701 static int nthw_register_write_data(const nthw_register_t *p, uint32_t cnt) 702 { 703 int rc = -1; 704 705 const int n_bus_type_id = nthw_module_get_bus(p->mp_owner); 706 const uint32_t addr = p->mn_addr; 707 const uint32_t len = p->mn_len; 708 uint32_t *const p_data = p->mp_shadow; 709 const bool trc = (p->mn_debug_mode & NTHW_REG_TRACE_ON_WRITE); 710 711 struct fpga_info_s *p_fpga_info = NULL; 712 713 if (p && p->mp_owner && p->mp_owner->mp_owner) 714 p_fpga_info = p->mp_owner->mp_owner->p_fpga_info; 715 716 assert(p_fpga_info); 717 assert(p_data); 718 719 rc = nthw_write_data(p_fpga_info, trc, n_bus_type_id, addr, (len * cnt), p_data); 720 721 return rc; 722 } 723 724 void nthw_register_get_val(const nthw_register_t *p, uint32_t *p_data, uint32_t len) 725 { 726 uint32_t i; 727 728 if (len == (uint32_t)-1 || len > p->mn_len) 729 len = p->mn_len; 730 731 assert(len <= p->mn_len); 732 assert(p_data); 733 734 for (i = 0; i < len; i++) 735 p_data[i] = p->mp_shadow[i]; 736 } 737 738 uint32_t nthw_register_get_val32(const nthw_register_t *p) 739 { 740 uint32_t val = 0; 741 742 nthw_register_get_val(p, &val, 1); 743 return val; 744 } 745 746 void nthw_register_update(const nthw_register_t *p) 747 { 748 if (p && p->mn_type != NTHW_FPGA_REG_TYPE_WO) { 749 const char *const p_dev_name = "NA"; 750 (void)p_dev_name; 751 const int n_bus_type_id = nthw_module_get_bus(p->mp_owner); 752 const char *const p_bus_name = get_bus_name(n_bus_type_id); 753 (void)p_bus_name; 754 const uint32_t addr = p->mn_addr; 755 (void)addr; 756 const uint32_t len = p->mn_len; 757 uint32_t *const p_data = p->mp_shadow; 758 759 nthw_register_read_data(p); 760 761 if (p->mn_debug_mode & NTHW_REG_DEBUG_ON_READ) { 762 uint32_t i = len; 763 uint32_t *ptr = p_data; 764 (void)ptr; 765 char *tmp_string = ntlog_helper_str_alloc("Register::read"); 766 ntlog_helper_str_add(tmp_string, 767 "(Dev: %s, Bus: %s, Addr: 0x%08X, Cnt: %d, Data:", 768 p_dev_name, p_bus_name, addr, len); 769 770 while (i--) 771 ntlog_helper_str_add(tmp_string, " 0x%08X", *ptr++); 772 773 ntlog_helper_str_add(tmp_string, ")"); 774 NT_LOG(DBG, NTHW, "%s", tmp_string); 775 ntlog_helper_str_free(tmp_string); 776 } 777 } 778 } 779 780 uint32_t nthw_register_get_val_updated32(const nthw_register_t *p) 781 { 782 uint32_t val = 0; 783 784 nthw_register_update(p); 785 nthw_register_get_val(p, &val, 1); 786 return val; 787 } 788 789 void nthw_register_make_dirty(nthw_register_t *p) 790 { 791 uint32_t i; 792 793 for (i = 0; i < p->mn_len; i++) 794 p->mp_dirty[i] = true; 795 } 796 797 void nthw_register_set_val(nthw_register_t *p, const uint32_t *p_data, uint32_t len) 798 { 799 assert(len <= p->mn_len); 800 assert(p_data); 801 802 if (len == (uint32_t)-1 || len > p->mn_len) 803 len = p->mn_len; 804 805 if (p->mp_shadow != p_data) 806 memcpy(p->mp_shadow, p_data, (len * sizeof(uint32_t))); 807 } 808 809 void nthw_register_flush(const nthw_register_t *p, uint32_t cnt) 810 { 811 int rc; 812 813 if (p->mn_type != NTHW_FPGA_REG_TYPE_RO) { 814 const char *const p_dev_name = "NA"; 815 const int n_bus_type_id = nthw_module_get_bus(p->mp_owner); 816 const char *p_bus_name = get_bus_name(n_bus_type_id); 817 const uint32_t addr = p->mn_addr; 818 const uint32_t len = p->mn_len; 819 uint32_t *const p_data = p->mp_shadow; 820 uint32_t i; 821 822 assert(len * cnt <= 256); 823 824 if (p->mn_debug_mode & NTHW_REG_DEBUG_ON_WRITE) { 825 uint32_t i = len * cnt; 826 uint32_t *ptr = p_data; 827 char *tmp_string = ntlog_helper_str_alloc("Register::write"); 828 829 ntlog_helper_str_add(tmp_string, 830 "(Dev: %s, Bus: %s, Addr: 0x%08X, Cnt: %d, Data:", 831 p_dev_name, p_bus_name, addr, i); 832 833 while (i--) 834 ntlog_helper_str_add(tmp_string, " 0x%08X", *ptr++); 835 836 ntlog_helper_str_add(tmp_string, ")"); 837 NT_LOG(DBG, NTHW, "%s", tmp_string); 838 ntlog_helper_str_free(tmp_string); 839 } 840 841 rc = nthw_register_write_data(p, cnt); 842 843 if (rc) 844 NT_LOG(ERR, NTHW, "Register write error %d\n", rc); 845 846 for (i = 0; i < cnt; i++) 847 p->mp_dirty[i] = false; 848 } 849 } 850 851 void nthw_register_clr(nthw_register_t *p) 852 { 853 memset(p->mp_shadow, 0, p->mn_len * sizeof(uint32_t)); 854 nthw_register_make_dirty(p); 855 } 856 857 /* 858 * Field 859 */ 860 nthw_field_t *nthw_field_new(void) 861 { 862 nthw_field_t *p = malloc(sizeof(nthw_field_t)); 863 864 return p; 865 } 866 867 void nthw_field_init(nthw_field_t *p, nthw_register_t *p_reg, const nthw_fpga_field_init_s *p_init) 868 { 869 p->mp_owner = p_reg; 870 871 p->mn_debug_mode = p_reg->mn_debug_mode; 872 873 p->mn_id = p_init->id; 874 p->mn_bit_width = p_init->bw; 875 p->mn_bit_pos_low = p_init->low; 876 p->mn_reset_val = (uint32_t)p_init->reset_val; 877 p->mn_first_word = p_init->low / 32; 878 p->mn_first_bit = p_init->low % 32; 879 p->mn_front_mask = 0; 880 p->mn_body_length = 0; 881 p->mn_words = (p_init->bw + 0x1f) / 0x20; 882 p->mn_tail_mask = 0; 883 884 { 885 int bits_remaining = p_init->bw; 886 int front_mask_length = 32 - p->mn_first_bit; 887 888 if (front_mask_length > bits_remaining) 889 front_mask_length = bits_remaining; 890 891 bits_remaining -= front_mask_length; 892 893 p->mn_front_mask = 894 (uint32_t)(((1ULL << front_mask_length) - 1) << p->mn_first_bit); 895 896 p->mn_body_length = bits_remaining / 32; 897 bits_remaining -= p->mn_body_length * 32; 898 p->mn_tail_mask = (1 << bits_remaining) - 1; 899 900 if (p->mn_debug_mode >= 0x100) { 901 NT_LOG_DBGX(DEBUG, NTHW, 902 "fldid=%08d: [%08d:%08d] %08d/%08d: (%08d,%08d) (0x%08X,%08d,0x%08X)\n", 903 p_init->id, p_init->low, (p_init->low + p_init->bw), 904 p_init->bw, ((p_init->bw + 31) / 32), p->mn_first_word, 905 p->mn_first_bit, p->mn_front_mask, p->mn_body_length, 906 p->mn_tail_mask); 907 } 908 } 909 } 910 911 int nthw_field_get_debug_mode(const nthw_field_t *p) 912 { 913 return p->mn_debug_mode; 914 } 915 916 void nthw_field_set_debug_mode(nthw_field_t *p, unsigned int debug_mode) 917 { 918 p->mn_debug_mode = debug_mode; 919 } 920 921 int nthw_field_get_bit_width(const nthw_field_t *p) 922 { 923 return p->mn_bit_width; 924 } 925 926 int nthw_field_get_bit_pos_low(const nthw_field_t *p) 927 { 928 return p->mn_bit_pos_low; 929 } 930 931 int nthw_field_get_bit_pos_high(const nthw_field_t *p) 932 { 933 return p->mn_bit_pos_low + p->mn_bit_width - 1; 934 } 935 936 uint32_t nthw_field_get_mask(const nthw_field_t *p) 937 { 938 return p->mn_front_mask; 939 } 940 941 void nthw_field_reset(const nthw_field_t *p) 942 { 943 nthw_field_set_val32(p, (uint32_t)p->mn_reset_val); 944 } 945 946 void nthw_field_get_val(const nthw_field_t *p, uint32_t *p_data, uint32_t len) 947 { 948 uint32_t i; 949 uint32_t data_index = 0; 950 uint32_t shadow_index = p->mn_first_word; 951 952 union { 953 uint32_t w32[2]; 954 uint64_t w64; 955 } buf; 956 957 (void)len; 958 assert(len <= p->mn_words); 959 960 /* handle front */ 961 buf.w32[0] = p->mp_owner->mp_shadow[shadow_index++] & p->mn_front_mask; 962 963 /* handle body */ 964 for (i = 0; i < p->mn_body_length; i++) { 965 buf.w32[1] = p->mp_owner->mp_shadow[shadow_index++]; 966 buf.w64 = buf.w64 >> (p->mn_first_bit); 967 assert(data_index < len); 968 p_data[data_index++] = buf.w32[0]; 969 buf.w64 = buf.w64 >> (32 - p->mn_first_bit); 970 } 971 972 /* handle tail */ 973 if (p->mn_tail_mask) 974 buf.w32[1] = p->mp_owner->mp_shadow[shadow_index++] & p->mn_tail_mask; 975 976 else 977 buf.w32[1] = 0; 978 979 buf.w64 = buf.w64 >> (p->mn_first_bit); 980 p_data[data_index++] = buf.w32[0]; 981 982 if (data_index < p->mn_words) 983 p_data[data_index++] = buf.w32[1]; 984 } 985 986 void nthw_field_set_val(const nthw_field_t *p, const uint32_t *p_data, uint32_t len) 987 { 988 uint32_t i; 989 uint32_t data_index = 0; 990 uint32_t shadow_index = p->mn_first_word; 991 992 union { 993 uint32_t w32[2]; 994 uint64_t w64; 995 } buf; 996 997 (void)len; 998 assert(len == p->mn_words); 999 1000 /* handle front */ 1001 buf.w32[0] = 0; 1002 buf.w32[1] = p_data[data_index++]; 1003 buf.w64 = buf.w64 >> (32 - p->mn_first_bit); 1004 p->mp_owner->mp_shadow[shadow_index] = 1005 (p->mp_owner->mp_shadow[shadow_index] & ~p->mn_front_mask) | 1006 (buf.w32[0] & p->mn_front_mask); 1007 shadow_index++; 1008 1009 /* handle body */ 1010 for (i = 0; i < p->mn_body_length; i++) { 1011 buf.w64 = buf.w64 >> (p->mn_first_bit); 1012 assert(data_index < len); 1013 buf.w32[1] = p_data[data_index++]; 1014 buf.w64 = buf.w64 >> (32 - p->mn_first_bit); 1015 p->mp_owner->mp_shadow[shadow_index++] = buf.w32[0]; 1016 } 1017 1018 /* handle tail */ 1019 if (p->mn_tail_mask) { 1020 buf.w64 = buf.w64 >> (p->mn_first_bit); 1021 1022 if (data_index < len) 1023 buf.w32[1] = p_data[data_index]; 1024 1025 buf.w64 = buf.w64 >> (32 - p->mn_first_bit); 1026 p->mp_owner->mp_shadow[shadow_index] = 1027 (p->mp_owner->mp_shadow[shadow_index] & ~p->mn_tail_mask) | 1028 (buf.w32[0] & p->mn_tail_mask); 1029 } 1030 1031 nthw_register_make_dirty(p->mp_owner); 1032 } 1033 1034 void nthw_field_set_val_flush(const nthw_field_t *p, const uint32_t *p_data, uint32_t len) 1035 { 1036 nthw_field_set_val(p, p_data, len); 1037 nthw_field_flush_register(p); 1038 } 1039 1040 uint32_t nthw_field_get_val32(const nthw_field_t *p) 1041 { 1042 uint32_t val; 1043 1044 nthw_field_get_val(p, &val, 1); 1045 return val; 1046 } 1047 1048 uint32_t nthw_field_get_updated(const nthw_field_t *p) 1049 { 1050 uint32_t val; 1051 1052 nthw_register_update(p->mp_owner); 1053 nthw_field_get_val(p, &val, 1); 1054 1055 return val; 1056 } 1057 1058 void nthw_field_update_register(const nthw_field_t *p) 1059 { 1060 nthw_register_update(p->mp_owner); 1061 } 1062 1063 void nthw_field_flush_register(const nthw_field_t *p) 1064 { 1065 nthw_register_flush(p->mp_owner, 1); 1066 } 1067 1068 void nthw_field_set_val32(const nthw_field_t *p, uint32_t val) 1069 { 1070 nthw_field_set_val(p, &val, 1); 1071 } 1072 1073 void nthw_field_set_val_flush32(const nthw_field_t *p, uint32_t val) 1074 { 1075 nthw_field_set_val(p, &val, 1); 1076 nthw_register_flush(p->mp_owner, 1); 1077 } 1078 1079 void nthw_field_clr_all(const nthw_field_t *p) 1080 { 1081 assert(p->mn_body_length == 0); 1082 nthw_field_set_val32(p, 0); 1083 } 1084 1085 void nthw_field_clr_flush(const nthw_field_t *p) 1086 { 1087 nthw_field_clr_all(p); 1088 nthw_register_flush(p->mp_owner, 1); 1089 } 1090 1091 void nthw_field_set_all(const nthw_field_t *p) 1092 { 1093 assert(p->mn_body_length == 0); 1094 nthw_field_set_val32(p, ~0); 1095 } 1096 1097 void nthw_field_set_flush(const nthw_field_t *p) 1098 { 1099 nthw_field_set_all(p); 1100 nthw_register_flush(p->mp_owner, 1); 1101 } 1102 1103 enum nthw_field_match { 1104 NTHW_FIELD_MATCH_CLR_ALL, 1105 NTHW_FIELD_MATCH_SET_ALL, 1106 NTHW_FIELD_MATCH_CLR_ANY, 1107 NTHW_FIELD_MATCH_SET_ANY, 1108 }; 1109 1110 static int nthw_field_wait_cond32(const nthw_field_t *p, enum nthw_field_match e_match, 1111 int n_poll_iterations, int n_poll_interval) 1112 { 1113 const uint32_t n_mask = (1 << p->mn_bit_width) - 1; 1114 1115 if (n_poll_iterations == -1) 1116 n_poll_iterations = 10000; 1117 1118 if (n_poll_interval == -1) 1119 n_poll_interval = 100; /* usec */ 1120 1121 if (p->mn_debug_mode) { 1122 const char *const p_cond_name = 1123 ((e_match == NTHW_FIELD_MATCH_SET_ALL) 1124 ? "SetAll" 1125 : ((e_match == NTHW_FIELD_MATCH_CLR_ALL) 1126 ? "ClrAll" 1127 : ((e_match == NTHW_FIELD_MATCH_CLR_ANY) ? "ClrAny" 1128 : "SetAny"))); 1129 (void)p_cond_name; 1130 const char *const p_dev_name = "NA"; 1131 (void)p_dev_name; 1132 const char *const p_bus_name = 1133 get_bus_name(nthw_module_get_bus(p->mp_owner->mp_owner)); 1134 (void)p_bus_name; 1135 uint32_t n_reg_addr = nthw_register_get_address(p->mp_owner); 1136 (void)n_reg_addr; 1137 uint32_t n_reg_mask = (((1 << p->mn_bit_width) - 1) << p->mn_bit_pos_low); 1138 (void)n_reg_mask; 1139 1140 NT_LOG(DBG, NTHW, 1141 "Register::Field::wait%s32(Dev: %s, Bus: %s, Addr: 0x%08X, Mask: 0x%08X, Iterations: %d, Interval: %d)\n", 1142 p_cond_name, p_dev_name, p_bus_name, n_reg_addr, n_reg_mask, 1143 n_poll_iterations, n_poll_interval); 1144 } 1145 1146 while (true) { 1147 uint32_t val = nthw_field_get_updated(p); 1148 1149 if (e_match == NTHW_FIELD_MATCH_SET_ANY && val != 0) { 1150 return 0; 1151 1152 } else if (e_match == NTHW_FIELD_MATCH_SET_ALL && val == n_mask) { 1153 return 0; 1154 1155 } else if (e_match == NTHW_FIELD_MATCH_CLR_ALL && val == 0) { 1156 return 0; 1157 1158 } else if (e_match == NTHW_FIELD_MATCH_CLR_ANY) { 1159 uint32_t mask = nthw_field_get_mask(p); 1160 1161 if (val != mask) 1162 return 0; 1163 } 1164 1165 n_poll_iterations--; 1166 1167 if (n_poll_iterations <= 0) 1168 return -1; 1169 1170 nt_os_wait_usec(n_poll_interval); 1171 } 1172 1173 return 0; 1174 } 1175 1176 int nthw_field_wait_set_all32(const nthw_field_t *p, int n_poll_iterations, int n_poll_interval) 1177 { 1178 return nthw_field_wait_cond32(p, NTHW_FIELD_MATCH_SET_ALL, n_poll_iterations, 1179 n_poll_interval); 1180 } 1181 1182 int nthw_field_wait_clr_all32(const nthw_field_t *p, int n_poll_iterations, int n_poll_interval) 1183 { 1184 return nthw_field_wait_cond32(p, NTHW_FIELD_MATCH_CLR_ALL, n_poll_iterations, 1185 n_poll_interval); 1186 } 1187 1188 int nthw_field_wait_set_any32(const nthw_field_t *p, int n_poll_iterations, int n_poll_interval) 1189 { 1190 return nthw_field_wait_cond32(p, NTHW_FIELD_MATCH_SET_ANY, n_poll_iterations, 1191 n_poll_interval); 1192 } 1193