Example #1
0
// 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;
}
Example #2
0
// 書き込みフック
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;
}