Пример #1
0
// スリープ
void pro100_sleep(UINT msecs)
{
	UINT64 tick;
	if (msecs == 0)
	{
		return;
	}

	tick = SeTick64() + (UINT64)msecs;

	while (SeTick64() <= tick);
}
Пример #2
0
// 指定した MAC アドレスがリストに登録されているかどうかチェックする
bool SeEthIsSenderMacAddressExistsInList(SE_ETH *e, UCHAR *mac_address)
{
	bool ret = false;
	// 引数チェック
	if (e == NULL || mac_address == NULL)
	{
		return false;
	}

	SeLock(e->SenderMacListLock);
	{
		UINT i;
		bool exists = false;

		for (i = 0;i < SE_LIST_NUM(e->SenderMacList);i++)
		{
			SE_ETH_SENDER_MAC *m = SE_LIST_DATA(e->SenderMacList, i);

			if (SeCmp(m->MacAddress, mac_address, SE_ETHERNET_MAC_ADDR_SIZE) == 0)
			{
				m->Expires = SeTick64() + (UINT64)SE_ETH_SENDER_MAC_EXPIRES;

				ret = true;
			}
		}

		SeEthDeleteOldSenderMacList(e);
	}
	SeUnlock(e->SenderMacListLock);

	return ret;
}
Пример #3
0
// タイマのセット
void SeTimerSet(SE_TIMER *t, UINT interval)
{
	SE_TIMER_ENTRY *e;
	// 引数チェック
	if (t == NULL)
	{
		return;
	}

	// タイマエントリの挿入
	SeLock(t->TimerEntryLock);
	{
		SE_TIMER_ENTRY st;
		UINT64 target_tick = SeTick64() + (UINT64)interval;

		SeZero(&st, sizeof(st));
		st.Tick = target_tick;

		// 同一の Tick を指すタイマエントリが存在するかどうかチェックする
		if (SeSearch(t->TimerEntryList, &st) == NULL)
		{
			// タイマエントリの新規作成
			e = SeZeroMalloc(sizeof(SE_TIMER_ENTRY));
			e->Tick = target_tick;

			// 挿入
			SeInsert(t->TimerEntryList, e);

			// タイマを調整
			SeTimerAdjust(t);
		}
	}
	SeUnlock(t->TimerEntryLock);
}
Пример #4
0
// MAC アドレスをリストへ追加
void SeEthAddSenderMacList(SE_ETH *e, UCHAR *mac_address)
{
	// 引数チェック
	if (e == NULL || mac_address == NULL)
	{
		return;
	}

	SeLock(e->SenderMacListLock);
	{
		UINT i;
		bool exists = false;

		for (i = 0;i < SE_LIST_NUM(e->SenderMacList);i++)
		{
			SE_ETH_SENDER_MAC *m = SE_LIST_DATA(e->SenderMacList, i);

			if (SeCmp(m->MacAddress, mac_address, SE_ETHERNET_MAC_ADDR_SIZE) == 0)
			{
				m->Expires = SeTick64() + (UINT64)SE_ETH_SENDER_MAC_EXPIRES;

				exists = true;
			}
		}

		if (exists == false)
		{
			SE_ETH_SENDER_MAC *m = SeZeroMalloc(sizeof(SE_ETH_SENDER_MAC));

			m->Expires = SeTick64() + (UINT64)SE_ETH_SENDER_MAC_EXPIRES;

			SeCopy(m->MacAddress, mac_address, SE_ETHERNET_MAC_ADDR_SIZE);

			SeAdd(e->SenderMacList, m);
		}

		SeEthDeleteOldSenderMacList(e);
	}
	SeUnlock(e->SenderMacListLock);
}
Пример #5
0
// タイマの調整
void SeTimerAdjust(SE_TIMER *t)
{
	// 引数チェック
	if (t == NULL)
	{
		return;
	}

	SeLock(t->TimerEntryLock);
	{
		UINT num = SE_LIST_NUM(t->TimerEntryList);

		if (num >= 1)
		{
			SE_TIMER_ENTRY *e = SE_LIST_DATA(t->TimerEntryList, 0);

			// タイマの状態が変化したかどうか調べる
			if (e->Tick != t->CurrentTimerTargetTick)
			{
				UINT64 now = SeTick64();
				UINT64 interval64;
				UINT interval;

				// 先頭のタイマエントリまでの時間を求める
				if (e->Tick > now)
				{
					interval64 = e->Tick - now;
				}
				else
				{
					interval64 = 0;
				}

				interval = (UINT)interval64;
				if (interval == 0)
				{
					interval = 1;
				}

				t->CurrentTimerTargetTick = e->Tick;

				// タイマを設定する
				SeSysSetTimer(t->TimerHandle, interval);
			}
		}
	}
	SeUnlock(t->TimerEntryLock);
}
Пример #6
0
// 古い MAC アドレスをリストから削除
void SeEthDeleteOldSenderMacList(SE_ETH *e)
{
	UINT64 now;
	// 引数チェック
	if (e == NULL)
	{
		return;
	}

	now = SeTick64();

	SeLock(e->SenderMacListLock);
	{
		UINT i;
		SE_LIST *o = NULL;

		for (i = 0;i < SE_LIST_NUM(e->SenderMacList);i++)
		{
			SE_ETH_SENDER_MAC *m = SE_LIST_DATA(e->SenderMacList, i);

			if (m->Expires <= now)
			{
				if (o == NULL)
				{
					o = SeNewList(NULL);
				}

				SeAdd(o, m);
			}
		}

		if (o != NULL)
		{
			for (i = 0;i < SE_LIST_NUM(o);i++)
			{
				SE_ETH_SENDER_MAC *m = SE_LIST_DATA(o, i);

				SeDelete(e->SenderMacList, m);

				SeFree(m);
			}

			SeFreeList(o);
		}
	}
	SeUnlock(e->SenderMacListLock);
}
Пример #7
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);
	}
}
Пример #8
0
// タイマのコールバック関数
void SeTimerCallback(SE_HANDLE timer_handle, void *param)
{
	SE_TIMER *t;
	bool invoke_callback = false;
	UINT64 now = 0;
	// 引数チェック
	if (timer_handle == NULL || param == NULL)
	{
		return;
	}

	t = (SE_TIMER *)param;

	SeLock(t->TimerEntryLock);
	{
		UINT i;
		SE_LIST *o = NULL;

		now = SeTick64();

		// 登録されているタイマエントリのうち現在時刻またはそれよりも前に
		// 発動すべきもののリストを取得する
		for (i = 0;i < SE_LIST_NUM(t->TimerEntryList);i++)
		{
			SE_TIMER_ENTRY *e = SE_LIST_DATA(t->TimerEntryList, i);

			if (now >= e->Tick)
			{
				if (o == NULL)
				{
					o = SeNewList(NULL);
				}

				SeAdd(o, e);
			}
		}

		if (o != NULL)
		{
			// 不要になったタイマエントリをリストから削除する
			for (i = 0;i < SE_LIST_NUM(o);i++)
			{
				SE_TIMER_ENTRY *e = SE_LIST_DATA(o, i);

				SeDelete(t->TimerEntryList, e);

				SeFree(e);
			}

			SeFreeList(o);

			t->CurrentTimerTargetTick = 0;

			invoke_callback = true;
		}

		// タイマ調整
		SeTimerAdjust(t);
	}
	SeUnlock(t->TimerEntryLock);

	if (invoke_callback)
	{
		// コールバック関数を呼び出す
		t->TimerCallback(t, now, t->TimerCallbackParam);
	}
}