Пример #1
0
// 物理的にパケットを送信する
void pro100_send_packet_to_line(PRO100_CTX *ctx, void *buf, UINT size)
{
	volatile PRO100_OP_BLOCK *b;
	PRO100_OP_TRANSMIT *t;
	phys_t ptr;
	// 引数チェック
	if (ctx == NULL || buf == NULL || size == 0)
	{
		return;
	}

	// メモリ確保
	b = pro100_alloc_page(&ptr);

	t = (PRO100_OP_TRANSMIT *)b;

	t->op_block.op = PRO100_CU_OP_TRANSMIT;
	t->op_block.transmit_flexible_mode = 0;
	t->op_block.transmit_raw_packet = 0;
	t->op_block.transmit_cid = 31;
	t->op_block.i = false;
	t->op_block.s = false;
	t->op_block.el = true;
	t->op_block.link_address = 0;
	t->tbd_array_address = 0xffffffff;
	t->data_bytes = size;
	t->threshold = 1;

	SeCopy(((UCHAR *)b) + sizeof(PRO100_OP_TRANSMIT) +
		(ctx->use_standard_txcb ? 0 : sizeof(PRO100_TBD) * 2), buf, size);

	if (false)
	{
		char tmp[8000];
		SeBinToStrEx(tmp, sizeof(tmp), (void *)b, size + sizeof(PRO100_OP_TRANSMIT));

		printf("%s\n\n", tmp);
	}

	pro100_init_cu_base_addr(ctx);
	pro100_wait_cu_ru_accepable(ctx);
	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);

	//printf("1\n");
	while (b->c == false);
	//printf("2\n");

	pro100_free_page((void *)b, ptr);
}
Пример #2
0
// バイナリデータのデバッグ出力
void SeDebugBin(void *data, UINT size)
{
	char *tmp;
	UINT tmp_size;
	// 引数チェック
	if (data == NULL)
	{
		return;
	}

	tmp_size = (size + 2) * 3;
	tmp = SeMalloc(tmp_size);

	SeBinToStrEx(tmp, tmp_size, data, size);

	SeDebug("%s", tmp);

	SeFree(tmp);
}
Пример #3
0
// ゲスト OS が開始したオペレーションを処理する
void pro100_proc_guest_op(PRO100_CTX *ctx)
{
	phys_t ptr;
	// 引数チェック
	if (ctx == NULL)
	{
		return;
	}
	if (ctx->guest_cu_started == false || ctx->guest_cu_current_pointer == 0)
	{
		return;
	}

	ptr = ctx->guest_cu_current_pointer;

	// 終端まで読み取る
	while (true)
	{
		PRO100_OP_BLOCK_MAX b;

		if (ctx->guest_cu_suspended)
		{
			// サスペンド中の場合、前回の最後のオペレーションの S ビットがクリア
			// されたかどうか検査する
			pro100_mem_read(&b, ptr, sizeof(b));
			if (b.op_block.s)
			{
				// サスペンド継続中
				break;
			}

			ptr = ctx->guest_cu_next_pointer;

			ctx->guest_cu_suspended = false;
		}

		pro100_mem_read(&b, ptr, sizeof(b));

		if (b.op_block.op == PRO100_CU_OP_TRANSMIT)
		{
			// 送信処理
			PRO100_OP_TRANSMIT *t = (PRO100_OP_TRANSMIT *)&b;

			if (false)
			{
				printf("flexible_mode=%u, raw_packet=%u, cid=%u, array=0x%x, thres=%u, tcount=%u, size=%u\n",
					t->op_block.transmit_flexible_mode,
					t->op_block.transmit_raw_packet,
					t->op_block.transmit_cid,
					t->tbd_array_address,
					t->threshold,
					t->tbd_count,
					t->data_bytes);
			}

			//printf("SEND\n");

			if (false)
			{
				char tmp[4096];

				SeBinToStrEx(tmp, sizeof(tmp), &b, 24);
				printf("%s\n", tmp);
			}

			if (true)
			{
				UCHAR buf[PRO100_MAX_PACKET_SIZE];
				UINT packet_size = pro100_read_send_packet(ctx, ptr, buf);

#ifdef	PRO100_PASS_MODE
				pro100_write_recv_packet(ctx, buf, packet_size);
#else	// PRO100_PASS_MODE
				if (ctx->CallbackRecvVirtNic != NULL)
				{
					void *packet_data[1];
					UINT packet_sizes[1];

					packet_data[0] = buf;
					packet_sizes[0] = packet_size;
					ctx->CallbackRecvVirtNic(ctx, 1, packet_data, packet_sizes, ctx->CallbackRecvVirtNicParam);
				}
#endif	// PRO100_PASS_MODE
			}

			b.op_block.ok = b.op_block.c = true;
			b.op_block.transmit_overrun = false;

			pro100_mem_write(ptr, &b, sizeof(PRO100_OP_BLOCK) + sizeof(PRO100_OP_TRANSMIT));

			if (b.op_block.i)
			{
				pro100_generate_int(ctx);
			}
		}
		else
		{
			// 送信以外の処理
			UINT size = pro100_get_op_size(b.op_block.op, &b);

			//printf("0x%x: OP: %u  Size=%u\n", (UINT)ptr, b.op_block.op, size);

			switch (b.op_block.op)
			{
			case PRO100_CU_OP_IA_SETUP:
				// IA Setup
				SeCopy(ctx->mac_address, ((UCHAR *)&b) + sizeof(PRO100_OP_BLOCK), 6);
				pro100_init_vpn_client(ctx);
				break;

			case PRO100_CU_OP_CONFIG:
				// Configure
				ctx->use_standard_txcb = ((((UCHAR *)&b)[sizeof(PRO100_OP_BLOCK) + 6] & 0x10) ? true : false);
				break;
			}

			pro100_exec_cu_op(ctx, &b, size);

			pro100_mem_write(ptr, &b, size);
		}

		if (b.op_block.el)
		{
			// 終了フラグ
			ctx->guest_cu_started = false;
			ctx->guest_cu_current_pointer = 0;
			ctx->guest_cu_suspended = false;
			//printf("EL\n");
			pro100_generate_int(ctx);
			break;
		}
		if (b.op_block.s)
		{
			// サスペンドフラグ
			ctx->guest_cu_suspended = true;
			ctx->guest_cu_next_pointer = b.op_block.link_address;
			//printf("SUSPEND\n");
			pro100_generate_int(ctx);
			break;
		}

		ptr = b.op_block.link_address;
	}

	if (ctx->guest_cu_started)
	{
		ctx->guest_cu_current_pointer = ptr;
	}
}
Пример #4
0
// 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);
	}
}