/*++ Copyright (c) 1998-1999 Microsoft Corporation Module Name: util.c Abstract: Utility functions for ARP1394. Revision History: Who When What -------- -------- ---------------------------------------------- josephj 01-05-99 Created Notes: --*/ #include // // File-specific debugging defaults. // #define TM_CURRENT TM_UT //========================================================================= // L O C A L P R O T O T Y P E S //========================================================================= VOID arpTaskDelete ( PRM_OBJECT_HEADER pObj, PRM_STACK_RECORD psr ); // // TODO: make these globals constant data. // // ArpTasks_StaticInfo contains static information about // objects of type ARP1394_TASK; // RM_STATIC_OBJECT_INFO ArpTasks_StaticInfo = { 0, // TypeUID 0, // TypeFlags "ARP1394 Task", // TypeName 0, // Timeout NULL, // pfnCreate arpTaskDelete, // pfnDelete NULL, // LockVerifier 0, // length of resource table NULL // Resource Table }; VOID arpTaskDelete ( PRM_OBJECT_HEADER pObj, PRM_STACK_RECORD psr ) /*++ Routine Description: Free an object of type ARP1394_TASK. Arguments: pHdr - Actually a pointer to the ARP1394_TASK to be deleted. --*/ { TASK_BACKUP* pTask= (TASK_BACKUP*)pObj; if (CHECK_TASK_IS_BACKUP(&pTask->Hdr) == TRUE) { arpReturnBackupTask((ARP1394_TASK*)pTask); } else { ARP_FREE(pObj); } } VOID arpObjectDelete ( PRM_OBJECT_HEADER pObj, PRM_STACK_RECORD psr ) /*++ Routine Description: Free an unspecified object owned by the ARP module. Arguments: pHdr - Object to be freed. --*/ { ARP_FREE(pObj); } VOID arpAdapterDelete ( PRM_OBJECT_HEADER pObj, PRM_STACK_RECORD psr ) /*++ Routine Description: Free an object of type ARP1394_ADAPTER. Arguments: pHdr - Actually a pointer to the ARP1394_ADAPTER to be deleted. --*/ { ARP1394_ADAPTER * pA = (ARP1394_ADAPTER *) pObj; if (pA->bind.DeviceName.Buffer != NULL) { ARP_FREE(pA->bind.DeviceName.Buffer); } if (pA->bind.ConfigName.Buffer != NULL) { ARP_FREE(pA->bind.ConfigName.Buffer); } if (pA->bind.IpConfigString.Buffer != NULL) { ARP_FREE(pA->bind.IpConfigString.Buffer); } ARP_FREE(pA); } NDIS_STATUS arpAllocateTask( IN PRM_OBJECT_HEADER pParentObject, IN PFN_RM_TASK_HANDLER pfnHandler, IN UINT Timeout, IN const char * szDescription, OPTIONAL OUT PRM_TASK *ppTask, IN PRM_STACK_RECORD pSR ) /*++ Routine Description: Allocates and initializes a task of subtype ARP1394_TASK. Arguments: pParentObject - Object that is to be the parent of the allocated task. pfnHandler - The task handler for the task. Timeout - Unused. szDescription - Text describing this task. ppTask - Place to store pointer to the new task. Return Value: NDIS_STATUS_SUCCESS if we could allocate and initialize the task. NDIS_STATUS_RESOURCES otherwise --*/ { ARP1394_TASK *pATask; NDIS_STATUS Status; BOOLEAN fBackupTask = FALSE; ARP_ALLOCSTRUCT(pATask, MTAG_TASK); // TODO use lookaside lists. if (pATask == NULL) { pATask = arpGetBackupTask(&ArpGlobals); fBackupTask = TRUE; } *ppTask = NULL; if (pATask != NULL) { ARP_ZEROSTRUCT(pATask); RmInitializeTask( &(pATask->TskHdr), pParentObject, pfnHandler, &ArpTasks_StaticInfo, szDescription, Timeout, pSR ); *ppTask = &(pATask->TskHdr); Status = NDIS_STATUS_SUCCESS; if (fBackupTask == TRUE) { MARK_TASK_AS_BACKUP(&pATask->TskHdr); } } else { Status = NDIS_STATUS_RESOURCES; } return Status; } NDIS_STATUS arpCopyUnicodeString( OUT PNDIS_STRING pDest, IN PNDIS_STRING pSrc, BOOLEAN fUpCase ) /*++ Routine Description: Copy the contents of unicode string pSrc into pDest. pDest->Buffer is allocated using NdisAllocateMemoryWithTag; Caller is responsible for freeing it. EXTRA EXTRA EXTRA: This make sure the destination is NULL terminated. IPAddInterface expects the Unicode string passed in to be NULL terminated. NOTE: fUpCase is ignored. Return Value: NDIS_STATUS_SUCCESS on success; NDIS failure status on failure. --*/ { USHORT Length = pSrc->Length; PWCHAR pwStr; NdisAllocateMemoryWithTag(&pwStr, Length+sizeof(WCHAR), MTAG_STRING); ARP_ZEROSTRUCT(pDest); if (pwStr == NULL) { return NDIS_STATUS_RESOURCES; } else { pDest->Length = Length; pDest->MaximumLength = Length+sizeof(WCHAR); pDest->Buffer = pwStr; // We-- ignore the copy flag. // For some reason, we're not in passive, and moreover // NdisUpcaseUnicode doesn't work. // if (0 && fUpCase) { #if !MILLEN ASSERT_PASSIVE(); NdisUpcaseUnicodeString(pDest, pSrc); #endif // !MILLEN } else { NdisMoveMemory(pwStr, pSrc->Buffer, Length); if (Length & 0x1) { ((PUCHAR)pwStr)[Length] = 0; } else { pwStr[Length/sizeof(*pwStr)] = 0; } } return NDIS_STATUS_SUCCESS; } } VOID arpSetPrimaryIfTask( PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT PRM_TASK pTask, ULONG PrimaryState, PRM_STACK_RECORD pSR ) { ENTER("arpSetPrimaryIfTask", 0x535f8cd4) RM_ASSERT_OBJLOCKED(&pIF->Hdr, pSR); ASSERT(pIF->pPrimaryTask==NULL); #if DBG // Veriy that this is a valid primary task. Also verify that PrimaryState // is a valid primary state. // { PFN_RM_TASK_HANDLER pfn = pTask->pfnHandler; ASSERT( ((pfn == arpTaskInitInterface) && (PrimaryState == ARPIF_PS_INITING)) || ((pfn == arpTaskDeinitInterface) && (PrimaryState == ARPIF_PS_DEINITING)) || ((pfn == arpTaskReinitInterface) && (PrimaryState == ARPIF_PS_REINITING)) || ((pfn == arpTaskLowPower) && (PrimaryState == ARPIF_PS_LOW_POWER)) ); } #endif // DBG // // Although it's tempting to put pTask as entity1 and pRask->Hdr.szDescption as // entity2 below, we specify NULL for both so that we can be sure that ONLY one // primary task can be active at any one time. // DBG_ADDASSOC( &pIF->Hdr, NULL, // Entity1 NULL, // Entity2 ARPASSOC_PRIMARY_IF_TASK, " Primary task\n", pSR ); pIF->pPrimaryTask = pTask; SET_IF_PRIMARY_STATE(pIF, PrimaryState); EXIT() } VOID arpClearPrimaryIfTask( PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT PRM_TASK pTask, ULONG PrimaryState, PRM_STACK_RECORD pSR ) { ENTER("arpClearPrimaryIfTask", 0x10ebb0c3) RM_ASSERT_OBJLOCKED(&pIF->Hdr, pSR); ASSERT(pIF->pPrimaryTask==pTask); // Veriy that PrimaryState is a valid primary state. // ASSERT( (PrimaryState == ARPIF_PS_INITED) || (PrimaryState == ARPIF_PS_FAILEDINIT) || (PrimaryState == ARPIF_PS_DEINITED) ); // Delete the association added when setting the primary IF task // DBG_DELASSOC( &pIF->Hdr, NULL, NULL, ARPASSOC_PRIMARY_IF_TASK, pSR ); pIF->pPrimaryTask = NULL; SET_IF_PRIMARY_STATE(pIF, PrimaryState); EXIT() } VOID arpSetSecondaryIfTask( PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT PRM_TASK pTask, ULONG SecondaryState, PRM_STACK_RECORD pSR ) { ENTER("arpSetSecondaryIfTask", 0xf7e925d1) RM_ASSERT_OBJLOCKED(&pIF->Hdr, pSR); if (pIF->pActDeactTask != NULL) { ASSERT(FALSE); return; // EARLY RETURN } #if DBG // Veriy that this is a valid act/deact task. Also verify that SecondaryState // is a valid state. // { PFN_RM_TASK_HANDLER pfn = pTask->pfnHandler; ASSERT( ((pfn == arpTaskActivateInterface) && (SecondaryState == ARPIF_AS_ACTIVATING)) || ((pfn == arpTaskDeactivateInterface) && (SecondaryState == ARPIF_AS_DEACTIVATING)) ); } #endif // DBG // // Although it's tempting to put pTask as entity1 and pRask->Hdr.szDescption as // entity2 below, we specify NULL for both so that we can be sure that ONLY one // primary task can be active at any one time. // DBG_ADDASSOC( &pIF->Hdr, NULL, // Entity1 NULL, // Entity2 ARPASSOC_ACTDEACT_IF_TASK, " ActDeact task\n", pSR ); pIF->pActDeactTask = pTask; SET_IF_ACTIVE_STATE(pIF, SecondaryState); EXIT() } VOID arpClearSecondaryIfTask( PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT PRM_TASK pTask, ULONG SecondaryState, PRM_STACK_RECORD pSR ) { ENTER("arpClearSecondaryIfTask", 0x2068f420) RM_ASSERT_OBJLOCKED(&pIF->Hdr, pSR); if (pIF->pActDeactTask != pTask) { ASSERT(FALSE); return; // EARLY RETURN } // Veriy that SecondaryState is a valid primary state. // ASSERT( (SecondaryState == ARPIF_AS_ACTIVATED) || (SecondaryState == ARPIF_AS_FAILEDACTIVATE) || (SecondaryState == ARPIF_AS_DEACTIVATED) ); // Delete the association added when setting the primary IF task // DBG_DELASSOC( &pIF->Hdr, NULL, NULL, ARPASSOC_ACTDEACT_IF_TASK, pSR ); pIF->pActDeactTask = NULL; SET_IF_ACTIVE_STATE(pIF, SecondaryState); EXIT() } VOID arpSetPrimaryAdapterTask( PARP1394_ADAPTER pAdapter, // LOCKIN LOCKOUT PRM_TASK pTask, ULONG PrimaryState, PRM_STACK_RECORD pSR ) { ENTER("arpSetPrimaryAdapterTask", 0x535f8cd4) RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR); ASSERT(pAdapter->bind.pPrimaryTask==NULL); #if DBG // Veriy that this is a valid primary task. Also verify that PrimaryState // is a valid primary state. // { PFN_RM_TASK_HANDLER pfn = pTask->pfnHandler; ASSERT( ((pfn == arpTaskInitializeAdapter) && (PrimaryState == ARPAD_PS_INITING)) || ((pfn == arpTaskShutdownAdapter) && (PrimaryState == ARPAD_PS_DEINITING)) || (pfn == arpTaskLowPower) || ( pfn == arpTaskOnPower) ); } #endif // DBG // // Although it's tempting to put pTask as entity1 and pRask->Hdr.szDescption as // entity2 below, we specify NULL for both so that we can be sure that ONLY one // primary task can be active at any one time. // DBG_ADDASSOC( &pAdapter->Hdr, NULL, // Entity1 NULL, // Entity2 ARPASSOC_PRIMARY_AD_TASK, " Primary task\n", pSR ); pAdapter->bind.pPrimaryTask = pTask; SET_AD_PRIMARY_STATE(pAdapter, PrimaryState); EXIT() } VOID arpClearPrimaryAdapterTask( PARP1394_ADAPTER pAdapter, // LOCKIN LOCKOUT PRM_TASK pTask, ULONG PrimaryState, PRM_STACK_RECORD pSR ) { ENTER("arpClearPrimaryAdapterTask", 0x9062b2ab) RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR); ASSERT(pAdapter->bind.pPrimaryTask==pTask); // Veriy that PrimaryState is a valid primary state. // ASSERT( (PrimaryState == ARPAD_PS_INITED) || (PrimaryState == ARPAD_PS_FAILEDINIT) || (PrimaryState == ARPAD_PS_DEINITED) ); // Delete the association added when setting the primary IF task // DBG_DELASSOC( &pAdapter->Hdr, NULL, NULL, ARPASSOC_PRIMARY_AD_TASK, pSR ); pAdapter->bind.pPrimaryTask = NULL; SET_AD_PRIMARY_STATE(pAdapter, PrimaryState); EXIT() } VOID arpSetSecondaryAdapterTask( PARP1394_ADAPTER pAdapter, // LOCKIN LOCKOUT PRM_TASK pTask, ULONG SecondaryState, PRM_STACK_RECORD pSR ) { ENTER("arpSetSecondaryAdapterTask", 0x95dae9ac) RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR); if (pAdapter->bind.pSecondaryTask != NULL) { ASSERT(FALSE); return; // EARLY RETURN } #if DBG // Veriy that this is a valid act/deact task. Also verify that SecondaryState // is a valid state. // { PFN_RM_TASK_HANDLER pfn = pTask->pfnHandler; ASSERT( ((pfn == arpTaskActivateAdapter) && (SecondaryState == ARPAD_AS_ACTIVATING)) || ((pfn == arpTaskDeactivateAdapter) && (SecondaryState == ARPAD_AS_DEACTIVATING)) ); } #endif // DBG // // Although it's tempting to put pTask as entity1 and pRask->Hdr.szDescption as // entity2 below, we specify NULL for both so that we can be sure that ONLY one // primary task can be active at any one time. // DBG_ADDASSOC( &pAdapter->Hdr, NULL, // Entity1 NULL, // Entity2 ARPASSOC_ACTDEACT_AD_TASK, " Secondary task\n", pSR ); pAdapter->bind.pSecondaryTask = pTask; SET_AD_ACTIVE_STATE(pAdapter, SecondaryState); EXIT() } VOID arpClearSecondaryAdapterTask( PARP1394_ADAPTER pAdapter, // LOCKIN LOCKOUT PRM_TASK pTask, ULONG SecondaryState, PRM_STACK_RECORD pSR ) { ENTER("arpClearSecondaryAdapterTask", 0xc876742b) RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR); if (pAdapter->bind.pSecondaryTask != pTask) { ASSERT(FALSE); return; // EARLY RETURN } // Veriy that SecondaryState is a valid primary state. // ASSERT( (SecondaryState == ARPAD_AS_ACTIVATED) || (SecondaryState == ARPAD_AS_FAILEDACTIVATE) || (SecondaryState == ARPAD_AS_DEACTIVATED) ); // Delete the association added when setting the primary IF task // DBG_DELASSOC( &pAdapter->Hdr, NULL, NULL, ARPASSOC_ACTDEACT_AD_TASK, pSR ); pAdapter->bind.pSecondaryTask = NULL; SET_AD_ACTIVE_STATE(pAdapter, SecondaryState); EXIT() } #if 0 NDIS_STATUS arpCopyAnsiStringToUnicodeString( OUT PNDIS_STRING pDest, IN PANSI_STRING pSrc ) /*++ Routine Description: Converts pSrc into unicode and sets up pDest with the it. pDest->Buffer is allocated using NdisAllocateMemoryWithTag; Caller is responsible for freeing it. Return Value: NDIS_STATUS_SUCCESS on success; NDIS_STATUS_RESOURCES on failure. --*/ { UINT Size; PWCHAR pwStr; Size = sizeof(WCHAR) * pSrc->MaximumLength; NdisAllocateMemoryWithTag(&pwStr, Size, MTAG_STRING); ARP_ZEROSTRUCT(pDest); if (pwStr == NULL) { return NDIS_STATUS_RESOURCES; } else { pDest->MaximumLength = Size; pDest->Buffer = pwStr; NdisAnsiStringToUnicodeString(pDest, pSrc); return NDIS_STATUS_SUCCESS; } } NDIS_STATUS arpCopyUnicodeStringToAnsiString( OUT PANSI_STRING pDest, IN PNDIS_STRING pSrc ) /*++ Routine Description: Converts pSrc into ansi and sets up pDest with the it. pDest->Buffer is allocated using NdisAllocateMemoryWithTag; Caller is responsible for freeing it. Return Value: NDIS_STATUS_SUCCESS on success; NDIS_STATUS_RESOURCES on failure. --*/ { UINT Size; PCHAR pStr; Size = pSrc->MaximumLength/sizeof(WCHAR) + sizeof(WCHAR); NdisAllocateMemoryWithTag(&pStr, Size, MTAG_STRING); ARP_ZEROSTRUCT(pDest); if (pStr == NULL) { return NDIS_STATUS_RESOURCES; } else { pDest->Buffer = pStr; NdisUnicodeStringToAnsiString(pDest, pSrc); pStr[pDest->Length] = 0; pDest->MaximumLength = Size; // Must be done AFTER call to // NdisUnicodeStringToAnsiString, which // sets MaximumLength to Length; return NDIS_STATUS_SUCCESS; } } #endif // 0 UINT arpGetSystemTime(VOID) /*++ Returns system time in seconds. Since it's in seconds, we won't overflow unless the system has been up for over a 100 years :-) --*/ { LARGE_INTEGER Time; NdisGetCurrentSystemTime(&Time); Time.QuadPart /= 10000000; //10-nanoseconds to seconds. return Time.LowPart; } #if ARP_DO_TIMESTAMPS void arpTimeStamp( char *szFormatString, UINT Val ) { UINT Minutes; UINT Seconds; UINT Milliseconds; LARGE_INTEGER Time; NdisGetCurrentSystemTime(&Time); Time.QuadPart /= 10000; //10-nanoseconds to milliseconds. Milliseconds = Time.LowPart; // don't care about highpart. Seconds = Milliseconds/1000; Milliseconds %= 1000; Minutes = Seconds/60; Seconds %= 60; DbgPrint( szFormatString, Minutes, Seconds, Milliseconds, Val); } #endif // ARP_DO_TIMESTAMPS