void handle_buffer_data(struct cmd *cmd, uint32_t parity_enable) { uint8_t *parity_check; int rc; struct cmd_event *event; int quadrant, byte; // Has struct been initialized? if ((cmd == NULL) || (cmd->buffer_read == NULL)) return; // Check if buffer read data has returned from AFU event = cmd->buffer_read; rc = psl_get_buffer_read_data(cmd->afu_event, event->data, event->parity); if (rc == PSL_SUCCESS) { debug_msg("%s:BUFFER READ tag=0x%02x", cmd->afu_name, event->tag); for (quadrant = 0; quadrant < 4; quadrant++) { DPRINTF("DEBUG: Q%d 0x", quadrant); for (byte = 0; byte < CACHELINE_BYTES / 4; byte++) { DPRINTF("%02x", event->data[byte]); } DPRINTF("\n"); } if (parity_enable) { parity_check = (uint8_t *) malloc(DWORDS_PER_CACHELINE / 8); generate_cl_parity(event->data, parity_check); if (strncmp((char *)event->parity, (char *)parity_check, DWORDS_PER_CACHELINE / 8)) { error_msg("Buffer read parity error tag=0x%02x", event->tag); } free(parity_check); } // Free buffer interface for another event cmd->buffer_read = NULL; // Randomly decide to not send data to client yet if (!event->buffer_activity && allow_buffer(cmd->parms)) { event->state = MEM_TOUCHED; event->buffer_activity = 1; return; } event->state = MEM_RECEIVED; } }
static void handle_psl_events (struct cxl_afu_h* afu) { uint32_t tag, size; uint8_t *addr; uint8_t parity[DWORDS_PER_CACHELINE]; if (status.event->aux2_change) { status.event->aux2_change = 0; if (afu->running != status.event->job_running) { status.event_occurred = 1-status.event->job_running; } if (status.event->job_running) afu->running = 1; if (status.event->job_done) { if (status.cmd.request==AFU_RESET) status.cmd.request = AFU_IDLE; afu->running = 0; } #ifdef DEBUG printf ("AUX2 jrunning=%d jdone=%d", status.event->job_running, status.event->job_done); if (status.event->job_done) { printf (" jerror=0x%016llx", (long long) status.event->job_error); } printf ("\n"); #endif /* #ifdef DEBUG */ } if (psl_get_mmio_acknowledge (status.event, (uint64_t *) &(status.mmio.data), (uint32_t *) &(status.mmio.parity)) == PSL_SUCCESS) { #ifdef DEBUG printf ("MMIO Acknowledge\n"); #endif /* #ifdef DEBUG */ status.mmio.request = AFU_IDLE; } if (status.first_br && status.psl_state==PSL_FLUSHING) { add_resp (status.first_br->tag, PSL_RESPONSE_FLUSHED); remove_buffer_read(); } else if (status.first_br) { uint8_t *buffer = (uint8_t *) malloc (CACHELINE_BYTES); if (psl_get_buffer_read_data (status.event, buffer, parity) == PSL_SUCCESS) { uint64_t offset = (uint64_t) status.first_br->addr; offset &= 0x7Fll; memcpy (status.first_br->addr, &(buffer[offset]), status.first_br->size); ++status.credits; #ifdef DEBUG printf ("Response tag=0x%02x\n", status.first_br->tag); #endif /* #ifdef DEBUG */ if ((status.first_br->resp_type==RESP_UNLOCK) && ((status.psl_state==PSL_LOCK) || (status.psl_state==PSL_NLOCK))) { #ifdef DEBUG printf ("Lock sequence completed\n"); fflush (stdout); #endif /* #ifdef DEBUG */ status.psl_state = PSL_RUNNING; } // Inject random "Paged" response if (!PAGED_RANDOMIZER || (rand() % PAGED_RANDOMIZER)) { add_resp (status.first_br->tag, PSL_RESPONSE_DONE); } else { add_resp (status.first_br->tag, PSL_RESPONSE_PAGED); status.psl_state = PSL_FLUSHING; } // Stop remembing status.first_br remove_buffer_read(); } } if (status.event->command_valid) { #ifdef DEBUG printf ("Command tag=0x%02x\n", status.event->command_tag); #endif /* #ifdef DEBUG */ status.event->command_valid = 0; tag = status.event->command_tag; size = status.event->command_size; if ((status.psl_state==PSL_FLUSHING) && (status.event->command_code != 1)) { #ifdef DEBUG printf ("Response FLUSHED tag=0x%02x\n", tag); fflush (stdout); #endif /* #ifdef DEBUG */ add_resp (tag, PSL_RESPONSE_FLUSHED); return; } --status.credits; addr = (uint8_t *) status.event->command_address; if (((status.psl_state==PSL_LOCK) && (status.event->command_code!=PSL_COMMAND_WRITE_UNLOCK)) || (status.psl_state==PSL_NLOCK)) { #ifdef DEBUG printf ("Response NLOCK tag=0x%02x\n", tag); #endif /* #ifdef DEBUG */ add_resp (tag, PSL_RESPONSE_NLOCK); status.psl_state=PSL_NLOCK; update_pending_resps (PSL_RESPONSE_NLOCK); #ifdef DEBUG printf ("Dumping lock intervening command, tag=0x%02x\n", tag); fflush (stdout); #endif /* #ifdef DEBUG */ return; } uint8_t resp_type = RESP_NORMAL; switch (status.event->command_code) { // Interrupt case PSL_COMMAND_INTREQ: printf ("AFU interrupt command received\n"); status.event_occurred = 1; #ifdef DEBUG printf ("Response tag=0x%02x\n", tag); #endif /* #ifdef DEBUG */ add_resp (tag, PSL_RESPONSE_FLUSHED); break; // Restart case PSL_COMMAND_RESTART: status.psl_state = PSL_RUNNING; #ifdef DEBUG printf ("AFU restart command received\n"); printf ("Response tag=0x%02x\n", tag); #endif /* #ifdef DEBUG */ add_resp (tag, PSL_RESPONSE_DONE); break; // Memory Reads case PSL_COMMAND_READ_CL_LCK: update_pending_resps (PSL_RESPONSE_NLOCK); status.psl_state = PSL_LOCK; #ifdef DEBUG printf ("Starting lock sequence, tag=0x%02x\n", tag); fflush (stdout); #endif /* #ifdef DEBUG */ case PSL_COMMAND_READ_CL_RES: case PSL_COMMAND_READ_CL_S: case PSL_COMMAND_READ_CL_M: case PSL_COMMAND_READ_CL_NA: case PSL_COMMAND_READ_PNA: case PSL_COMMAND_READ_LS: case PSL_COMMAND_READ_LM: case PSL_COMMAND_RD_GO_S: case PSL_COMMAND_RD_GO_M: #ifdef DEBUG printf ("Read command size=%d tag=0x%02x\n", size, tag); #endif /* #ifdef DEBUG */ buffer_event (0, tag, addr); break; // Memory Writes case PSL_COMMAND_WRITE_UNLOCK: resp_type = RESP_UNLOCK; case PSL_COMMAND_WRITE_C: case PSL_COMMAND_WRITE_MI: case PSL_COMMAND_WRITE_MS: case PSL_COMMAND_WRITE_NA: case PSL_COMMAND_WRITE_INJ: case PSL_COMMAND_WRITE_LM: #ifdef DEBUG printf ("Write command size=%d, tag=0x%02x\n", size, tag); #endif /* #ifdef DEBUG */ //printf ("Memory write request 0x%02x\n", tag); // Only issue buffer read if no other pending if (!status.first_br) { //printf ("Buffer read request 0x%02x\n", tag); buffer_event (1, tag, addr); } add_buffer_read (tag, size, addr, resp_type); // Remember tag and addr break; default: break; } } }