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