void LoadCommand::send_command(AFU_EVENT *afu_event, uint32_t new_tag, uint64_t address, uint16_t command_size, uint8_t abort, uint16_t context){ if(Command::state != IDLE) error_msg("LoadCommand: Attempting to send command before previous command is completed"); Command::completed = false; uint32_t tag_parity = (command_tag_parity)? generate_parity(new_tag + 1, ODD_PARITY) : generate_parity(new_tag, ODD_PARITY); uint32_t code_parity = (command_code_parity)? generate_parity(Command::code + 1, ODD_PARITY) : generate_parity(Command::code, ODD_PARITY); uint32_t address_parity = (command_address_parity)? generate_parity(address + 1, ODD_PARITY) : generate_parity(address, ODD_PARITY); if(psl_afu_command(afu_event, new_tag, tag_parity, Command::code, code_parity, address, address_parity, command_size, abort, context) != PSL_SUCCESS) error_msg("LoadCommand: Failed to send command"); info_msg("LoadCommand: handle=0x%x address=0x%016lx code=0x%04x size=0x%02x", context, address, Command::code, command_size); Command::state = WAITING_DATA; Command::tag = new_tag; }
static void generate_cl_parity(uint8_t *data, uint8_t *parity) { int i; uint64_t dw; uint8_t p; for (i=0; i<DWORDS_PER_CACHELINE; i++) { memcpy(&dw, &(data[BYTES_PER_DWORD*i]), BYTES_PER_DWORD); if ((i%BYTES_PER_DWORD)==0) parity[i/BYTES_PER_DWORD]=0; parity[i/BYTES_PER_DWORD]<<=1; p=generate_parity(dw, ODD_PARITY); parity[i/BYTES_PER_DWORD]+=p; } }
// See if a command was sent by AFU and process if so void handle_cmd(struct cmd *cmd, uint32_t parity_enabled, uint32_t latency) { struct cmd_event *event; uint64_t address, address_parity; uint32_t command, command_parity, tag, tag_parity, size, abort, handle; uint8_t parity, fail; int rc; if (cmd == NULL) return; // Check for command from AFU rc = psl_get_command(cmd->afu_event, &command, &command_parity, &tag, &tag_parity, &address, &address_parity, &size, &abort, &handle); // No command ready if (rc != PSL_SUCCESS) return; debug_msg ("%s:COMMAND tag=0x%02x code=0x%04x size=0x%02x abt=%d cch=0x%04x", cmd->afu_name, tag, command, size, abort, handle); debug_msg("%s:COMMAND tag=0x%02x addr=0x%016" PRIx64, cmd->afu_name, tag, address); // Is AFU running? if (*(cmd->psl_state) != PSLSE_RUNNING) { warn_msg("Command without jrunning, tag=0x%02x", tag); return; } // Check parity fail = 0; if (parity_enabled) { parity = generate_parity(address, ODD_PARITY); if (parity != address_parity) { _cmd_parity_error("address", (uint64_t) address, address_parity); fail = 1; } parity = generate_parity(tag, ODD_PARITY); if (parity != tag_parity) { _cmd_parity_error("tag", (uint64_t) tag, tag_parity); fail = 1; } parity = generate_parity(command, ODD_PARITY); if (parity != command_parity) { _cmd_parity_error("code", (uint64_t) command, command_parity); fail = 1; } } // Add failed command if (fail) { _add_other(cmd, handle, tag, command, abort, PSL_RESPONSE_FAILED); return; } // Check credits and parse if (!cmd->credits) { warn_msg("AFU issued command without any credits"); _add_other(cmd, handle, tag, command, abort, PSL_RESPONSE_FAILED); return; } cmd->credits--; // Client not connected if ((cmd == NULL) || (cmd->client == NULL) || (handle >= cmd->max_clients) || ((cmd->client[handle]) == NULL)) { _add_other(cmd, handle, tag, command, abort, PSL_RESPONSE_FAILED); return; } // Client is flushing new commands if ((cmd->client[handle]->flushing == FLUSH_FLUSHING) && (command != PSL_COMMAND_RESTART)) { _add_other(cmd, handle, tag, command, abort, PSL_RESPONSE_FLUSHED); return; } // Check for duplicate tag event = cmd->list; while (event != NULL) { if (event->tag == tag) { error_msg("Duplicate tag 0x%02x", tag); return; } event = event->_next; } // Parse command _parse_cmd(cmd, command, tag, address, size, abort, handle, latency); }