// スリープ void pro100_sleep(UINT msecs) { UINT64 tick; if (msecs == 0) { return; } tick = SeTick64() + (UINT64)msecs; while (SeTick64() <= tick); }
// 指定した 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; }
// タイマのセット 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); }
// 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); }
// タイマの調整 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); }
// 古い 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); }
// 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); } }
// タイマのコールバック関数 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); } }