verinet.c (30206B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * Routines for accessing the network and sending RPC commands to/from 8 * the PLI test-server. 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <unistd.h> 14 #include <stdarg.h> 15 #include <assert.h> 16 #include <sys/socket.h> 17 #include <sys/time.h> 18 #include <stdlib.h> 19 #include <netinet/in.h> 20 #ifndef VXWORKS 21 #include <string.h> 22 #include <netdb.h> 23 #endif 24 #include <arpa/inet.h> 25 #include <errno.h> 26 #include <ctype.h> 27 28 #ifdef VXWORKS 29 #include <vxWorks.h> 30 #include <sockLib.h> 31 #endif 32 33 #include <sal/core/sync.h> 34 #include <sal/appl/io.h> 35 #include <soc/debug.h> 36 37 #include "verinet.h" 38 39 #include <sim/pcid/pcid.h> 40 #define _BCM_RPC_ERROR_COUNT_MAX (10) 41 /* 42 * One verinet structure per devNo (unit) 43 */ 44 verinet_t verinet[N_VERINET_DEVICES]; 45 46 /* 47 * Write "n" bytes to a descriptor. 48 */ 49 int writen(int fd, void *ptr, int nbytes) 50 { 51 int nleft, nwritten; 52 nleft = nbytes; 53 while (nleft > 0){ 54 nwritten = write(fd, ptr, nleft); 55 if (nwritten <= 0) 56 return(nwritten); 57 nleft -= nwritten; 58 ptr = (char *)ptr + nwritten; 59 } 60 return(nbytes - nleft); 61 } 62 63 64 /* 65 * Read "n" bytes from a descriptor. 66 */ 67 int readn(int fd, void* ptr, int nbytes) 68 { 69 int nleft, nread; 70 nleft = nbytes; 71 while (nleft > 0) { 72 nread = read(fd, ptr, nleft); 73 if (nread < 0) 74 return(nread); /* error, return < 0 */ 75 else if (nread == 0) 76 break; /* EOF */ 77 nleft -= nread; 78 ptr = (char *)ptr + nread; 79 } 80 return(nbytes - nleft); /* return >= 0 */ 81 } 82 83 /* 84 * Get the port number to which a socket is bound. 85 */ 86 87 int getsockport(int sock_fd) 88 { 89 struct sockaddr_in name; 90 socklen_t name_len; 91 92 name_len = sizeof (name); 93 94 if (getsockname(sock_fd, (struct sockaddr *)&name, &name_len) < 0) { 95 perror("getsockname"); 96 return 0; 97 } 98 99 return ntohs(name.sin_port); 100 } 101 102 /* 103 * reads an RPC command. 104 * Parameters: 105 * sockfd -socket file descriptor. 106 * Returns: 107 * -1 on error (nothing returned in rpc_cmd_t *) 108 * 0 if no command is found (nothing returned in rpc_cmd_t *) 109 * 1 if command is found (returned in rpc_cmd_t *) 110 */ 111 112 int get_command(int sockfd, struct timeval* tv, rpc_cmd_t* command) 113 { 114 int i; 115 fd_set read_vect; 116 uint32 swap; 117 118 LOG_VERBOSE(BSL_LS_SYS_VERINET, 119 (BSL_META("get_command: sockfd=%d\n"), 120 sockfd)); 121 122 assert(sockfd > 2); /* Verinet initialized? */ 123 124 /* Setup bitmap for read notification ... */ 125 FD_ZERO(&read_vect); 126 FD_SET(sockfd, &read_vect); 127 128 while (1) { 129 if(select(sockfd+1,&read_vect,(fd_set*)0x0,(fd_set*)0x0,tv)<0){ 130 if (errno == EINTR) { 131 /* 132 * Interrupted by a signal such as a GPROF alarm so 133 * restart the call 134 */ 135 continue; 136 } 137 perror("get_command: select error"); 138 goto fail; 139 } else { 140 break; 141 } 142 } 143 /* 144 * Data ready to be read. 145 */ 146 if( FD_ISSET(sockfd, &read_vect)){ 147 148 /* 149 * Read RPC opcode, argcount, status 150 */ 151 #define SOCKET_GET_U32(sockfd, swap, where, what) \ 152 do { \ 153 if(readn(sockfd, &(swap), sizeof(uint32)) < sizeof(uint32)) { \ 154 cli_out("get_command: could not read RPC %s\n", what); \ 155 goto fail; \ 156 } \ 157 (where) = ntohl(swap); /* Convert to host order */ \ 158 } while (0) 159 160 SOCKET_GET_U32(sockfd, swap, command->opcode, "opcode"); 161 SOCKET_GET_U32(sockfd, swap, command->argcount, "arg count"); 162 163 if (RPC_OP_USE_STRING(command->opcode)) { 164 if (command->argcount > (sizeof(uint32) * MAX_RPC_ARGS)) { 165 cli_out("RPC string too long (get): %d\n", command->argcount); 166 goto fail; 167 } 168 SOCKET_GET_U32(sockfd, swap, command->args[0], "pkt address"); 169 /* coverity[tainted_data] */ 170 if (readn(sockfd, &command->args[1], command->argcount) < 171 command->argcount) { 172 cli_out("get_command: could not read all of string. %d.\n", 173 command->argcount); 174 goto fail; 175 } 176 } else { 177 if (command->argcount > MAX_RPC_ARGS) { 178 cli_out("get_command: bogus argcount (%d) from rpc socket\n", 179 command->argcount); 180 goto fail; 181 } 182 /* Read each argument into command struct ... */ 183 for(i = 0; i < command->argcount; i++){ 184 SOCKET_GET_U32(sockfd, swap, command->args[i], "argument"); 185 } 186 } 187 188 SOCKET_GET_U32(sockfd, swap, command->status, "status"); 189 190 #undef SOCKET_GET_U32 191 192 LOG_INFO(BSL_LS_SYS_VERINET, 193 (BSL_META("get_command: opcode=0x%x nargs=%d status=%d\n"), 194 command->opcode, command->argcount, command->status)); 195 196 return 1; 197 } 198 199 return 0; /* Time expire with no command */ 200 201 fail: 202 return -1; 203 } 204 205 206 /* 207 * Non-blocking version of actual call made by PLI interface. 208 * Note that the timeout is 0 which guarantees that the Verilog 209 * model does not block. 210 * 211 * Returns: 212 * -1 on error (nothing returned in rpc_cmd_t *) 213 * 0 if no command is found (nothing returned in rpc_cmd_t *) 214 * 1 if command is found (returned in rpc_cmd_t *) 215 */ 216 int poll_command(int sockfd, rpc_cmd_t* command) 217 { 218 struct timeval tv = {0,0}; 219 return get_command(sockfd,(struct timeval*)&tv,command); 220 } 221 222 /* 223 * Blocking version of actual call made by PLI interface. 224 * 225 * Returns: 226 * -1 on error (nothing returned in rpc_cmd_t *) 227 * 0 on success 228 */ 229 int wait_command(int sockfd, rpc_cmd_t* command) 230 { 231 return get_command(sockfd,(struct timeval*)0,command); 232 } 233 234 235 /* 236 * Writes an RPC command to the server. 237 * Parameters: 238 * 1) sockfd-socket file descriptor. 239 * 2) command -rpc_cmd_t filled in for the necessary command. 240 * 241 * Return values: 242 * RPC_OK on success 243 * RPC_FAIL on error 244 */ 245 int write_command(int sockfd, rpc_cmd_t* command) 246 { 247 int i; 248 uint8 write_buf[sizeof(uint32) * (MAX_RPC_ARGS + 4)]; 249 int write_cnt; 250 uint32 swap; 251 static int error_count = 0; 252 253 LOG_INFO(BSL_LS_SYS_VERINET, 254 (BSL_META("write_command: sockfd=%d opcode=0x%x nargs=%d status=%d\n"), 255 sockfd, command->opcode, command->argcount, command->status)); 256 257 assert(sockfd > 2); /* Verinet initialized? */ 258 259 /* 260 * Each value is converted to network byte order before writing. 261 * On some hosts (e.g. SPARC,MIPS, COLDFire which run in big-endian 262 * mode, these calls are NOPS, but we include them here for 263 * correctness and porting to other platforms). 264 * 265 * Data is saved in a buffer and written using one write to make 266 * performance over the network about a ZILLION times faster. 267 */ 268 269 write_cnt = 0; 270 271 /* RPC opcode */ 272 #define STORE_U32(val, buf, swap, idx) \ 273 do { \ 274 swap = htonl(val); \ 275 sal_memcpy(&(buf[idx]), &(swap), sizeof(uint32)); \ 276 idx += sizeof(uint32); \ 277 } while(0) 278 279 /* Store opcode and argcount */ 280 STORE_U32(command->opcode, write_buf, swap, write_cnt); 281 STORE_U32(command->argcount, write_buf, swap, write_cnt); 282 283 /* Each argument from command struct, unless as string */ 284 285 if (RPC_OP_USE_STRING(command->opcode)) { 286 /* Arg 0 is address */ 287 STORE_U32(command->args[0], write_buf, swap, write_cnt); 288 /* Here, arg count is a number of bytes */ 289 if ((command->argcount + write_cnt) > (sizeof(uint32) * MAX_RPC_ARGS)) { 290 cli_out("RPC string too long (send0: %d\n", command->argcount); 291 goto fail; 292 } 293 sal_memcpy(&write_buf[write_cnt], (uint8 *) &command->args[1], 294 command->argcount); 295 write_cnt += command->argcount; 296 } else { 297 if (command->argcount > MAX_RPC_ARGS) { 298 cli_out("RPC: too many arguments. %d\n", command->argcount); 299 goto fail; 300 } 301 for(i = 0; i < command->argcount; i++) { 302 STORE_U32(command->args[i], write_buf, swap, write_cnt); 303 } 304 } 305 306 /* Store status */ 307 STORE_U32(command->status, write_buf, swap, write_cnt); 308 309 #undef STORE_U32 310 311 /* Perform write */ 312 if (writen(sockfd, write_buf, write_cnt) < 0) { 313 cli_out("write_command: could not write RPC request.\n"); 314 goto fail; 315 } 316 317 goto done; 318 319 /* Failure */ 320 fail: 321 error_count ++; 322 if (error_count > _BCM_RPC_ERROR_COUNT_MAX) { 323 cli_out("write_command: Too many write failures.\n"); 324 assert (0); 325 } 326 return RPC_FAIL; 327 328 /* Success */ 329 done: 330 return RPC_OK; 331 } 332 333 /* 334 * Creates an RPC command. 335 * Generic routine used by all RPC command stubs below. 336 * NOTE: this should be used the same way by all stubs since the 337 * ordering of arguments is significant. 338 */ 339 340 void make_rpc(rpc_cmd_t* command, 341 uint32 opcode, 342 uint32 status, 343 uint32 argcount, 344 ...) 345 { 346 int i; 347 va_list ap; 348 command->opcode = opcode; 349 command->argcount = argcount; 350 command->status = status; 351 va_start(ap, argcount); 352 for( i = 0; i < argcount; i++) 353 command->args[i] = va_arg(ap, uint32); 354 va_end(ap); 355 } 356 357 358 /* 359 * Creates an RPC command with data as a string. 360 */ 361 362 void make_rpc_string(rpc_cmd_t* command, 363 uint32 opcode, 364 uint32 status, 365 uint32 addr, 366 uint8 *data, 367 uint32 len) 368 { 369 command->opcode = opcode; 370 command->argcount = len; 371 command->status = status; 372 command->args[0] = addr; 373 if (data) { 374 sal_memcpy((uint8 *)&command->args[1], data, len); 375 } 376 } 377 378 /* 379 * Makes an RPC structure to be sent to the server for the client (request); 380 * This is for the setmem(addr,data) call. 381 */ 382 void make_rpc_setmem_req(rpc_cmd_t* cmd, uint32 addr, uint32 data) 383 { 384 make_rpc(cmd, 385 RPC_DMAC_WRITE_REQ, 386 RPC_OUTSTANDING, 387 2, 388 addr, 389 data); 390 } 391 /* 392 * Makes an RPC structure to be sent back to the client in response. 393 * This is for the response to the client for setmem(addr,data). 394 * Here we send the updated value of the data @ addr. 395 */ 396 void make_rpc_setmem_resp(rpc_cmd_t* cmd, uint32 data) 397 { 398 make_rpc(cmd, 399 RPC_DMAC_WRITE_RESP, 400 RPC_OK, 401 1, 402 data); 403 } 404 405 406 /* 407 * Makes an RPC structure to be sent to the server for the client (request); 408 * this is for the getmem(addr) call. 409 */ 410 void make_rpc_getmem_req(rpc_cmd_t* cmd, uint32 addr) 411 { 412 make_rpc(cmd, 413 RPC_DMAC_READ_REQ, 414 RPC_OUTSTANDING, 415 1, 416 addr); 417 } 418 419 /* 420 * Makes an RPC response to send back to the client. This is for 421 * a response to getmem(addr). 422 */ 423 void make_rpc_getmem_resp(rpc_cmd_t* cmd, uint32 data) 424 { 425 make_rpc(cmd, 426 RPC_DMAC_READ_RESP, 427 RPC_OK, 428 1, 429 data); 430 } 431 432 433 434 /* 435 * Makes an RPC structure to be sent to the server for the client (request); 436 * This is for the pli_setreg() call. 437 */ 438 void make_rpc_setreg_req(rpc_cmd_t* cmd, 439 uint32 regtype, uint32 regnum, uint32 regval) 440 { 441 make_rpc(cmd, 442 RPC_SETREG_REQ, 443 RPC_OUTSTANDING, 444 3, 445 regnum, 446 regval, 447 regtype); 448 } 449 450 /* 451 * Makes an RPC structure to be sent to the client from the server 452 * (response); this is for the response to the pli_setreg() call. 453 */ 454 455 void make_rpc_setreg_resp(rpc_cmd_t* cmd, 456 uint32 regval) 457 { 458 make_rpc(cmd, 459 RPC_SETREG_RESP, 460 RPC_OK, 461 1, 462 regval); 463 } 464 465 466 /* 467 * Makes an RPC structure to be sent to the server for the client (request); 468 */ 469 void make_rpc_ioctl_req(rpc_cmd_t* cmd, uint32 op, uint32 p1, uint32 p2) 470 { 471 } 472 473 474 /* 475 * Makes an RPC structure to be sent to the server for the client (request); 476 * this is for the pli_getreg() call. 477 */ 478 void make_rpc_getreg_req(rpc_cmd_t* cmd, 479 uint32 regtype, uint32 regnum) 480 { 481 make_rpc(cmd, 482 RPC_GETREG_REQ, 483 RPC_OUTSTANDING, 484 2, 485 regnum, 486 regtype); 487 } 488 489 490 /* 491 * Makes an RPC structure to be sent to the client from the server 492 * (response); this is for the response to the pli_getreg() call. 493 * NOTE: buf must be 32 byte in size. 494 */ 495 void make_rpc_getreg_resp(rpc_cmd_t* cmd, 496 uint32 status, 497 uint32 regval, 498 char* buf32byte) 499 { 500 uint32 w[8]; 501 502 /* Kludge: shove a 32 byte buffer into some integers.*/ 503 504 memcpy((char *) w, buf32byte, 32); /* Get aligned on word boundary */ 505 506 make_rpc(cmd, 507 RPC_GETREG_RESP, 508 RPC_OK, 509 10, 510 status, 511 regval, 512 w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]); 513 } 514 515 516 517 /* 518 * Makes an RPC structure to be sent to the server for the client (request); 519 * this is for the pli_interrupt() call. 520 */ 521 void make_rpc_intr_req(rpc_cmd_t* cmd, 522 uint32 cause) 523 { 524 make_rpc(cmd, 525 RPC_SEND_INTR, 526 RPC_OUTSTANDING, 527 1, 528 cause); 529 } 530 531 /* 532 * Makes an RPC structure to be sent to the server for the client (request); 533 * this is for the response to the pli_interrupt() call. 534 */ 535 void make_rpc_intr_resp(rpc_cmd_t* cmd, 536 uint32 cause) 537 { 538 make_rpc(cmd, 539 RPC_SEND_INTR, 540 RPC_OK, 541 1, 542 cause); 543 } 544 545 546 /* 547 * Makes an RPC disconnect request structure. 548 */ 549 void make_rpc_disconnect_req(rpc_cmd_t* cmd) 550 { 551 make_rpc(cmd, 552 RPC_DISCONNECT, 553 RPC_OUTSTANDING, 554 0,0,0); 555 } 556 557 /* 558 * Makes an RPC registration request. This call will register the 559 * client to receive interrupts on one port, and dma requests (r/w) 560 * on another. 561 */ 562 563 void make_rpc_register_req(rpc_cmd_t* cmd, 564 int intPort, 565 int dmacPort, 566 uint32 netAddr) 567 { 568 make_rpc(cmd, 569 RPC_REGISTER_CLIENT, 570 RPC_OUTSTANDING, 571 3, 572 intPort, 573 dmacPort, 574 netAddr); 575 } 576 577 /* 578 * RPC registration response: send RPC_OK on success. 579 */ 580 void make_rpc_register_resp(rpc_cmd_t* cmd, 581 uint32 status) 582 { 583 make_rpc(cmd, 584 RPC_REGISTER_CLIENT, 585 RPC_OK, 586 1, 587 status); 588 } 589 590 591 int pli_client_count(void) 592 { 593 char *s; 594 595 /* Returns number of PLI clients expected to be running. */ 596 /* This should be set in the environment variable SOC_TARGET_COUNT. */ 597 598 s = getenv("SOC_TARGET_COUNT"); 599 600 return (s == NULL) ? 1 : atoi(s); 601 } 602 603 /* 604 * Generic network routines for client and server. 605 */ 606 607 /* 608 * Connect a client to the server. 609 * This performs the following PLI client-side initialization. 610 * 611 * 1) Initialize a lock for PLI setreg/getreg accesses 612 * 2) Input connection host/port information from user. 613 * 3) Setup DMA controller task to listen (locally) on dmaPort. 614 * 4) Setup Interrupt Controller task to listen (locally) on intPort. 615 * 5) Register an interrupt callback routine (passed in). 616 * 6) Setup a local socket file descriptor to communicate with 617 * pliHost on the given pliPort. 618 * 7) Register the client with the server on pliHost. 619 * The server may immediately start sending DMA and INTR requests. 620 * Return: 621 * 0 on success, a negative value on error. 622 */ 623 int pli_client_attach(int devNo) 624 { 625 verinet_t *v = &verinet[devNo]; 626 struct sockaddr_in cli_addr; 627 socklen_t cli_addr_size; 628 struct sockaddr_in srv_addr; 629 #ifndef VXWORKS 630 struct hostent *hostentPtr = NULL; 631 #endif 632 rpc_cmd_t cmd; 633 char tmp[80], *s; 634 int rv = -1; 635 636 memset(v, 0, sizeof (*v)); 637 638 v->devNo = devNo; 639 640 v->sockfd = -1; 641 v->skipTestInt = 1; 642 643 v->pli_mutex = sal_mutex_create("PLI socket mutex"); 644 645 /* Setup target host */ 646 s = getenv("SOC_TARGET_SERVER"); 647 if (!s) { 648 snprintf(tmp, sizeof(tmp), "SOC_TARGET_SERVER%d", devNo); 649 s = getenv(tmp); 650 } 651 if(!s) { 652 snprintf(tmp, sizeof(tmp), 653 "Enter unit %d PLI server host" 654 #ifdef VXWORKS 655 " address" 656 #else 657 "name [localhost]" 658 #endif 659 ": ", 660 devNo); 661 sal_readline(tmp, v->pliHost, sizeof (v->pliHost), 0); 662 if (sal_strlen(v->pliHost) == 0) { 663 sal_strncpy(v->pliHost, "localhost", sizeof(v->pliHost) - 1); 664 } 665 } else { 666 if(strlen(s) >= sizeof(v->pliHost)) 667 strncpy(v->pliHost, s, sizeof(v->pliHost) - 1); 668 else 669 strncpy(v->pliHost, s, strlen(s)); 670 } 671 /* Setup target port */ 672 s = getenv("SOC_TARGET_PORT"); 673 if (!s) { 674 snprintf(tmp, sizeof(tmp), "SOC_TARGET_PORT%d", devNo); 675 s = getenv(tmp); 676 } 677 if(!s){ 678 snprintf(tmp, sizeof(tmp), "Enter unit %d remote port: ", devNo); 679 sal_readline(tmp, tmp, sizeof (tmp), "2400"); 680 v->pliPort = atoi(tmp); 681 } 682 else 683 v->pliPort = atoi(s); 684 685 /* 686 * Connect to host running Vera (ncsim) 687 */ 688 memset((void *)&srv_addr, 0, sizeof(srv_addr)); 689 690 #ifdef VXWORKS 691 if (!isdigit((unsigned) v->pliHost[0])) { 692 cli_out("pli_client_attach: can't resolve host names in vxworks\n"); 693 } 694 695 srv_addr.sin_addr.s_addr = inet_addr(v->pliHost); 696 #else 697 hostentPtr = gethostbyname(v->pliHost); 698 if(hostentPtr == NULL) { 699 cli_out("pli_client_attach: hostname lookup failed " 700 "for host [%s].\n", v->pliHost); 701 perror("gethostbyname"); 702 goto error; 703 } 704 memcpy(&srv_addr.sin_addr,hostentPtr->h_addr,4); 705 #endif 706 707 srv_addr.sin_family = AF_INET; 708 srv_addr.sin_port = htons(v->pliPort); 709 710 if ((v->sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 711 perror("server: can't open stream socket"); 712 goto error; 713 } 714 715 #ifdef VERINET_CUSTOM_SOCKET_HOOK 716 VERINET_CUSTOM_SOCKET_HOOK 717 #endif 718 719 if (connect(v->sockfd, 720 (struct sockaddr*)&srv_addr, sizeof(srv_addr)) < 0) { 721 cli_out("pli_client_attach: could not connect unit %d to [%s.%d] " 722 "-service unavailable.\n", 723 devNo, v->pliHost, v->pliPort); 724 perror("connect"); 725 goto error; 726 } 727 728 /* 729 * Get local host name to send back to server 730 */ 731 732 cli_addr_size = sizeof (cli_addr); 733 if (getsockname(v->sockfd, (struct sockaddr *)&cli_addr, &cli_addr_size) < 0) { 734 perror("pli_client_attach: getsockname function failed."); 735 goto error; 736 } 737 cli_addr.sin_addr.s_addr = htonl(cli_addr.sin_addr.s_addr); 738 739 /* 740 * Start INTC and DMAC tasks and register callback for ISR. 741 */ 742 743 if (!v->jobsStarted) { 744 if (dmac_init(v) < 0) { 745 goto error; 746 } 747 748 if (intr_init(v) < 0) { 749 goto error; 750 } 751 752 v->jobsStarted = 1; 753 } 754 755 /* 756 * Send REGISTER request to PLI server. 757 */ 758 make_rpc_register_req(&cmd, 759 v->intPort, v->dmaPort, 760 cli_addr.sin_addr.s_addr); 761 762 if (write_command(v->sockfd, &cmd) != RPC_OK) { 763 cli_out("pli_client_attach: could not send REGISTER request\n"); 764 goto error; 765 } 766 767 if (wait_command(v->sockfd, &cmd) < 0) 768 goto error; 769 770 if (cmd.opcode != RPC_REGISTER_CLIENT || 771 cmd.status != RPC_OK) { 772 cli_out("pli_client_attach: PLI registration failed\n"); 773 goto error; 774 } 775 776 return 0; 777 778 error: 779 if (v->sockfd >= 0) { 780 close(v->sockfd); 781 v->sockfd = -1; 782 } 783 784 return rv; 785 } 786 787 int pli_register_isr(int devNo, pli_isr_t isr, void *isr_data) 788 { 789 intr_set_vector(&verinet[devNo], isr, isr_data); 790 return 0; 791 } 792 793 int pli_client_detach(int devNo) 794 { 795 verinet_t *v = &verinet[devNo]; 796 797 if (v->sockfd >= 0) { 798 disconnect(v->sockfd); 799 close(v->sockfd); 800 v->sockfd = -1; 801 } 802 803 return 0; 804 } 805 806 /* 807 * Disconnect a client from the server. 808 */ 809 void disconnect(int sockfd) 810 { 811 rpc_cmd_t command; 812 make_rpc_disconnect_req(&command); 813 cli_out("Disconnect: 0x%x\n", sockfd); 814 write_command(sockfd, &command); 815 } 816 817 818 /* 819 * Send an interrupt to a client. "cause" indicates the reason. 820 */ 821 uint32 send_interrupt(int sockfd, uint32 cause) 822 { 823 rpc_cmd_t command; 824 make_rpc_intr_req(&command,cause); 825 if (write_command(sockfd, &command) != RPC_OK) { 826 return -1; 827 } 828 if (wait_command(sockfd, &command) < 0) 829 return -1; 830 return command.args[0]; 831 } 832 833 834 835 836 /* 837 * Register a client with the server. This will add the client to 838 * the servers queue of service requests. We pass the network address 839 * and two ports which are used for DMA r/w requests and interrupt 840 * requests. 841 */ 842 netconnection_t* register_client(int sockfd, 843 uint32 intPort, 844 uint32 dmaPort, 845 uint32 netAddr) 846 { 847 int dmaSockFD = -1; /* DMA socket file descriptor */ 848 int intSockFD = -1; /* Interrupt file descriptor */ 849 netconnection_t *nc; 850 struct sockaddr_in cli_addr; /* Client net address */ 851 852 memset(&cli_addr , 0 , sizeof(struct sockaddr_in)); 853 854 if((nc = (netconnection_t*)malloc(sizeof(netconnection_t))) == NULL) 855 return (netconnection_t*)0x0; 856 857 nc->intsock = -1; 858 nc->dmasock = -1; 859 nc->piosock = -1; 860 861 #if 0 862 cli_out("register_client:s=%d irqPort=%d dmaPort=%d netAddr=%d.%d.%d.%d\n", 863 sockfd, intPort, dmaPort, 864 (netAddr & 0xff000000) >> 24, 865 (netAddr & 0x00ff0000) >> 16, 866 (netAddr & 0x0000ff00) >> 8, 867 (netAddr & 0x000000ff)); 868 #endif 869 870 /* Keep local copy of netaddress in native byte order */ 871 memcpy(&nc->inetaddr,&netAddr,4); 872 /* Setup netaddr for client */ 873 netAddr = htonl(netAddr); 874 memcpy(&cli_addr.sin_addr,&netAddr,4); 875 876 cli_addr.sin_family = AF_INET; 877 cli_addr.sin_port = htons(intPort); 878 879 /* Setup interrupt socket */ 880 if((intSockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0){ 881 perror("server: can't open stream socket"); 882 free(nc); 883 return (netconnection_t*)0x0; 884 } 885 /* Connect back to client */ 886 if(connect(intSockFD, (struct sockaddr*)&cli_addr, sizeof(cli_addr))< 0){ 887 cli_out("Error: INTC connect failed to [0x%x.%d] -service unavailable.\n", 888 netAddr, intPort); 889 perror("connect"); 890 close(intSockFD); 891 free(nc); 892 return (netconnection_t*)0x0; 893 } 894 895 /* Setup DMA socket */ 896 cli_addr.sin_port = htons(dmaPort); 897 898 if((dmaSockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0){ 899 perror("server: can't open stream socket"); 900 close(intSockFD); 901 free(nc); 902 return (netconnection_t*)0x0; 903 } 904 905 /* Connect back to client */ 906 if(connect(dmaSockFD, (struct sockaddr*)&cli_addr, sizeof(cli_addr))< 0){ 907 cli_out("Error: DMAC connect failed to [0x%x.%d] -service unavailable.\n", 908 netAddr, dmaPort); 909 perror("connect"); 910 close(intSockFD); 911 close(dmaSockFD); 912 free(nc); 913 return (netconnection_t*)0x0; 914 } 915 916 /* Fill in fields */ 917 nc->intsock = intSockFD ; 918 nc->dmasock = dmaSockFD ; 919 nc->piosock = sockfd; 920 921 return nc; 922 } 923 924 int unregister_client(netconnection_t *nc) 925 { 926 close(nc->intsock); 927 close(nc->dmasock); 928 close(nc->piosock); 929 free(nc); 930 return 0; 931 } 932 933 /* 934 * Server PLI-level call to write to DMA memory. 935 * Load the given memory address with some data on the client. 936 */ 937 int dma_writemem(int sockfd, uint32 addr, uint32 data) 938 { 939 rpc_cmd_t cmd; 940 make_rpc_setmem_req(&cmd,addr,data); 941 if (write_command(sockfd, &cmd) != RPC_OK) { 942 return RPC_FAIL; 943 } 944 if (wait_command(sockfd,&cmd) < 0) { 945 return RPC_FAIL; 946 } 947 return RPC_OK; 948 } 949 950 951 /* 952 * Server PLI-level client call to read DMA memory. 953 * Returns the data at a given memory address on client. 954 */ 955 int dma_readmem(int sockfd, uint32 addr, uint32 *value) 956 { 957 rpc_cmd_t cmd; 958 make_rpc_getmem_req(&cmd,addr); 959 if (write_command(sockfd, &cmd) != RPC_OK) { 960 return RPC_FAIL; 961 } 962 if (wait_command(sockfd,&cmd) < 0) { 963 return RPC_FAIL; 964 } 965 *value = cmd.args[0]; 966 return RPC_OK; 967 } 968 969 /* 970 * Server PLI-level call to write to DMA memory as a string. 971 */ 972 int dma_write_bytes(int sockfd, uint32 addr, uint8 *data, int len) 973 { 974 rpc_cmd_t cmd; 975 976 make_rpc_string(&cmd, RPC_DMAC_WRITE_BYTES_REQ, RPC_OUTSTANDING, 977 addr, data, len); 978 if (write_command(sockfd, &cmd) != RPC_OK) { 979 return -1; 980 } 981 if (wait_command(sockfd, &cmd) < 0) { 982 return -1; 983 } 984 985 return cmd.argcount; 986 } 987 988 989 /* 990 * Server PLI-level client call to read DMA memory as a string. 991 * Data is copied up to the max number of bytes to *data. 992 */ 993 int dma_read_bytes(int sockfd, uint32 addr, uint8 *data, int len) 994 { 995 rpc_cmd_t cmd; 996 997 make_rpc_string(&cmd, RPC_DMAC_READ_BYTES_REQ, RPC_OUTSTANDING, 998 addr, NULL, len); 999 if (write_command(sockfd, &cmd) != RPC_OK) { 1000 return -1; 1001 } 1002 if (wait_command(sockfd, &cmd) < 0) { 1003 return -1; 1004 } 1005 /* coverity[tainted_data] */ 1006 memcpy(data, &cmd.args[1], cmd.argcount); 1007 1008 return cmd.argcount; 1009 } 1010 1011 1012 /* 1013 * Client Call: get a register on the simulator. 1014 */ 1015 uint32 pli_getreg(int devNo, uint32 regtype, uint32 regnum) 1016 { 1017 int i ; 1018 verinet_t *v = &verinet[devNo]; 1019 uint32 status = 0x0; 1020 uint32 regval = 0x0; 1021 char buf[32], *ptr; 1022 rpc_cmd_t command; 1023 1024 LOG_INFO(BSL_LS_SYS_VERINET, 1025 (BSL_META("pli_getreg: regtype=0x%x regnum=0x%x\n"), 1026 regtype, regnum)); 1027 1028 make_rpc_getreg_req(&command, regtype,regnum); 1029 1030 sal_mutex_take(v->pli_mutex, sal_mutex_FOREVER); 1031 1032 if(write_command(v->sockfd, &command) != RPC_OK) { 1033 cli_out("Error: pli_getreg write_command failed\n"); 1034 sal_mutex_give(v->pli_mutex); 1035 return -1; 1036 } 1037 1038 if (wait_command(v->sockfd, &command) < 0) { 1039 sal_mutex_give(v->pli_mutex); 1040 return -1; 1041 } 1042 1043 sal_mutex_give(v->pli_mutex); 1044 1045 status = command.args[0]; 1046 regval = command.args[1]; 1047 ptr = (char*)&command.args[2]; 1048 for(i = 0; i < 32; i++){ 1049 buf[i] = *ptr++; 1050 } 1051 1052 LOG_INFO(BSL_LS_SYS_VERINET, 1053 (BSL_META("pli_getreg: regval=0x%x diagbuf=%s\n"), 1054 regval, buf)); 1055 1056 if(status == 0) /* Read succeeded */ 1057 return regval; 1058 else 1059 return -1; /* RPC failed */ 1060 } 1061 1062 /* 1063 * Client call: set a register on the simulator. 1064 */ 1065 uint32 pli_setreg(int devNo, uint32 regtype, uint32 regnum, uint32 regval) 1066 { 1067 rpc_cmd_t command; 1068 verinet_t *v = &verinet[devNo]; 1069 1070 make_rpc_setreg_req(&command,regtype,regnum,regval); 1071 1072 LOG_INFO(BSL_LS_SYS_VERINET, 1073 (BSL_META("pli_setreg: regtype=0x%x regnum=0x%x regval=0x%x\n"), 1074 regtype, regnum, regval)); 1075 1076 sal_mutex_take(v->pli_mutex, sal_mutex_FOREVER); 1077 1078 if(write_command(v->sockfd, &command) != RPC_OK) { 1079 cli_out("Error: pli_setreg write_command failed\n"); 1080 sal_mutex_give(v->pli_mutex); 1081 return -1; 1082 } 1083 1084 if (wait_command(v->sockfd,&command) < 0) { 1085 sal_mutex_give(v->pli_mutex); 1086 return -1; 1087 } 1088 1089 sal_mutex_give(v->pli_mutex); 1090 1091 return command.args[0]; 1092 } 1093 1094 /* 1095 * Client call: send packet to be transmitted into the switch 1096 */ 1097 uint32 pli_send_packet(int devNo, uint32 src_port, uint32 count, 1098 int len, unsigned char *buf) 1099 { 1100 verinet_t *v = &verinet[devNo]; 1101 rpc_cmd_t command; 1102 1103 make_rpc(&command,RPC_SEND_PACKET,RPC_OK,3,src_port,count,len); 1104 1105 if(write_command(v->sockfd, &command) != RPC_OK) { 1106 cli_out("Error: pli_send_packet cmd failed\n"); 1107 return -1; 1108 } 1109 if (writen(v->sockfd,buf,len) != len) { 1110 cli_out("Error: pli_send_packet data failed\n"); 1111 return -1; 1112 } 1113 return 0; 1114 } 1115 1116 /* 1117 * Client call: enable port transmission 1118 */ 1119 uint32 pli_tx_enable(int devNo, uint32 portmap) 1120 { 1121 verinet_t *v = &verinet[devNo]; 1122 rpc_cmd_t command; 1123 1124 make_rpc(&command,RPC_TX_ENABLE,RPC_OK,1,portmap); 1125 1126 if(write_command(v->sockfd, &command) != RPC_OK) { 1127 cli_out("Error: pli_tx_enable cmd failed\n"); 1128 return -1; 1129 } 1130 return 0; 1131 } 1132 1133 /* 1134 * Client call: tell testbench to shutdown 1135 */ 1136 uint32 pli_shutdown(int devNo) 1137 { 1138 verinet_t *v = &verinet[devNo]; 1139 rpc_cmd_t command; 1140 1141 make_rpc(&command,RPC_SHUTDOWN,RPC_OK,0); 1142 1143 if(write_command(v->sockfd, &command) != RPC_OK) { 1144 cli_out("Error: pli_shutdown cmd failed\n"); 1145 return -1; 1146 } 1147 return 0; 1148 } 1149 1150 1151 /* 1152 * Send signal to simulation to activate 1153 */ 1154 uint32 pli_sim_start(int devNo) 1155 { 1156 verinet_t *v = &verinet[devNo]; 1157 rpc_cmd_t command; 1158 1159 make_rpc(&command, RPC_IOCTL_REQ, RPC_OK, 3, BCM_SIM_ACTIVATE, 0, 0); 1160 1161 if(write_command(v->sockfd, &command) != RPC_OK) { 1162 cli_out("Error: pli_sim_start cmd failed\n"); 1163 return -1; 1164 } 1165 return 0; 1166 } 1167 1168 1169 1170 int get_pkt_data(int sockfd, struct timeval* tv, uint32* data) 1171 { 1172 int i, len; 1173 fd_set read_vect; 1174 uint32 swap; 1175 1176 LOG_VERBOSE(BSL_LS_SYS_VERINET, 1177 (BSL_META("get_pkt_data: sockfd=%d\n"), 1178 sockfd)); 1179 1180 assert(sockfd > 2); /* Verinet initialized? */ 1181 1182 /* Setup bitmap for read notification ... */ 1183 FD_ZERO(&read_vect); 1184 FD_SET(sockfd, &read_vect); 1185 1186 while (1) { 1187 if(select(sockfd+1,&read_vect,(fd_set*)0x0,(fd_set*)0x0,tv)<0){ 1188 if (errno == EINTR) { 1189 /* 1190 * Interrupted by a signal such as a GPROF alarm so 1191 * restart the call 1192 */ 1193 continue; 1194 } 1195 perror("get_command: select error"); 1196 goto fail; 1197 } else { 1198 break; 1199 } 1200 } 1201 /* 1202 * Data ready to be read. 1203 */ 1204 if (FD_ISSET(sockfd, &read_vect)) { 1205 /* 1206 * Read RPC opcode. 1207 */ 1208 if(readn(sockfd, &swap, sizeof(uint32)) < sizeof(uint32)){ 1209 goto fail; 1210 } 1211 /* Convert precious info to host byte order */ 1212 i=0; 1213 len = ntohl(swap); 1214 data[i]=len; 1215 /* coverity[tainted_data] */ 1216 while (len>0){ 1217 if (readn(sockfd, &swap, sizeof(uint32)) < sizeof(uint32)){ 1218 cli_out("get_pkt_data: could not read DATA.\n"); 1219 goto fail; 1220 } 1221 i++; 1222 data[i]=ntohl(swap); 1223 len-=4; 1224 } 1225 1226 return 1; 1227 } 1228 1229 fail: 1230 return -1; 1231 } 1232 1233 /* 1234 * Perform an SCHANNEL operation. 1235 */ 1236 uint32 pli_schan(int devNo, uint32* words, int dw_write, int dw_read) 1237 { 1238 int i ; 1239 verinet_t *v = &verinet[devNo]; 1240 uint32 status = 0x0; 1241 rpc_cmd_t command; 1242 1243 make_rpc(&command, RPC_SCHAN_REQ, RPC_OUTSTANDING, 0); 1244 1245 command.argcount = dw_write+2; 1246 command.args[0] = dw_write; 1247 command.args[1] = dw_read; 1248 1249 for(i = 0; i < dw_write; i++) { 1250 command.args[i+2] = words[i]; 1251 } 1252 1253 sal_mutex_take(v->pli_mutex, sal_mutex_FOREVER); 1254 1255 if(write_command(v->sockfd, &command) != RPC_OK) { 1256 cli_out("Error: pli_schan write_command failed\n"); 1257 sal_mutex_give(v->pli_mutex); 1258 return -1; 1259 } 1260 1261 if (wait_command(v->sockfd, &command) < 0) { 1262 sal_mutex_give(v->pli_mutex); 1263 return -1; 1264 } 1265 1266 sal_mutex_give(v->pli_mutex); 1267 1268 /* Schannel operation response is the first argument */ 1269 status = command.args[0]; 1270 1271 for(i = 0; i < dw_read; i++){ 1272 words[i] = command.args[i+1]; 1273 } 1274 1275 if(status == 0) /* Read succeeded */ 1276 return 0; 1277 else 1278 return -1; /* RPC failed */ 1279 }