// 書き込みフック bool pro100_hook_write(PRO100_CTX *ctx, UINT offset, UINT data, UINT size) { // 引数チェック if (ctx == NULL) { return false; } switch (offset) { case PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0: // RU Command, CU Command if (size == 1) { UCHAR b = (UCHAR)data; UINT ru = PRO100_GET_RU_COMMAND(b); UINT cu = PRO100_GET_CU_COMMAND(b); char *s1 = NULL; char *s2 = NULL; s1 = pro100_get_ru_command_string(ru); s2 = pro100_get_cu_command_string(cu); if (s1 != NULL || s2 != NULL) { //printf("[%s, %s] ", s1, s2); } switch (cu) { case PRO100_CU_CMD_NOOP: break; case PRO100_CU_CMD_START: //printf("GUEST PRO100_CU_CMD_START: 0x%x\n", (UINT)ctx->guest_last_general_pointer); ctx->guest_cu_started = true; ctx->guest_cu_suspended = false; ctx->guest_cu_start_pointer = (phys_t)ctx->guest_last_general_pointer; ctx->guest_cu_current_pointer = ctx->guest_cu_start_pointer; pro100_proc_guest_op(ctx); cu = PRO100_CU_CMD_NOOP; break; case PRO100_CU_CMD_RESUME: //printf("GUEST PRO100_CU_CMD_RESUME\n"); pro100_proc_guest_op(ctx); cu = PRO100_CU_CMD_NOOP; break; case PRO100_CU_CMD_LOAD_CU_BASE: //printf("GUEST PRO100_CU_CMD_LOAD_CU_BASE: 0x%x\n", (UINT)ctx->guest_last_general_pointer); cu = PRO100_CU_CMD_NOOP; ctx->cu_base_inited = false; break; case PRO100_CU_CMD_LOAD_DUMP_ADDR: //printf("GUEST PRO100_CU_CMD_LOAD_DUMP_ADDR: 0x%x\n", (UINT)ctx->guest_last_general_pointer); cu = PRO100_CU_CMD_NOOP; //pro100_write(ctx, PRO100_CSR_OFFSET_SCB_GENERAL_POINTER, (UINT)ctx->guest_last_general_pointer, 4); break; case PRO100_CU_CMD_DUMP_STAT: //printf("GUEST PRO100_CU_CMD_DUMP_STAT\n"); cu = PRO100_CU_CMD_NOOP; break; case PRO100_CU_CMD_DUMP_AND_RESET_STAT: //printf("GUEST PRO100_CU_CMD_DUMP_AND_RESET_STAT\n"); cu = PRO100_CU_CMD_NOOP; break; case PRO100_CU_CMD_HPQ_START: //printf("GUEST PRO100_CU_CMD_HPQ_START: 0x%x\n", (UINT)ctx->guest_last_general_pointer); cu = PRO100_CU_CMD_NOOP; break; case PRO100_CU_CMD_CU_STAT_RESUME: //printf("GUEST PRO100_CU_CMD_CU_STAT_RESUME\n"); //pro100_write(ctx, PRO100_CSR_OFFSET_SCB_GENERAL_POINTER, (UINT)ctx->guest_last_general_pointer, 4); //cu = PRO100_CU_CMD_NOOP; break; case PRO100_CU_CMD_HPQ_RESUME: //printf("GUEST PRO100_CU_CMD_HPQ_RESUME\n"); cu = PRO100_CU_CMD_NOOP; break; default: printf("!!!! GUEST SEND UNKNOWN CU CMD: %u\n", cu); break; } switch (ru) { case PRO100_RU_CMD_NOOP: break; case PRO100_RU_CMD_START: //printf("GUEST PRO100_RU_CMD_START: 0x%x\n", (UINT)ctx->guest_last_general_pointer); ru = PRO100_CU_CMD_NOOP; // ゲスト OS が指定してきた受信バッファのポインタを記憶する ctx->guest_rfd_current = ctx->guest_rfd_first = (phys_t)ctx->guest_last_general_pointer; pro100_poll_ru(ctx); break; case PRO100_RU_CMD_RESUME: //printf("GUEST PRO100_RU_CMD_RESUME\n"); ru = PRO100_CU_CMD_NOOP; ctx->guest_ru_suspended = false; pro100_poll_ru(ctx); break; case PRO100_RU_CMD_LOAD_HEADER_DATA_SIZE: //printf("GUEST PRO100_RU_CMD_LOAD_HEADER_DATA_SIZE: 0x%x\n", (UINT)ctx->guest_last_general_pointer); ru = PRO100_CU_CMD_NOOP; break; case PRO100_RU_CMD_LOAD_RU_BASE: //printf("GUEST PRO100_RU_CMD_LOAD_RU_BASE: 0x%x\n", (UINT)ctx->guest_last_general_pointer); ru = PRO100_CU_CMD_NOOP; ctx->ru_base_inited = false; break; default: printf("!!!! GUEST SEND UNKNOWN RU CMD: %u\n", cu); break; } ru = 0; b = PRO100_MAKE_CU_RU_COMMAND(cu, ru); if ((cu != 0 || ru != 0) && (cu == 0 || ru == 0)) { //printf("<P"); pro100_wait_cu_ru_accepable(ctx); //printf(">"); pro100_write(ctx, PRO100_CSR_OFFSET_SCB_GENERAL_POINTER, (UINT)ctx->guest_last_general_pointer, 4); pro100_write(ctx, PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0, b, 1); //printf("<Y"); pro100_wait_cu_ru_accepable(ctx); //printf(">"); } return true; } break; case PRO100_CSR_OFFSET_SCB_COMMAND_WORD_1: // 割り込み制御ビット if (size == 1) { ctx->int_mask_guest_set = data; if (true) { //PRO100_INT_BIT *ib = (PRO100_INT_BIT *)&ctx->int_mask_guest_set; //printf("int mask: M=%u 0x%x\n", (UINT)ib->mask_all, (UINT)ctx->int_mask_guest_set); /* ib->mask_all = true; ib->fcp = ib->er = ib->rnr = ib->cna = ib->fr = ib->cx = 1; */ //pro100_beep((ib->mask_all == 0 ? 880 : 440), 200); pro100_write(ctx, PRO100_CSR_OFFSET_SCB_COMMAND_WORD_1, ctx->int_mask_guest_set, 4); return true; } } break; case PRO100_CSR_OFFSET_SCB_GENERAL_POINTER: // 汎用ポインタ if (size == 4) { ctx->guest_last_general_pointer = data; //printf("GUEST WRITES POINTER: 0x%x\n", data); } return true; case PRO100_CSR_OFFSET_SCB_STATUS_WORD_1: // STAT/ACK /*if (size == 1) { printf("<ACK>"); if (data != 0) { pro100_write(ctx, PRO100_CSR_OFFSET_SCB_STATUS_WORD_1, 0xff, 1); } return true; }*/ pro100_poll_ru(ctx); break; case PRO100_CSR_OFFSET_SCB_PORT: // ポート break; case PRO100_CSR_OFFSET_SCB_MDI: // MDI break; default: //printf("*** ACCESS TO 0x%x size=%u data=0x%x\n", offset, size, data); break; } return false; }
// 書き込みフック bool pro100_hook_write(PRO100_CTX *ctx, UINT offset, UINT data, UINT size) { // 引数チェック if (ctx == NULL) { return false; } switch (offset) { case PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0: // RU Command, CU Command if (size != 1) { debugprint("pro100_hook_write: PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0: BAD SIZE: %u\n", size); } if (size == 1) { UCHAR b = (UCHAR)data; UINT ru = PRO100_GET_RU_COMMAND(b); UINT cu = PRO100_GET_CU_COMMAND(b); char *s1 = NULL; char *s2 = NULL; s1 = pro100_get_ru_command_string(ru); s2 = pro100_get_cu_command_string(cu); if (s1 != NULL || s2 != NULL) { //debugprint("[%s, %s] ", s1, s2); } switch (cu) { case PRO100_CU_CMD_NOOP: break; case PRO100_CU_CMD_START: //debugprint("GUEST PRO100_CU_CMD_START: 0x%x\n", (UINT)ctx->guest_last_general_pointer); ctx->guest_cu_started = true; ctx->guest_cu_suspended = false; ctx->guest_cu_start_pointer = (phys_t)ctx->guest_last_general_pointer; ctx->guest_cu_current_pointer = ctx->guest_cu_start_pointer; pro100_proc_guest_op(ctx); cu = PRO100_CU_CMD_NOOP; break; case PRO100_CU_CMD_RESUME: //debugprint("GUEST PRO100_CU_CMD_RESUME\n"); pro100_proc_guest_op(ctx); cu = PRO100_CU_CMD_NOOP; break; case PRO100_CU_CMD_LOAD_CU_BASE: //debugprint("GUEST PRO100_CU_CMD_LOAD_CU_BASE: 0x%x\n", (UINT)ctx->guest_last_general_pointer); cu = PRO100_CU_CMD_NOOP; ctx->cu_base_inited = false; break; case PRO100_CU_CMD_LOAD_DUMP_ADDR: debugprint("GUEST PRO100_CU_CMD_LOAD_DUMP_ADDR: 0x%x\n", (UINT)ctx->guest_last_general_pointer); cu = PRO100_CU_CMD_NOOP; //pro100_write(ctx, PRO100_CSR_OFFSET_SCB_GENERAL_POINTER, (UINT)ctx->guest_last_general_pointer, 4); ctx->guest_last_counter_pointer = ctx->guest_last_general_pointer; break; case PRO100_CU_CMD_DUMP_STAT: case PRO100_CU_CMD_DUMP_AND_RESET_STAT: debugprint(cu == PRO100_CU_CMD_DUMP_STAT ? "GUEST PRO100_CU_CMD_DUMP_STAT\n" : "GUEST PRO100_CU_CMD_DUMP_AND_RESET_STAT\n"); if (ctx->guest_last_counter_pointer != 0) { UINT dummy_data[21]; // ゲスト OS がカウンタデータのダンプを要求しているのでウソのデータを返す // (これをしないと Windows 版ドライバの一部で 2 秒間のビジーループによる待ちが発生してしまう) memset(dummy_data, 0, sizeof(dummy_data)); dummy_data[16] = dummy_data[19] = dummy_data[20] = (cu == PRO100_CU_CMD_DUMP_STAT ? 0xa005 : 0xa007); pro100_mem_write((phys_t)ctx->guest_last_counter_pointer, dummy_data, sizeof(dummy_data)); } else { debugprint("error: ctx->guest_last_counter_pointer == 0\n"); } cu = PRO100_CU_CMD_NOOP; break; case PRO100_CU_CMD_HPQ_START: //debugprint("GUEST PRO100_CU_CMD_HPQ_START: 0x%x\n", (UINT)ctx->guest_last_general_pointer); cu = PRO100_CU_CMD_NOOP; break; case PRO100_CU_CMD_CU_STAT_RESUME: //debugprint("GUEST PRO100_CU_CMD_CU_STAT_RESUME\n"); //pro100_write(ctx, PRO100_CSR_OFFSET_SCB_GENERAL_POINTER, (UINT)ctx->guest_last_general_pointer, 4); //cu = PRO100_CU_CMD_NOOP; break; case PRO100_CU_CMD_HPQ_RESUME: //debugprint("GUEST PRO100_CU_CMD_HPQ_RESUME\n"); cu = PRO100_CU_CMD_NOOP; break; default: printf("!!!! GUEST SEND UNKNOWN CU CMD: %u\n", cu); break; } switch (ru) { case PRO100_RU_CMD_NOOP: break; case PRO100_RU_CMD_START: //debugprint("GUEST PRO100_RU_CMD_START: 0x%x\n", (UINT)ctx->guest_last_general_pointer); ru = PRO100_CU_CMD_NOOP; // ゲスト OS が指定してきた受信バッファのポインタを記憶する ctx->guest_rfd_current = ctx->guest_rfd_first = (phys_t)ctx->guest_last_general_pointer; pro100_poll_ru(ctx); break; case PRO100_RU_CMD_RESUME: //debugprint("GUEST PRO100_RU_CMD_RESUME\n"); ru = PRO100_CU_CMD_NOOP; ctx->guest_ru_suspended = false; pro100_poll_ru(ctx); break; case PRO100_RU_CMD_LOAD_HEADER_DATA_SIZE: //debugprint("GUEST PRO100_RU_CMD_LOAD_HEADER_DATA_SIZE: 0x%x\n", (UINT)ctx->guest_last_general_pointer); ru = PRO100_CU_CMD_NOOP; break; case PRO100_RU_CMD_LOAD_RU_BASE: //debugprint("GUEST PRO100_RU_CMD_LOAD_RU_BASE: 0x%x\n", (UINT)ctx->guest_last_general_pointer); ru = PRO100_CU_CMD_NOOP; ctx->ru_base_inited = false; break; default: printf("!!!! GUEST SEND UNKNOWN RU CMD: %u\n", ru); break; } ru = 0; b = PRO100_MAKE_CU_RU_COMMAND(cu, ru); if ((cu != 0 || ru != 0) && (cu == 0 || ru == 0)) { debugprint("<P"); pro100_wait_cu_ru_accepable(ctx); debugprint(">"); pro100_write(ctx, PRO100_CSR_OFFSET_SCB_GENERAL_POINTER, (UINT)ctx->guest_last_general_pointer, 4); pro100_write(ctx, PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0, b, 1); debugprint("<Y"); pro100_wait_cu_ru_accepable(ctx); debugprint(">"); } return true; } break; case PRO100_CSR_OFFSET_SCB_COMMAND_WORD_1: // 割り込み制御ビット if (size != 1) { debugprint("pro100_hook_write: PRO100_CSR_OFFSET_SCB_COMMAND_WORD_1: BAD SIZE: %u\n", size); } if (size == 1) { ctx->int_mask_guest_set = data; if (true) { //PRO100_INT_BIT *ib = (PRO100_INT_BIT *)&ctx->int_mask_guest_set; //debugprint("int mask: M=%u 0x%x\n", (UINT)ib->mask_all, (UINT)ctx->int_mask_guest_set); /* ib->mask_all = true; ib->fcp = ib->er = ib->rnr = ib->cna = ib->fr = ib->cx = 1; */ //pro100_beep((ib->mask_all == 0 ? 880 : 440), 200); pro100_write(ctx, PRO100_CSR_OFFSET_SCB_COMMAND_WORD_1, ctx->int_mask_guest_set, 4); return true; } } break; case PRO100_CSR_OFFSET_SCB_GENERAL_POINTER: // 汎用ポインタ if (size != 4) { debugprint("pro100_hook_write: PRO100_CSR_OFFSET_SCB_GENERAL_POINTER: BAD SIZE: %u\n", size); } if (size == 4) { ctx->guest_last_general_pointer = data; //debugprint("GUEST WRITES POINTER: 0x%x\n", data); } return true; case PRO100_CSR_OFFSET_SCB_STATUS_WORD_1: // STAT/ACK /*if (size == 1) { debugprint("<ACK>"); if (data != 0) { pro100_write(ctx, PRO100_CSR_OFFSET_SCB_STATUS_WORD_1, 0xff, 1); } return true; }*/ pro100_poll_ru(ctx); break; case PRO100_CSR_OFFSET_SCB_PORT: // ポート break; case PRO100_CSR_OFFSET_SCB_MDI: // MDI break; default: if (offset == 0 && size == 2) { UCHAR buf[4]; *((UINT *)buf) = data; pro100_hook_write(ctx, 1, buf[1], 1); return true; } else { if (offset < 0x10) { printf("*** WRITE ACCESS TO 0x%x size=%u data=0x%x\n", offset, size, data); } } break; } return false; }