/* * Initializes the PDU Router. */ void PduR_Init (const PduR_PBConfigType* ConfigPtr) { //Enter(0); // Make sure the PDU Router is uninitialized. // Otherwise raise an error. if (PduRState != PDUR_UNINIT) { // Raise error and return. PDUR_DET_REPORTERROR(MODULE_ID_PDUR, PDUR_INSTANCE_ID, 0x00, PDUR_E_INVALID_REQUEST); } else if (ConfigPtr == NULL) { PDUR_DET_REPORTERROR(MODULE_ID_PDUR, PDUR_INSTANCE_ID, 0x00, PDUR_E_CONFIG_PTR_INVALID); } else { PduRConfig = ConfigPtr; // Start initialization! DEBUG_PRINT0(DEBUG_LOW,"--Initialization of PDU router--\n"); //uint8 failed = 0; // Initialize buffers. /*if (failed) { // TODO Report PDUR_E_INIT_FAILED to Dem. PduRState = PDUR_REDUCED; DEBUG_PRINT0(DEBUG_LOW,"--Initialization of PDU router failed--\n"); }*/ // The initialization succeeded! PduRState = PDUR_ONLINE; DEBUG_PRINT0(DEBUG_LOW,"--Initialization of PDU router completed --\n"); } }
/***************************************************************************** * DriverEntry() * * この関数のは System がこのドライバをロードするときに呼ばれ、ドライバを * NDIS と関連付け、エントリポイントを登録する。 * * 引数: * DriverObject : ドライバーオブジェクトのポインタ * RegistryPath : ドライバーのレジストリのパス 関連付け * * 返り値: * * NDIS_STATUS * ********************************************************************************/ NDIS_STATUS DriverEntry( IN PVOID DriverObject, IN PVOID RegistryPath) { NDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics; NDIS_STATUS Status; DEBUG_PRINT0(3, "DriverEntry called\n"); NdisZeroMemory(&MiniportCharacteristics, sizeof(NDIS_MINIPORT_CHARACTERISTICS)); /* * ミニポートドライバを NDIS に関連付けし、NdisWrapperHandle を得る。 */ NdisMInitializeWrapper( &NdisWrapperHandle, // OUT PNDIS_HANDLE DriverObject, // IN ドライバーオブジェクト RegistryPath, // IN レジストリパス NULL // IN 必ず NULL ); if(NdisWrapperHandle == NULL){ DEBUG_PRINT0(1, "NdisInitializeWrapper failed\n"); return(STATUS_INVALID_HANDLE); } MiniportCharacteristics.MajorNdisVersion = STE_NDIS_MAJOR_VERSION; // Major Version MiniportCharacteristics.MinorNdisVersion = STE_NDIS_MINOR_VERSION; // Minor Version MiniportCharacteristics.CheckForHangHandler = SteMiniportCheckForHang; MiniportCharacteristics.HaltHandler = SteMiniportHalt; MiniportCharacteristics.InitializeHandler = SteMiniportInitialize; MiniportCharacteristics.QueryInformationHandler = SteMiniportQueryInformation; MiniportCharacteristics.ResetHandler = SteMiniportReset ; MiniportCharacteristics.SetInformationHandler = SteMiniportSetInformation; MiniportCharacteristics.ReturnPacketHandler = SteMiniportReturnPacket; MiniportCharacteristics.SendPacketsHandler = SteMiniportSendPackets; Status = NdisMRegisterMiniport( NdisWrapperHandle, // IN NDIS_HANDLE &MiniportCharacteristics, // IN PNDIS_MINIPORT_CHARACTERISTICS sizeof(NDIS_MINIPORT_CHARACTERISTICS) // IN UINT ); if( Status != NDIS_STATUS_SUCCESS){ DEBUG_PRINT1(1, "NdisMRegisterMiniport failed(Status = 0x%x)\n", Status); NdisTerminateWrapper( NdisWrapperHandle, // IN NDIS_HANDLE NULL ); return(Status); } // グローバルロックを初期化 NdisAllocateSpinLock(&SteGlobalSpinLock); NdisMRegisterUnloadHandler(NdisWrapperHandle, SteMiniportUnload); return(NDIS_STATUS_SUCCESS); }
//Peer_id 为返回对方peer_id; bool parse_handshake_info(const t_byte* pbuf, Sha1Hash &info_hash, PeerID &peer_id, t_byte ext_info[8]) { assert(pbuf != 0); if(pbuf[0] != PROTOCOL_LENGTH) { DEBUG_PRINT0("invalid protocol length\n"); return false; } //DEBUG_PRINT1("%s\n", (const char*)&pbuf[1]); if(memcmp(&pbuf[1], PROTOCOL_STRING, PROTOCOL_LENGTH) == 0) { //DEBUG_PRINT0("invalid protocol string\n"); memcpy(ext_info, &pbuf[20], 8); info_hash.Reset(&pbuf[28]); peer_id.Reset(&pbuf[48]); return true; }else { DEBUG_PRINT0("invalid protocol string\n"); return false; } }
void OutConnValidator::check_connection_handshake() { assert(m_buf.Size() == 68); PeerID remote_peer_id; Sha1Hash info_hash; t_byte ext_info[8]; bool res = parse_handshake_info(m_buf.Data(), info_hash, remote_peer_id, ext_info); if(!res) { DEBUG_PRINT0("parse_handshae_info failed\n"); goto FAILED; } if(info_hash != m_infohash) { DEBUG_PRINT0("response infohash invalid\n"); goto FAILED; } if(remote_peer_id == m_peer_id) { DEBUG_PRINT0("OutConnValidator::response peer id equal to local\n"); goto FAILED; } MsgSpace::PostMessageEx(m_task_id, new NetConnEstablished(m_stream_sock.Duplicate(), LOCAL, remote_peer_id, m_infohash, m_peer_entry, ext_info)); return; FAILED: MsgSpace::PostMessageEx(m_task_id, new NetConnectPeerFailed(m_peer_entry)); }
/*************************************************************************** * SteMiniportSendPackets() * * NDIS Miniport エントリポイント * このドライバにバインドしているプロトコルが、パケットを送信する際に * NDIS によって呼ばれる。 * * 引数: * * MiniportAdapterContext : アダプタコンテキストへのポインタ * PacketArray : 送信するパケット配列 * NumberOfPackets : 上記の配列の長さ * * 返り値: * * 無し * *************************************************************************/ VOID SteMiniportSendPackets( IN NDIS_HANDLE MiniportAdapterContext, IN PPNDIS_PACKET PacketArray, IN UINT NumberOfPackets ) { UINT i; NDIS_STATUS Status; STE_ADAPTER *Adapter; BOOLEAN IsStedRegistered = TRUE; DEBUG_PRINT0(3, "SteMiniportSendPackets called\n"); Adapter = (STE_ADAPTER *) MiniportAdapterContext; // 仮想 NIC デーモンからのイベントオブジェクトが登録されているか // TODO: Adapter 毎の Lock を作成し、EventObject の参照時に // ロックを取得すべき if( Adapter->EventObject == NULL ) { DEBUG_PRINT0(2, "SteMiniportSendPackets: sted is not registerd yet\n"); IsStedRegistered = FALSE; } for( i = 0 ; i < NumberOfPackets ; i++){ if(DebugLevel >= 3) StePrintPacket(PacketArray[i]); if(IsStedRegistered){ Status = StePutQueue(&Adapter->SendQueue, PacketArray[i]); } else { Status = NDIS_STATUS_RESOURCES; } if(Status != NDIS_STATUS_SUCCESS){ // 送信キューが一杯、もしくは仮想 NIC デーモンが未登録のようだ。 NdisMSendComplete( Adapter->MiniportAdapterHandle, //IN NDIS_HANDLE PacketArray[i], //IN PNDIS_PACKET Status //IN NDIS_STATUS // NDIS_STATUS_RESOURCES を返すことになる。 ); Adapter->Oerrors++; continue; } Adapter->Opackets++; /* * 仮想 NIC デーモンにイベント通知 */ KeSetEvent(Adapter->EventObject, 0, FALSE); DEBUG_PRINT0(3, "SteMiniportSendPackets: Notified to Daemon\n"); } return; }
void OutConnValidator::OnInput() { m_ts.Update(); assert(m_buf.Size() < 68); t_byte buf[68]; size_t read_n = 68 - m_buf.Size(); assert(read_n <= 68); int rn = m_stream_sock.Recv(buf, read_n); assert(rn <= 68); if(rn > 0) { m_buf.Insert(buf, rn); assert(m_buf.Size() <= 68); if(m_buf.Size() == 68) { check_connection_handshake(); GetSelector()->RemoveHandler(this); } }else if(rn == -1 && NetGetLastError() == EWOULDBLOCK) { //等待下次 }else { DEBUG_PRINT0("OutConnValidator::OnInput connection abort\n"); //网络连接断开 MsgSpace::PostMessageEx(m_task_id, new NetConnectPeerFailed(m_peer_entry)); GetSelector()->RemoveHandler(this); } }
void OutConnValidator::OnOutput() { m_ts.Update(); assert(m_buf.Size() > 0); int wn = m_stream_sock.Send(m_buf.Data(),m_buf.Size()); if(wn > 0) { m_buf.Erase(wn); if(m_buf.Size() == 0) { Mask(NetSpace::INPUT_MASK|NetSpace::TIMER_MASK); } }else if(wn == -1 && NetGetLastError() == EWOULDBLOCK) { //等待下一次可写 }else { //失败 DEBUG_PRINT0("OutConnValidator::OnOutput() failed\n"); MsgSpace::PostMessageEx(m_task_id, new NetConnectPeerFailed(m_peer_entry)); GetSelector()->RemoveHandler(this); } }
bool PieceManager::GetRequest(std::list<SliceInfo> &slice_list, t_uint32 want_num, const BitField &remote_own_pieces) { assert(want_num > 0); slice_list.clear(); DownloadingPiece* pdown = get_best_downloading(remote_own_pieces); if(pdown == 0) { DEBUG_PRINT0("get_best_downloading failed\n"); return false; } else { for(size_t i = 0; i < want_num; ++i) { SliceInfo si; if(!pdown->GetRequest(si, IsEndGame())) { DEBUG_PRINT1("pdown->GetRequest(si) failed slist.size() == %d\n", slice_list.size()); break; } else { DEBUG_PRINT1("slice_list.size() == %d\n", slice_list.size()); slice_list.push_back(si); } } return (slice_list.size() > 0); } }
bool PieceManager::SliceCompleted(const SliceInfo &slice_info) { StartedPiecesMap::iterator it = m_started_pieces.find(slice_info.piece_idx); if(it == m_started_pieces.end()) return false; DownloadingPiece *pdown = it->second; if(!pdown->RequestCompleted(slice_info)) return false; if(pdown->IsCompleted()) { if(CheckPiece(slice_info.piece_idx)) { t_uint32 pidx = slice_info.piece_idx; assert(m_pieces_info[pidx].state == P_DOWNLOADING); m_pieces_info[pidx].state = P_DONE; t_uint32 pos = m_pos_in_interests[pidx]; assert(pos != NONE_POS); m_pos_in_interests[pidx] = NONE_POS; std::vector<t_uint32> &piece_list = m_interests[m_pieces_info[pidx].have]; assert(!piece_list.empty()); if(pos == piece_list.size() - 1) { piece_list.erase(piece_list.end() - 1); } else { piece_list[pos] = piece_list[piece_list.size() - 1]; m_pos_in_interests[piece_list[pos]] = pos; piece_list.erase(piece_list.end() - 1); } m_bitfield.Set(pidx); //确认此片写入磁盘中(因为此片也许会在cache中) m_storage.FlushPiece(pidx); if(!m_is_endgame && need_enter_endgame()) { m_is_endgame = true; DEBUG_PRINT0("ENTER END GAME MODE!!!!!!!!!!!!!!!\n"); } } else { DEBUG_PRINT1("Piece index == %d hash check failed\n", slice_info.piece_idx); ::MessageBox(0, TEXT("Piece index == hash check failed\n"), 0,0); t_uint32 pidx = slice_info.piece_idx; assert(m_pieces_info[pidx].state == P_DOWNLOADING); m_pieces_info[pidx].state = P_FREE; } m_started_pieces.erase(it); delete pdown; } return true; }
/******************************************************************************* * SteMiniportCheckForHang() * * NDIS Miniport エントリポイント * NIC の状態を報告するためによばれ、またデバイスドライバの反応の有無を * モニターするために呼ばれる。 * * 引数: * * MiniportAdapterContext : アダプタのポインタ * * 返り値: * * TRUE NDIS がドライバの MiniportReset を呼び出した * FALSE 正常 * * Note: * CheckForHang ハンドラはタイマー DPC のコンテキストで呼び出されます。 * この利点は、spinlock を確保/解放するときに得られます。 * ******************************************************************************/ BOOLEAN SteMiniportCheckForHang( IN NDIS_HANDLE MiniportAdapterContext ) { // あまりに冗長なので、必要なデバッグレベルを上げる DEBUG_PRINT0(4, "SteMiniportCheckForHang called\n"); return(FALSE); }
/*************************************************************************** * SteMiniportUnload() * * NDIS Miniport エントリポイント * アンドロードハンドラは DriverEntry の中で獲得されたリソースを解放 * するために、ドライバのアンロード中に呼ばれる。 * このハンドラは NdisMRegisterUnloadHandler を通して登録される。 * * ** 注意** * MiniportUnload() は MiniportHalt() とは違う!! * MiniportUload() はより広域のスコープを持つのに対し、MiniportHalt は * 特定の miniport ドライバインスタンスに限定される。 * * 引数: * * DriverObject : 使ってない * * 返り値: * * None * *************************************************************************/ VOID SteMiniportUnload( IN PDRIVER_OBJECT DriverObject ) { // DriverEntry() でリソースを確保していないので // 何もしなくてよいものか? DEBUG_PRINT0(3, "SteMiniportUnload called\n"); return; }
void InConnValidator::OnTimer() { if(m_ts.ElapsedMillisecond() >= VALIDATOR_TIMEOUT) { //MsgSpace::PostMessageEx(m_task_id, new NetConnectPeerFailed(m_peer_entry)); DEBUG_PRINT0("accepted peer connection timeout\n"); GetSelector()->RemoveHandler(this); } }
/*************************************************************************** * SteMiniportSetInformation() * * NDIS エントリポイント * OID の値を問い合わせるために NDIS によって呼ばれる。 * * 引数: * * MiniportAdapterContext : Adapter 構造体のポインタ * Oid : この問い合わせの OID * InformationBuffer : 情報のためのバッファー * InformationBufferLength : バッファのサイズ * BytesRead : いくつの情報が読まれたか * BytesNeeded : バッファが少ない場合に必要なサイズを指示 * * 返り値: * * 正常時 : NDIS_STATUS_SUCCESS * *******************************************************************************/ NDIS_STATUS SteMiniportSetInformation( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesRead, OUT PULONG BytesNeeded) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; STE_ADAPTER *Adapter; ULONG NewFilter; DEBUG_PRINT0(3, "SteMiniportSetInformation called\n"); Adapter = (STE_ADAPTER *)MiniportAdapterContext; DEBUG_PRINT1(3, "SteMiniportSetInformation: Oid = 0x%x\n", Oid); // 必須 OID のセット要求だけを実装 // TODO: // 今のところ、パケットフィルター以外は実際にはセットしていないので、セットできるようにする。 // switch(Oid) { // 一般的な特性 case OID_GEN_CURRENT_PACKET_FILTER: if(InformationBufferLength != sizeof(ULONG)){ *BytesNeeded = sizeof(ULONG); *BytesRead = 0; Status = NDIS_STATUS_INVALID_LENGTH; break; } NewFilter = *(ULONG *)InformationBuffer; Adapter->PacketFilter = NewFilter; *BytesRead = InformationBufferLength; DEBUG_PRINT1(3,"SteMiniportSetInformation: New filter = 0x%x (See ntddndis.h)\n", NewFilter); break; case OID_GEN_CURRENT_LOOKAHEAD: *BytesRead = InformationBufferLength; break; case OID_GEN_PROTOCOL_OPTIONS: *BytesRead = InformationBufferLength; break; // Ethernet の特性 case OID_802_3_MULTICAST_LIST: *BytesRead = InformationBufferLength; break; default: Status = NDIS_STATUS_INVALID_OID; break; } return(Status); }
bool InConnValidator::check_connection_handshake() { assert(m_buf.Size() == 68); PeerID remote_peer_id; if(parse_handshake_info(m_buf.Data(), m_infohash, remote_peer_id, m_ext_info)) { DownloaderInfo dl_info; if(m_res_manager.GetDownloaderRecorder().GetRecord(m_infohash, dl_info)) { if(dl_info.peer_id == remote_peer_id) { DEBUG_PRINT0("InConnValidator::remote peer id equal to local\n"); NetSpace::InetAddress addr; m_stream_sock.GetLocalAddr(addr);//因为这个很可能是自己,反正无论如何也要band m_res_manager.GetIPFilter().BandAddress(addr.Str(), addr.Port()); DEBUG_PRINT2("InConnValidator::check_connection_handshake : band peer entry == %s:%d\n", addr.Str().c_str(), addr.Port()); return false; } m_task_id = dl_info.task_id; m_infohash = dl_info.info_hash; m_peer_id = remote_peer_id; m_buf.Clear(); m_buf.Insert(&build_hand_shake(m_infohash, dl_info.peer_id)[0], 68); assert(m_buf.Size() == 68); return true; }else { DEBUG_PRINT0("unknow infohash\n"); return false; } }else { DEBUG_PRINT0("parse_handshake_info failed\n"); return false; } }
/**************************************************************************** * SteMiniportShutdown() * * NDIS エントリポイント * システムのシャットダウンや、予期せぬシステムエラー時に、NIC を初期状態 * に戻すために呼ばれる。ここではメモリリソースを解放したり、パケットの転 * 送完了を待ったりはしない * * 引数: * * ShutdownContext : STE_ADAPTER 構造体のポインタ * * 戻り値: * * 無し * ***************************************************************************/ VOID SteMiniportShutdown( IN PVOID ShutdownContext ) { STE_ADAPTER *Adapter; DEBUG_PRINT0(3, "SteMiniportShutdown called\n"); Adapter = (STE_ADAPTER *)ShutdownContext; return; }
/****************************************************************************** * SteMiniportReset() * * NDIS Miniport エントリポイント * 以下の条件のとき NIC がハングしていると判断しドライバーのソフトステート * をリセットするために呼ばれる。 * * 1) SteMiniportCheckForHang() が TRUE を返してきた * 2) 未処理の送信パケットを検出した(シリアライズドドライバのみ) * 3) 一定時間内に完了することができなかった未処理の要求があった * * この関数の中では以下を行う * * 1) キューイングされている送信パケットの処理をやめ、NDIS_STATUS_REQUEST_ABORTED を返す。 * 2) 上位に通知した全てのパケットがリターンしてきたか確認する。 * 3) 上記2つに問題がありリセット処理をただちに完了できない場合、ResetTimer をセットし、 * NDIS_STATUS_PENDING を返す。 * * 引数: * * AddressingReset : マルチキャストや、MAC アドレス、lookahead サイズ * に変更があった場合にはここを TRUE にしなければならない。 * * MiniportAdapterContext : STE_ADAPTER 構造体のポインタ * * * 返り値: * * NDIS_STATUS * **************************************************************************/ NDIS_STATUS SteMiniportReset( OUT PBOOLEAN AddressingReset, IN NDIS_HANDLE MiniportAdapterContext ) { NDIS_STATUS Status; STE_ADAPTER *Adapter; NDIS_PACKET *Packet = NULL; DEBUG_PRINT0(3, "SteMiniportReset called\n"); Adapter = (STE_ADAPTER *)MiniportAdapterContext; // MAC アドレス、マルチキャストアドレスの変更はない!?ときめつけて FALSE を返す *AddressingReset = FALSE; Status = NDIS_STATUS_REQUEST_ABORTED; // 送信キューに入っているパケットを処理する while (SteGetQueue(&Adapter->SendQueue, &Packet) == NDIS_STATUS_SUCCESS) { NdisMSendComplete( Adapter->MiniportAdapterHandle, //IN NDIS_HANDLE Packet, //IN PNDIS_PACKET Status //IN NDIS_STATUS ); } // 受信キューに入っているパケットを処理する while (SteGetQueue(&Adapter->RecvQueue, &Packet) == NDIS_STATUS_SUCCESS) { SteFreeRecvPacket(Adapter, Packet); } // これが終われば、全ての受信パケットがフリーされているはず。 // 後は上位プロトコルに通知済みでまだ戻ってきていないパケットがあるかどうかを // 確認する。 if (Adapter->RecvIndicatedPackets > 0) { // まだ戻ってきてないパケットがあるようだ。 // リセットタイマーをセットして、後ほど SteResetTimerFunc() から // NdisMResetComplete() を呼んでリセットを完了することにする。 NdisSetTimer(&Adapter->ResetTimer, 300); Status = NDIS_STATUS_PENDING; } else { // リセット操作完了! Status = NDIS_STATUS_SUCCESS; } return(Status); }
/************************************************************************** * SteMiniportReturnPacket() * * NDIS Miniport エントリポイント * このドライバが上位プロトコルに通知したパケットが、プロトコルによって * 処理が終了した場合に NDIS によって呼ばれる。 * * 引数: * * MiniportAdapterContext : ADAPTER 構造体のポインタ * Packet : リターンされてきたパケット * * 返り値: * * 無し * **************************************************************************/ VOID SteMiniportReturnPacket( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet) { STE_ADAPTER *Adapter; Adapter = (STE_ADAPTER *)MiniportAdapterContext; DEBUG_PRINT0(3, "SteMiniportReturnPacket called\n"); SteFreeRecvPacket( Adapter, //IN STE_ADAPTER Packet //IN NDIS_PACKET ); NdisInterlockedDecrement( (PLONG)&Adapter->RecvIndicatedPackets //IN PLONG ); return; }
void InConnValidator::OnInput() { m_ts.Update(); t_byte buf[68]; int read_len = 68 - m_buf.Size(); assert(read_len <= 68); int rn = m_stream_sock.Recv(buf, read_len); if(rn > 0) { m_buf.Insert(buf, rn); assert(m_buf.Size() <= 68); if(m_buf.Size() == 68) { if(!check_connection_handshake()) { //DEBUG_PRINT0("check_connection_handshake failed\n"); GetSelector()->RemoveHandler(this); return; }else { assert(m_buf.Size() == 68); Mask(NetSpace::OUTPUT_MASK|NetSpace::TIMER_MASK); } } }else if(rn == -1 && NetGetLastError() == EWOULDBLOCK) { //等待下次; }else { DEBUG_PRINT0("accepted peer connection abort\n"); GetSelector()->RemoveHandler(this); } }
void InConnValidator::OnOutput() { m_ts.Update(); int wn = m_stream_sock.Send(m_buf.Data(), m_buf.Size()); if(wn > 0) { m_buf.Erase(wn); if(m_buf.IsEmpty()) { MsgSpace::PostMessageEx(m_task_id, new NetConnEstablished(m_stream_sock.Duplicate(), REMOTE, m_peer_id, m_infohash, m_peer_entry, m_ext_info)); GetSelector()->RemoveHandler(this); } }else if(wn == -1 && NetGetLastError() == EWOULDBLOCK) { //等待下次; }else { DEBUG_PRINT0("accepted peer connection abort\n"); GetSelector()->RemoveHandler(this); } }
void Com_Init(const Com_ConfigType *config ) { uint8 failure = 0; uint32 firstTimeout; uint8 endiannessByte; uint16 i; uint16 j; //ComIPdu_type *IPdu; //Com_Arc_IPdu_type *Arc_IPdu; const ComSignal_type *Signal; const ComGroupSignal_type *GroupSignal; DEBUG_PRINT0(DEBUG_LOW, "--Initialization of COM--\n"); ComConfig = config; //lint --e(928) PC-Lint exception Misra 11.4, Must be like this. /tojo endiannessByte = *(const uint8 *)&endianness_test; if ( endiannessByte == 0xef ) { Com_SystemEndianness = COM_LITTLE_ENDIAN; } else if ( endiannessByte == 0xde ) { Com_SystemEndianness = COM_BIG_ENDIAN; } else { // No other endianness supported //lint --e(506) PC-Lint exception Misra 13.7, 14.1, Allow boolean to always be false. AR_ASSERT(0); } // Initialize each IPdu #if 0 //F*****g bad code as always need a dummy ComIPdu config with Com_Arc_EOL equal to TRUE. for (i = 0; !ComConfig->ComIPdu[i].Com_Arc_EOL; i++) { #else /*So I changed it to ...*/ for(i = 0;i < COM_N_IPDUS;i++){ #endif const ComIPdu_type *IPdu = GET_IPdu(i); Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(i); Arc_IPdu->Com_Arc_DynSignalLength = 0; if (i >= COM_N_IPDUS) { DET_REPORTERROR(COM_MODULE_ID, COM_INSTANCE_ID, 0x01, COM_E_TOO_MANY_IPDU); failure = 1; break; } // If this is a TX and cyclic IPdu, configure the first deadline. if ( (IPdu->ComIPduDirection == SEND) && ( (IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeMode == PERIODIC) || (IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeMode == MIXED) )) { //IPdu->Com_Arc_TxIPduTimers.ComTxModeTimePeriodTimer = IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeTimeOffsetFactor; Arc_IPdu->Com_Arc_TxIPduTimers.ComTxModeTimePeriodTimer = IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeTimeOffsetFactor; } // Reset firstTimeout. firstTimeout = 0xffffffffu; // Initialize the memory with the default value. if (IPdu->ComIPduDirection == SEND) { memset((void *)IPdu->ComIPduDataPtr, IPdu->ComTxIPdu.ComTxIPduUnusedAreasDefault, IPdu->ComIPduSize); } // For each signal in this PDU. //Arc_IPdu->NComIPduSignalRef = 0; for (j = 0; (IPdu->ComIPduSignalRef != NULL) && (IPdu->ComIPduSignalRef[j] != NULL) ; j++) { Com_Arc_Signal_type * Arc_Signal; Signal = IPdu->ComIPduSignalRef[j]; Arc_Signal = GET_ArcSignal(Signal->ComHandleId); // Configure signal deadline monitoring if used. if (Signal->ComTimeoutFactor > 0) { if (Signal->ComSignalArcUseUpdateBit) { // This signal uses an update bit, and hence has its own deadline monitoring. Arc_Signal->Com_Arc_DeadlineCounter = Signal->ComFirstTimeoutFactor; // Configure the deadline counter } else { // This signal does not use an update bit, and should therefore use per I-PDU deadline monitoring. if (firstTimeout > Signal->ComFirstTimeoutFactor) { firstTimeout = Signal->ComFirstTimeoutFactor; } } } // Clear update bits if (Signal->ComSignalArcUseUpdateBit) { CLEARBIT(IPdu->ComIPduDataPtr, Signal->ComUpdateBitPosition); } // If this signal is a signal group if (Signal->Com_Arc_IsSignalGroup) { uint8 h; // For each group signal of this signal group. for(h = 0; Signal->ComGroupSignal[h] != NULL; h++) { Com_Arc_GroupSignal_type *Arc_GroupSignal; GroupSignal = Signal->ComGroupSignal[h]; Arc_GroupSignal = GET_ArcGroupSignal(GroupSignal->ComHandleId); // Set pointer to shadow buffer Arc_GroupSignal->Com_Arc_ShadowBuffer = (void *)Signal->Com_Arc_ShadowBuffer; // Initialize group signal data. Com_WriteGroupSignalDataToPdu(Signal->ComHandleId, GroupSignal->ComHandleId, GroupSignal->ComSignalInitValue); } } else { // Initialize signal data. Com_WriteSignalDataToPdu(Signal->ComHandleId, Signal->ComSignalInitValue); } } if (IPdu->ComIPduDirection == RECEIVE && IPdu->ComIPduSignalProcessing == DEFERRED) { // Copy the initialized pdu to deferred buffer memcpy(IPdu->ComIPduDeferredDataPtr,IPdu->ComIPduDataPtr,IPdu->ComIPduSize); } // Configure per I-PDU based deadline monitoring. for (j = 0; (IPdu->ComIPduSignalRef != NULL) && (IPdu->ComIPduSignalRef[j] != NULL); j++) { Com_Arc_Signal_type * Arc_Signal; Signal = IPdu->ComIPduSignalRef[j]; Arc_Signal = GET_ArcSignal(Signal->ComHandleId); if ( (Signal->ComTimeoutFactor > 0) && (!Signal->ComSignalArcUseUpdateBit) ) { Arc_Signal->Com_Arc_DeadlineCounter = firstTimeout; } } } for (i = 0; i < COM_N_IPDUS; i++) { Com_BufferPduState[i].currentPosition = 0; Com_BufferPduState[i].locked = FALSE; } // An error occurred. if (failure) { DEBUG_PRINT0(DEBUG_LOW, "--Initialization of COM failed--\n"); //DET_REPORTERROR(COM_MODULE_ID, COM_INSTANCE_ID, 0x01, COM_E_INVALID_FILTER_CONFIGURATION); } else { DEBUG_PRINT0(DEBUG_LOW, "--Initialization of COM completed--\n"); } } void Com_DeInit( void ) { } void Com_IpduGroupStart(Com_PduGroupIdType IpduGroupId,boolean Initialize) { uint16 i; (void)Initialize; // Nothing to be done. This is just to avoid Lint warning. #if 0 for (i = 0; !ComConfig->ComIPdu[i].Com_Arc_EOL; i++) { #else /*So I changed it to ...*/ for(i = 0;i < COM_N_IPDUS;i++){ #endif if (ComConfig->ComIPdu[i].ComIPduGroupRef == IpduGroupId) { Com_Arc_Config.ComIPdu[i].Com_Arc_IpduStarted = 1; } } } void Com_IpduGroupStop(Com_PduGroupIdType IpduGroupId) { uint16 i; #if 0 for (i = 0; !ComConfig->ComIPdu[i].Com_Arc_EOL; i++) { #else /*So I changed it to ...*/ for(i = 0;i < COM_N_IPDUS;i++){ #endif if (ComConfig->ComIPdu[i].ComIPduGroupRef == IpduGroupId) { Com_Arc_Config.ComIPdu[i].Com_Arc_IpduStarted = 0; } } } /** * * @param PduId * @param PduInfoPtr * @param RetryInfoPtr not supported * @param TxDataCntPtr * @return */ BufReq_ReturnType Com_CopyTxData(PduIdType PduId, PduInfoType* PduInfoPtr, RetryInfoType* RetryInfoPtr, PduLengthType* TxDataCntPtr) { imask_t state; BufReq_ReturnType r = BUFREQ_OK; const ComIPdu_type *IPdu = GET_IPdu(PduId); boolean dirOk = ComConfig->ComIPdu[PduId].ComIPduDirection == SEND; boolean sizeOk; (void)RetryInfoPtr; // get rid of compiler warning Irq_Save(state); sizeOk = IPdu->ComIPduSize >= Com_BufferPduState[PduId].currentPosition + PduInfoPtr->SduLength; Com_BufferPduState[PduId].locked = TRUE; if (dirOk && sizeOk) { void* source = (void *)(IPdu->ComIPduDataPtr); memcpy((void *)PduInfoPtr->SduDataPtr,(void *)((uint8*)source + Com_BufferPduState[PduId].currentPosition), PduInfoPtr->SduLength); Com_BufferPduState[PduId].currentPosition += PduInfoPtr->SduLength; *TxDataCntPtr = IPdu->ComIPduSize - Com_BufferPduState[PduId].currentPosition; } else { r = BUFREQ_NOT_OK; } Irq_Restore(state); return r; }
/************************************************************************ * SteMiniportHalt() * * NDIS Miniport エントリポイント * Halt ハンドラは NDIS が PNP マネージャから IRP_MN_STOP_DEVICE、 * IRP_MN_SUPRISE_REMOVE、IRP_MN_REMOVE_DEVICE 要求を受け取ったと * きに呼ばれる。SteMiniportInitialize で確保された全てのリソース * を解放する。(特定のミニポートドライバインスタンスに限定される) * * o 全ての I/O リソースを free し、unmap する。 * o NdisMRegisterAdapterShutdownHandler によって登録されたシャッ * トダウンハンドラを登録解除する。 * o NdisMCancelTimer を呼んでキューイングされているコールバック * ルーチンをキャンセルする。 * o 全ての未処理の受信パケットが処理され終わるまで待つ。 * * 引数: * MiniportAdapterContext アダプタへのポインタ * * 返り値: * * 無し ********************************************************************/ VOID SteMiniportHalt( IN NDIS_HANDLE MiniportAdapterContext ) { STE_ADAPTER *Adapter; BOOLEAN bTimerCancelled; INT i; DEBUG_PRINT0(3, "SteMiniportHalt called\n"); Adapter = (STE_ADAPTER *) MiniportAdapterContext; SteMiniportShutdown( (PVOID) Adapter //IN PVOID ); // // NdisMCancelTimer を呼んでキューイングされているコールバック // ルーチンをキャンセルする。 // // ReceiveIndication タイマーをキャンセル NdisCancelTimer( &Adapter->RecvTimer, // IN PNDIS_TIMER &bTimerCancelled // OUT PBOOLEAN ); // Reset タイマーをキャンセル NdisCancelTimer( &Adapter->ResetTimer, // IN PNDIS_TIMER &bTimerCancelled // OUT PBOOLEAN ); if (bTimerCancelled == TRUE){ // キャンセルされたコールバックルーチンがあったようだ。 // 受信キューに残っている Packet はこの後の SteDeleteAdapter() // によって Free されるので、ここでは何もしない。 } // NdisMRegisterAdapterShutdownHandler によって登録された // シャットダウンハンドラを登録解除する。 NdisMDeregisterAdapterShutdownHandler( Adapter->MiniportAdapterHandle // IN NDIS_HANDLE ); // // 仮想 NIC デーモンからの IOCT/READ/WRITE 用のデバイスの登録を解除する。 // SteDeregisterDevice(Adapter); // // 処理中の受信通知済みパケットがないかどうかチェックする。 // 1 秒おきに、STE_MAX_WAIT_FOR_RECVINDICATE(=5)回確認し、 // RecvIndicatedPackets が 0 にならないようであれば、 // なにか問題があったと考え無視してリソースの開放に進む。 // for ( i = 0 ; i < STE_MAX_WAIT_FOR_RECVINDICATE ; i++){ if (Adapter->RecvIndicatedPackets == 0) { break; } NdisMSleep(1000); } // // Adapter を削除する。このなかで、Adapter の為に確保されたリソースの // 開放も(Packet や、Buffer)行われる。 // SteDeleteAdapter(Adapter); return; }
/************************************************************************* * SteMiniportinitialize() * * NDIS エントリポイント * ネットワーク I/O 操作のために NIC ドライバがネットワーク I/O 操作を * するために必要なリソースを確保する。 * * 引数: * * OpenErrorStatus OUT PNDIS_STATUS * SelectedMediumIndex OUT PUINT * MediumArray IN PNDIS_MEDIUM * MediumArraySize IN UINT * MiniportAdapterHandle IN NDIS_HANDLE * WrapperConfigurationContext IN NDIS_HANDLE * * 返り値: * * 正常時: NDIS_STATUS_SUCCESS * *************************************************************************/ NDIS_STATUS SteMiniportInitialize( OUT PNDIS_STATUS OpenErrorStatus, OUT PUINT SelectedMediumIndex, IN PNDIS_MEDIUM MediumArray, IN UINT MediumArraySize, IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_HANDLE WrapperConfigurationContext ) { UINT i; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; STE_ADAPTER *Adapter = NULL; BOOLEAN MediaFound = FALSE; DEBUG_PRINT0(3, "SteMiniportInitialize called\n"); *SelectedMediumIndex = 0; for ( i = 0 ; i < MediumArraySize ; i++){ if (MediumArray[i] == NdisMedium802_3){ *SelectedMediumIndex = i; MediaFound = TRUE; break; } } // 途中で break するためだけの Do-While 文 do { if(!MediaFound){ // 上記の for 文で見つけられなかったようだ DEBUG_PRINT0(1, "SteMiniportInitialize: No Media much\n"); Status = NDIS_STATUS_UNSUPPORTED_MEDIA; break; } // // Adapter を確保し、初期化する // if ((Status = SteCreateAdapter(&Adapter)) != NDIS_STATUS_SUCCESS){ DEBUG_PRINT0(1, "SteMiniportInitialize: Can't allocate memory for STE_ADAPTER\n"); Status = NDIS_STATUS_RESOURCES; break; } DEBUG_PRINT1(3, "SteMiniportInitialize: Adapter = 0x%p\n", Adapter); Adapter->MiniportAdapterHandle = MiniportAdapterHandle; // // Registory を読む処理。...省略。 // NdisOpenConfiguration(); // NdisReadConfiguration(); // // NIC のためのハードウェアリソースのリストを得る。...省略。 // NdisMQueryAdapterResources() // // // NDIS に NIC の情報を伝える。 // かならず NdisXxx 関数を呼び出すより前に、以下の NdisMSetAttributesEx // を呼び出さなければならない。 // NdisMSetAttributesEx( MiniportAdapterHandle, //IN NDIS_HANDLE (NDIS_HANDLE) Adapter, //IN NDIS_HANDLE 0, //IN UINT NDIS_ATTRIBUTE_DESERIALIZE, //IN ULONG Deserialized ミニポートドライバ NdisInterfaceInternal //IN NDIS_INTERFACE_TYPE ); // // NDIS 5.0 の場合はかならず SHUTDOWN_HANDLER を登録しなければならない。 // NdisMRegisterAdapterShutdownHandler( MiniportAdapterHandle, // IN NDIS_HANDLE (PVOID) Adapter, // IN PVOID (ADAPTER_SHUTDOWN_HANDLER) SteMiniportShutdown // IN ADAPTER_SHUTDOWN_HANDLER ); // // 仮想 NIC デーモンからの IOCT/ReadFile/WriteFile 用の // デバイスを作成し、Dispatch ルーチンを登録する。 // SteRegisterDevice(Adapter); // // SteRecvTimerFunc() を呼ぶためのタイマーオブジェクトを初期化 // NdisInitializeTimer( &Adapter->RecvTimer, //IN OUT PNDIS_TIMER SteRecvTimerFunc, //IN PNDIS_TIMER_FUNCTION (PVOID)Adapter //IN PVOID ); // // SteResetTimerFunc() を呼ぶためのタイマーオブジェクトを初期化 // NdisInitializeTimer( &Adapter->ResetTimer, //IN OUT PNDIS_TIMER SteResetTimerFunc, //IN PNDIS_TIMER_FUNCTION (PVOID)Adapter //IN PVOID ); } while (FALSE); return(Status); }
/************************************************************************ * SteMiniportQueryInformation() * * NDIS エントリポイント * OID の値を問い合わせるために NDIS によって呼ばれる。 * * 引数: * * MiniportAdapterContext : STE_ADAPTER 構造体のポインタ * Oid : この問い合わせの OID * InformationBuffer : 情報のためのバッファー * InformationBufferLength : バッファのサイズ * BytesWritten : いくつの情報が記述されたか * BytesNeeded : バッファが少ない場合に必要なサイズを指示 * * 返り値: * * 正常時 : NDIS_STATUS_SUCCESS * ************************************************************************/ NDIS_STATUS SteMiniportQueryInformation( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesWritten, OUT PULONG BytesNeeded ) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; STE_ADAPTER *Adapter; PVOID Information = NULL; // 提供する情報へのポインタ ULONG InformationLength = 0; // 提供する情報の長さ ULONG ulTemp; // 整数値の情報のための領域(マクロ内で利用) CHAR VendorName[] = STE_VENDOR_NAME; // ベンダー名 // あまりに冗長なので、必要なデバッグレベルを上げる DEBUG_PRINT0(4, "SteMiniportQueryInformation called\n"); Adapter = (STE_ADAPTER *)MiniportAdapterContext; DEBUG_PRINT1(4, "SteMiniportQueryInformation: Oid = 0x%x\n", Oid); switch(Oid) { // 一般的な特性 (22個) case OID_GEN_SUPPORTED_LIST: //サポートされる OID のリスト SET_INFORMATION_BY_POINTER(sizeof(STESupportedList), &STESupportedList); case OID_GEN_HARDWARE_STATUS: // ハードウェアステータス SET_INFORMATION_BY_VALUE(sizeof(NDIS_HARDWARE_STATUS), NdisHardwareStatusReady); case OID_GEN_MEDIA_SUPPORTED: // NIC がサポートできる(が必須ではない)メディアタイプ case OID_GEN_MEDIA_IN_USE: // NIC が現在使っている完全なメディアタイプのリスト SET_INFORMATION_BY_VALUE(sizeof(NDIS_MEDIUM), NdisMedium802_3); case OID_GEN_MAXIMUM_LOOKAHEAD: // NIC が lookahead データとして提供できる最大バイト数 case OID_GEN_MAXIMUM_FRAME_SIZE: // NIC がサポートする、ヘッダを抜いたネットワークパケットサイズ SET_INFORMATION_BY_VALUE(sizeof(ULONG), ETHERMTU); case OID_GEN_LINK_SPEED: //NIC がサポートする最大スピード SET_INFORMATION_BY_VALUE(sizeof(ULONG), ETHERLINKSPEED); case OID_GEN_TRANSMIT_BUFFER_SPACE: // NIC 上の送信用のメモリの総量 // TODO: これでいいのか? SET_INFORMATION_BY_VALUE(sizeof(ULONG), ETHERMTU); case OID_GEN_RECEIVE_BUFFER_SPACE: // NIC 上の受信用のメモリの総量 // TODO: これでいいのか? SET_INFORMATION_BY_VALUE(sizeof(ULONG), ETHERMTU); case OID_GEN_TRANSMIT_BLOCK_SIZE: // NIC がサポートする送信用のネットワークパケットサイズ SET_INFORMATION_BY_VALUE(sizeof(ULONG), ETHERMAX); case OID_GEN_RECEIVE_BLOCK_SIZE: // NIC がサポートする受信用のネットワークパケットサイズ SET_INFORMATION_BY_VALUE(sizeof(ULONG), ETHERMAX); case OID_GEN_VENDOR_ID: // IEEE に登録してあるベンダーコード SET_INFORMATION_BY_VALUE(sizeof(ULONG), 0xFFFFFF); case OID_GEN_VENDOR_DESCRIPTION: // NIC のベンダー名 SET_INFORMATION_BY_POINTER(sizeof(VendorName), VendorName); case OID_GEN_VENDOR_DRIVER_VERSION: // ドライバーのバージョン SET_INFORMATION_BY_VALUE(sizeof(ULONG), STE_DRIVER_VERSION); case OID_GEN_CURRENT_PACKET_FILTER: // プロトコルが NIC から受け取るパケットのタイプ SET_INFORMATION_BY_VALUE(sizeof(ULONG), Adapter->PacketFilter); case OID_GEN_CURRENT_LOOKAHEAD: // 現在の lookahead のバイト数 SET_INFORMATION_BY_VALUE(sizeof(ULONG), ETHERMTU); case OID_GEN_DRIVER_VERSION: // NDIS のバージョン SET_INFORMATION_BY_VALUE(sizeof(USHORT), STE_NDIS_VERSION); case OID_GEN_MAXIMUM_TOTAL_SIZE: // NIC がサポートするネットワークパケットサイズ SET_INFORMATION_BY_VALUE(sizeof(ULONG), ETHERMAX); // case OID_GEN_PROTOCOL_OPTIONS: // オプションのプロトコルフラグ。Set のみ必須 case OID_GEN_MAC_OPTIONS: // 追加の NIC のプロパティを定義したビットマスク SET_INFORMATION_BY_VALUE(sizeof(ULONG), NDIS_MAC_OPTION_NO_LOOPBACK | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA); case OID_GEN_MEDIA_CONNECT_STATUS: // NIC 上の connection 状態 // TODO: 状態を確認し、NdisMediaStateDisconnected を返すようにする SET_INFORMATION_BY_VALUE(sizeof(ULONG), NdisMediaStateConnected); case OID_GEN_MAXIMUM_SEND_PACKETS: // 一回のリクエストで受けられるパケットの最大数 SET_INFORMATION_BY_VALUE(sizeof(ULONG), STE_MAX_SEND_PACKETS); // 一般的な統計情報 (5個) case OID_GEN_XMIT_OK: // 正常に送信できたフレーム数 SET_INFORMATION_BY_VALUE(sizeof(ULONG), Adapter->Opackets); case OID_GEN_RCV_OK: // 正常に受信できたフレーム数 SET_INFORMATION_BY_VALUE(sizeof(ULONG), Adapter->Ipackets); case OID_GEN_XMIT_ERROR: // 送信できなかった(もしくはエラーになった)フレーム数 SET_INFORMATION_BY_VALUE(sizeof(ULONG), Adapter->Oerrors); case OID_GEN_RCV_ERROR: // 受信できなかった(もしくはエラーになった)フレーム数 SET_INFORMATION_BY_VALUE(sizeof(ULONG), Adapter->Ierrors); case OID_GEN_RCV_NO_BUFFER: // バッファ不足のために受信できなかったフレーム数 SET_INFORMATION_BY_VALUE(sizeof(ULONG), Adapter->NoResources); // Ethernet 用の特性 (4個) case OID_802_3_PERMANENT_ADDRESS: // ハードウェアに書かれている MAC アドレス case OID_802_3_CURRENT_ADDRESS: // NIC の現在の MAC アドレス SET_INFORMATION_BY_POINTER(ETHERADDRL, Adapter->EthernetAddress); case OID_802_3_MULTICAST_LIST: // 現在のマルチキャストパケットのアドレスリスト // TODO: マルチキャストリストをセットする。 // 今のところ 0 を返す SET_INFORMATION_BY_VALUE(ETHERADDRL, 0); case OID_802_3_MAXIMUM_LIST_SIZE: // NIC ドライバが管理できる最大のマルチキャストアドレスの数 SET_INFORMATION_BY_VALUE(sizeof(ULONG), STE_MAX_MCAST_LIST); // Ethernet 用統計情報 (3個) case OID_802_3_RCV_ERROR_ALIGNMENT: // アライメントエラーの受信フレーム数 SET_INFORMATION_BY_VALUE(sizeof(ULONG), Adapter->AlignErrors); case OID_802_3_XMIT_ONE_COLLISION: // コリジョンが 1 回発生した送信フレーム数 SET_INFORMATION_BY_VALUE(sizeof(ULONG), Adapter->OneCollisions); case OID_802_3_XMIT_MORE_COLLISIONS: // コリジョンが 1 回以上発生した送信フレーム数 SET_INFORMATION_BY_VALUE(sizeof(ULONG), Adapter->Collisions); default: Status = NDIS_STATUS_NOT_SUPPORTED; break; } if(Information != NULL) { NdisMoveMemory(InformationBuffer, Information, InformationLength); *BytesWritten = InformationLength; } else if(InformationLength > 0) { // バッファが小さい場合は、必要なサイズを通知する。 *BytesNeeded = InformationLength; Status = NDIS_STATUS_BUFFER_TOO_SHORT; } return(Status); }