// CU と RU が受付可能になるまで待機 void pro100_wait_cu_ru_accepable(PRO100_CTX *ctx) { bool flag = false; // 引数チェック if (ctx == NULL) { return; } //printf("{B"); while (true) { UINT t = pro100_read(ctx, PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0, 1); if (t == 0) { break; } if (flag == false) { flag = true; // printf(" ** CU=%u, RU=%u ** \n", // PRO100_GET_CU_COMMAND(t), PRO100_GET_RU_COMMAND(t)); } } // printf("} "); }
// 書き込み操作のフラッシュ void pro100_flush(PRO100_CTX *ctx) { // 引数チェック if (ctx == NULL) { return; } pro100_read(ctx, PRO100_CSR_OFFSET_SCB_STATUS_WORD_0, 1); }
// CU にオペレーションを実行させる void pro100_exec_cu_op(PRO100_CTX *ctx, PRO100_OP_BLOCK_MAX *op, UINT size) { volatile PRO100_OP_BLOCK *b; PRO100_OP_BLOCK *b2; phys_t ptr; bool src_el, src_s, src_i; UINT src_link_addr; bool timeouted; UINT64 start_tick; // 引数チェック if (ctx == NULL || op == NULL) { return; } // メモリ確保 b = pro100_alloc_page(&ptr); // 一時領域にコピー SeCopy((void *)b, op, size); // バックアップ src_el = b->el; src_s = b->s; src_i = b->i; src_link_addr = b->link_address; // フラグセット b->el = true; b->s = false; //b->ok = b->c = false; b->link_address = ptr; //b->i = false; pro100_init_cu_base_addr(ctx); pro100_wait_cu_ru_accepable(ctx); if (false) { char tmp[4096]; SeBinToStrEx(tmp, sizeof(tmp), (void *)b, size); printf("%s\n", tmp); } pro100_write(ctx, PRO100_CSR_OFFSET_SCB_GENERAL_POINTER, (UINT)ptr, 4); pro100_write(ctx, PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0, PRO100_MAKE_CU_RU_COMMAND(PRO100_CU_CMD_START, PRO100_RU_CMD_NOOP), 1); pro100_flush(ctx); // NIC がコマンドを完了するまで待機 //printf("["); start_tick = SeTick64(); timeouted = true; while ((start_tick + 1000ULL) >= SeTick64()) { if (b->c) { timeouted = false; break; } } //printf("%u] ", b->c); //b->c = true; if (false) { UINT t = pro100_read(ctx, PRO100_CSR_OFFSET_SCB_STATUS_WORD_0, 1); PRO100_SCB_STATUS_WORD_BIT *b = (PRO100_SCB_STATUS_WORD_BIT *)(void *)&t; printf("STATUS CU=%u, RU=%u\n", b->cu_status, b->ru_status); } // 結果を書き戻す SeCopy(op, (void *)b, size); b2 = (PRO100_OP_BLOCK *)op; // バックアップを復元 b2->el = src_el; b2->s = src_s; b2->i = src_i; b2->link_address = src_link_addr; // メモリ解放 pro100_free_page((void *)b, ptr); if (timeouted && src_i) { //pro100_generate_int(ctx); } }
// CSR レジスタ用 MMIO ハンドラ int pro100_mm_handler(void *data, phys_t gphys, bool wr, void *buf, uint len, u32 flags) { int ret = 0; PRO100_CTX *ctx = (PRO100_CTX *)data; SeLock(ctx->lock); // 範囲チェック if (((UINT64)gphys >= (UINT64)ctx->csr_mm_addr) && ((UINT64)gphys < ((UINT64)ctx->csr_mm_addr) + (UINT64)PRO100_CSR_SIZE)) { UINT offset = (UINT)((UINT64)gphys - (UINT64)ctx->csr_mm_addr); if (len == 1 || len == 2 || len == 4) { if (wr == 0) { UINT ret_data = 0; if (pro100_hook_read(ctx, offset, len, &ret_data) == false) { ret_data = pro100_read(ctx, offset, len); } if (len == 1) { *((UCHAR *)buf) = (UCHAR)ret_data; } else if (len == 2) { *((USHORT *)buf) = (USHORT)ret_data; } else if (len == 4) { *((UINT *)buf) = (UINT)ret_data; } } else { UINT data = 0; if (len == 1) { data = (UINT)(*((UCHAR *)buf)); } else if (len == 2) { data = (UINT)(*((USHORT *)buf)); } else if (len == 4) { data = (UINT)(*((UINT *)buf)); } if (pro100_hook_write(ctx, offset, data, len) == false) { pro100_write(ctx, offset, data, len); } } ret = 1; } } SeUnlock(ctx->lock); return ret; }
// 読み取りフック bool pro100_hook_read(PRO100_CTX *ctx, UINT offset, UINT size, UINT *data) { // 引数チェック if (ctx == NULL) { return false; } switch (offset) { case PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0: // コマンド実行状態 if (size == 1) { UINT t = pro100_read(ctx, PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0, 1); t = PRO100_MAKE_CU_RU_COMMAND(0, 0); *data = t; return true; } break; case PRO100_CSR_OFFSET_SCB_STATUS_WORD_0: // RU と CU のステータス if (size == 1) { UINT t = pro100_read(ctx, PRO100_CSR_OFFSET_SCB_STATUS_WORD_0, 1); PRO100_SCB_STATUS_WORD_BIT *sb = (PRO100_SCB_STATUS_WORD_BIT *)(void *)&t; sb->ru_status = 2; *data = t; return true; } break; case PRO100_CSR_OFFSET_SCB_STATUS_WORD_1: // STAT/ACK pro100_poll_ru(ctx); if (size == 1) { UINT t; PRO100_STAT_ACK *sa; //printf("<INT>"); pro100_proc_guest_op(ctx); t = pro100_read(ctx, offset, size); pro100_write(ctx, offset, t, 1); sa = (PRO100_STAT_ACK *)(void *)&t; sa->cna = sa->cx_tno = sa->fr = sa->rnr = sa->mdi = sa->swi = sa->fcp = 1; sa->rnr = 0; *data = t; return true; } break; case PRO100_CSR_OFFSET_SCB_COMMAND_WORD_1: // 割り込み制御ビット if (size == 1) { UINT t = ctx->int_mask_guest_set; PRO100_INT_BIT *bi = (PRO100_INT_BIT *)(void *)&t; bi->si = false; *data = t; return true; } break; case PRO100_CSR_OFFSET_SCB_GENERAL_POINTER: // 汎用ポインタ if (size == 4) { *data = ctx->guest_last_general_pointer; return true; } break; } return false; }
// 読み取りフック bool pro100_hook_read(PRO100_CTX *ctx, UINT offset, UINT size, UINT *data) { // 引数チェック if (ctx == NULL) { return false; } switch (offset) { case PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0: // コマンド実行状態 if (size != 1) { debugprint("pro100_hook_read: PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0: BAD SIZE: %u\n", size); } if (size == 1) { UINT t = pro100_read(ctx, PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0, 1); t = PRO100_MAKE_CU_RU_COMMAND(0, 0); *data = t; return true; } break; case PRO100_CSR_OFFSET_SCB_STATUS_WORD_0: // RU と CU のステータス if (size != 1) { if (size != 2) { debugprint("pro100_hook_read: PRO100_CSR_OFFSET_SCB_STATUS_WORD_0: BAD SIZE: %u\n", size); } else { UINT data1 = 0, data2 = 0; UCHAR data3[4]; pro100_hook_read(ctx, PRO100_CSR_OFFSET_SCB_STATUS_WORD_0, 1, &data1); pro100_hook_read(ctx, PRO100_CSR_OFFSET_SCB_STATUS_WORD_1, 1, &data2); data3[0] = (UCHAR)data1; data3[1] = (UCHAR)data2; data3[2] = data3[3] = 0; *data = *((UINT *)data3); //debugprint("*data = 0x%x\n", *data); return true; } } if (size == 1) { UINT t = pro100_read(ctx, PRO100_CSR_OFFSET_SCB_STATUS_WORD_0, 1); PRO100_SCB_STATUS_WORD_BIT *sb = (PRO100_SCB_STATUS_WORD_BIT *)(void *)&t; sb->ru_status = 2; *data = t; return true; } break; case PRO100_CSR_OFFSET_SCB_STATUS_WORD_1: // STAT/ACK pro100_poll_ru(ctx); if (size != 1) { debugprint("pro100_hook_read: PRO100_CSR_OFFSET_SCB_STATUS_WORD_1: BAD SIZE: %u\n", size); } if (size == 1) { UINT t; PRO100_STAT_ACK *sa; //debugprint("<INT>"); pro100_proc_guest_op(ctx); t = pro100_read(ctx, offset, size); pro100_write(ctx, offset, t, 1); sa = (PRO100_STAT_ACK *)(void *)&t; sa->cna = sa->cx_tno = sa->fr = sa->rnr = sa->mdi = sa->swi = sa->fcp = 1; sa->rnr = 0; *data = t; return true; } break; case PRO100_CSR_OFFSET_SCB_COMMAND_WORD_1: // 割り込み制御ビット if (size != 1) { debugprint("pro100_hook_read: PRO100_CSR_OFFSET_SCB_COMMAND_WORD_1: BAD SIZE: %u\n", size); } if (size == 1) { UINT t = ctx->int_mask_guest_set; PRO100_INT_BIT *bi = (PRO100_INT_BIT *)(void *)&t; bi->si = false; *data = t; return true; } break; case PRO100_CSR_OFFSET_SCB_GENERAL_POINTER: // 汎用ポインタ if (size != 4) { debugprint("pro100_hook_read: PRO100_CSR_OFFSET_SCB_GENERAL_POINTER: BAD SIZE: %u\n", size); } if (size == 4) { *data = ctx->guest_last_general_pointer; return true; } break; default: if (offset < 0x10) { printf("*** READ ACCESS TO 0x%x size=%u\n", offset, size); } break; } return false; }