proc_req.c (6296B)
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 * File: proc_req.c 8 * Purpose: 9 * Requires: 10 */ 11 12 13 #include <shared/bsl.h> 14 15 #include <unistd.h> 16 #include <stdlib.h> 17 18 #include <netinet/in.h> 19 #include <arpa/inet.h> 20 #include <memory.h> 21 22 #include <sys/types.h> 23 #include <sys/socket.h> 24 #include <sys/time.h> 25 #include <soc/mem.h> 26 #include <soc/hash.h> 27 28 #include <soc/cmic.h> 29 #include <soc/drv.h> 30 #include <soc/debug.h> 31 #include <soc/schanmsg.h> 32 #include <sal/appl/io.h> 33 #include <bde/pli/verinet.h> 34 35 #include "pcid.h" 36 #include "mem.h" 37 #include "cmicsim.h" 38 #include "dma.h" 39 #include "pli.h" 40 41 STATIC rpc_cmd_t cmd; 42 /* 43 * Handles an incoming client request 44 * We block until the client has something to send us and then 45 * we do something over the socket descriptor. 46 * Returns 1 when a command is processed, 0 on disconnect. 47 */ 48 49 int pcid_process_request(pcid_info_t *pcid_info, int sockfd, 50 struct timeval *tmout) 51 { 52 char buf[32]; 53 uint32 regval; 54 int r, unit, finished = 0; 55 56 unit = pcid_info->unit; 57 r = get_command(sockfd, tmout, &cmd); 58 59 if (r == 0) { 60 return PR_NO_REQUEST; /* No request; return to poll later */ 61 } 62 63 if (r < 0) { /* Error; cause polling loop to exit */ 64 return PR_ERROR; 65 } 66 67 switch (cmd.opcode) { 68 /* 69 * We only handle requests: anything else is a programming 70 * error. Once we are here, all parameters have been marshalled 71 * and we simply need to call the correct routine (see pli_cmd.c). 72 */ 73 74 case RPC_SCHAN_REQ: 75 { 76 schan_msg_t msg; 77 int i; 78 int dw_write, dw_read; 79 extern int schan_op(pcid_info_t *pcid_info, int unit, schan_msg_t* data); 80 81 dw_write = cmd.args[0]; 82 dw_read = cmd.args[1]; 83 84 for(i = 0; i < dw_write; i++) { 85 msg.dwords[i] = cmd.args[i+2]; 86 } 87 PCID_MEM_LOCK(pcid_info); 88 if (!(pcid_info->schan_cb) || 89 (i = (pcid_info->schan_cb)(pcid_info, unit, &msg))) { 90 i = schan_op(pcid_info, unit, &msg); 91 } 92 PCID_MEM_UNLOCK(pcid_info); 93 make_rpc(&cmd, RPC_SCHAN_RESP, RPC_OK, 0); 94 cmd.argcount = dw_read+1; 95 cmd.args[0] = i; 96 for(i = 0; i < dw_read; i++) { 97 cmd.args[i+1] = msg.dwords[i]; 98 } 99 if (write_command(sockfd, &cmd) != RPC_OK) { 100 pcid_info->opt_rpc_error = 1; 101 } 102 break; 103 } 104 105 case RPC_GETREG_REQ: /* PIO read of register */ 106 /* Get a register from our model ... */ 107 /* cmd.args[1] is register type (verinet.h) */ 108 109 regval = pli_getreg_service(pcid_info, unit, cmd.args[1], cmd.args[0]); 110 111 /* coverity[secure_coding] */ 112 strcpy(buf, "********"); 113 make_rpc_getreg_resp(&cmd, 114 0, 115 regval, 116 buf); 117 if (write_command(sockfd, &cmd) != RPC_OK) { 118 pcid_info->opt_rpc_error = 1; 119 } 120 121 break; 122 123 case RPC_SETREG_REQ: /* PIO write to register */ 124 /* Set a register on our model... */ 125 /* coverity[stack_use_overflow] */ 126 pli_setreg_service(pcid_info, unit, cmd.args[2], cmd.args[0], 127 cmd.args[1]); 128 make_rpc_setreg_resp(&cmd, cmd.args[1]); 129 if (write_command(sockfd, &cmd) != RPC_OK) { 130 pcid_info->opt_rpc_error = 1; 131 } 132 break; 133 134 case RPC_IOCTL_REQ: /* Change something inside the model */ 135 if (pcid_info->ioctl) { 136 pcid_info->ioctl(pcid_info, cmd.args); 137 } 138 break; 139 140 case RPC_SHUTDOWN: /* Change something inside the model */ 141 if (pcid_info->ioctl) { 142 cmd.args[0] = BCM_SIM_DEACTIVATE; 143 pcid_info->ioctl(pcid_info, cmd.args); 144 } 145 break; 146 147 case RPC_REGISTER_CLIENT: 148 /* Setup port for DMA r/w requests to client and interrupts ...*/ 149 /* Connect to client interrupt and DMA ports and test*/ 150 LOG_CLI((BSL_META_U(unit, 151 "Received register client request\n"))); 152 regval = RPC_OK; 153 154 pcid_info->client = register_client(sockfd, 155 cmd.args[0], 156 cmd.args[1], 157 cmd.args[2]); 158 159 if (pcid_info->client == 0) { 160 finished = 1; 161 break; 162 } 163 164 /* 165 * TEST: Write to DMA address 0 on client. 166 */ 167 r = dma_writemem(pcid_info->client->dmasock, 168 0, 169 0xbabeface); 170 171 /* 172 * TEST: Read from DMA address 0 on client. 173 */ 174 r = dma_readmem(pcid_info->client->dmasock,0, ®val); 175 176 /* TEST: Result should be the same, if not FAIL! */ 177 if(regval != 0xbabeface){ 178 LOG_CLI((BSL_META_U(unit, 179 "ERROR: regval = 0x%x\n"), regval)); 180 pcid_info->opt_rpc_error = 1; 181 } 182 183 /* 184 * TEST: Send an interrupt to the client. 185 */ 186 r = send_interrupt(pcid_info->client->intsock, 0); 187 if (r < 0) { 188 LOG_ERROR(BSL_LS_SOC_COMMON, 189 (BSL_META_U(unit, 190 "RPC error: soc_internal_send_int failed. \n"))); 191 pcid_info->opt_rpc_error = 1; 192 } else { 193 r = RPC_OK; 194 } 195 196 /* Send Registration status back ... */ 197 make_rpc_register_resp(&cmd, r); 198 if (write_command(pcid_info->client->piosock, &cmd) != RPC_OK) { 199 pcid_info->opt_rpc_error = 1; 200 } 201 202 LOG_VERBOSE(BSL_LS_SOC_COMMON, 203 (BSL_META_U(unit, 204 "Client registration: 0x%x DMA=0x%x, INT=0x%x, PIO=0x%x -OK\n"), 205 pcid_info->client->inetaddr, 206 pcid_info->client->dmasock, 207 pcid_info->client->intsock, 208 pcid_info->client->piosock)); 209 210 break; 211 212 case RPC_DISCONNECT: 213 /* First disconnect the interrupt and dma sockets on client */ 214 215 unregister_client(pcid_info->client); 216 217 finished = 1; 218 break; 219 220 default: 221 /* Unknown opcode */ 222 break; 223 } 224 225 return (finished ? PR_ALL_DONE : PR_REQUEST_HANDLED); 226 }