// 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) { 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; }