/*---------------------------------------------------------------------------*
  Project:  NitroSDK - WM - libraries
  File:     wm_system.c

  Copyright 2003,2004 Nintendo.  All rights reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law.  They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Log: wm_system.c,v $
  Revision 1.14  2004/10/22 08:52:52  terui
  Restored way to queue consecutive requests, which was accidentally deleted.

  Revision 1.13  2004/10/22 04:37:28  terui
  Changed functions that return int type as WMErrCode so that they return WMErrCode enumerator type.

  Revision 1.12  2004/10/21 12:08:25  terui
  Changed location that does post-processing for WM_End in PXI callback to be before user callback is called.

  Revision 1.11  2004/10/05 09:45:28  terui
  Standardized the MAC address as the u8 type array

  Revision 1.10  2004/10/05 01:04:17  terui
  Added the structure size check when compiling

  Revision 1.9  2004/10/03 07:47:13  ooe
  Merged with ipl_branch. Added the freeze process when Flash error

  Revision 1.8  2004/09/29 09:48:25  terui
  Corrected for cases where WMi_SendCommand might be called from an interrupt. 

  Revision 1.7  2004/09/24 04:02:39  terui
  Changed the error check sequence in WM_Init. 

  Revision 1.6  2004/09/23 09:24:17  seiki_masashi
  Corrected the exclusive control of WMi_SendCommand 

  Revision 1.5  2004/09/17 06:36:08  seiki_masashi
  Added ssid and myAid fields to WMPortRecvCallback 

  Revision 1.4  2004/09/14 02:47:58  terui
  Added a function to discard the buffer cache provided during initialization. 

  Revision 1.3  2004/09/11 06:09:12  yasu
  Use OS_TPrintf instead of WMi_Printf

  Revision 1.2  2004/09/11 04:13:00  terui
  Changed the print that does the warning display so it does not consume much of the stack. 

  Revision 1.1  2004/09/10 11:03:30  terui
  New upload along with the division of wm.c. 

  $NoKeywords: $
 *---------------------------------------------------------------------------*/

#include    <nitro/wm.h>
#include    "wm_arm9_private.h"


/*---------------------------------------------------------------------------*
    Constant Definition 
 *---------------------------------------------------------------------------*/
#define     WM_BUF_MSG_NUM                  10


/*---------------------------------------------------------------------------*
    Internal Variable Definition 
 *---------------------------------------------------------------------------*/
static u16              wmInitialized = 0;  // WM initialization flag
static WMArm9Buf*       wm9buf;
static u32              fifoBuf[ WM_BUF_MSG_NUM ][ WM_FIFO_BUF_SIZE / sizeof(u32) ]  ATTRIBUTE_ALIGN(32);
static OSMessageQueue   bufMsgQ;                // Request queue for WM7 
static OSMessage        bufMsg[WM_BUF_MSG_NUM]; // Request queue buffer for WM7


/*---------------------------------------------------------------------------*
    Internal Function Definition 
 *---------------------------------------------------------------------------*/
static void WmReceiveFifo( PXIFifoTag tag , u32 fifo_buf_adr , BOOL err );
static void WmClearFifoRecvFlag( void );

/* Assert when compiled */
#define SDK_ASSERT_ON_COMPILE(expr) \
extern  assert_on_compile ## #__LINE__ ( char a[(expr) ? 1 : -1] )


/*---------------------------------------------------------------------------*
  Name:         WM_Init

  Description:  Performs WM library initialization process.
                Synchronous function only performs initializatin on the ARM9 side.

  Arguments:    wmSysBuf    -   pointer to buffer secured by call source.
                                Buffer size must be WM_SYSTEM_BUF_SIZE only.
                dmaNo       -   DMA number used by WM.

  Returns:      WMErrCode   -   Returns process results.
 *---------------------------------------------------------------------------*/
WMErrCode
WM_Init( void* wmSysBuf , u16 dmaNo )
{
    // Checks if the structure size exceeds the expected value.
    SDK_ASSERT_ON_COMPILE( sizeof( WMArm9Buf ) <= WM_ARM9WM_BUF_SIZE );
    SDK_ASSERT_ON_COMPILE( sizeof( WMArm7Buf ) <= WM_ARM7WM_BUF_SIZE );
    SDK_ASSERT_ON_COMPILE( sizeof( WMStatus  ) <= WM_STATUS_BUF_SIZE );

    // Confirms that the WM library initialization is complete. 
    if( wmInitialized )
    {
        return WM_ERRCODE_ILLEGAL_STATE;    // Initialization complete 
    }
    wmInitialized = 1;

    // Parameter check
    if( wmSysBuf == NULL )
    {
        WM_WARNING( "Parameter \"wmSysBuf\" must not be NULL.\n" );
        wmInitialized = 0;
        return WM_ERRCODE_INVALID_PARAM;
    }
    if( dmaNo > MI_DMA_MAX_NUM )
    {
        WM_WARNING( "Parameter \"dmaNo\" is over %d.\n" , MI_DMA_MAX_NUM );
        wmInitialized = 0;
        return WM_ERRCODE_INVALID_PARAM;
    }
    if( (u32)wmSysBuf & 0x01f )
    {
        WM_WARNING( "Parameter \"wmSysBuf\" must be 32-byte aligned.\n" );
        wmInitialized = 0;
        return WM_ERRCODE_INVALID_PARAM;
    }

    // Confirms whether the WM library has started in ARM7
    PXI_Init();
    if( ! PXI_IsCallbackReady( PXI_FIFO_TAG_WM , PXI_PROC_ARM7 ) )
    {
        WM_WARNING( "WM library on ARM7 side is not ready yet.\n" );
        wmInitialized = 0;
        return WM_ERRCODE_WM_DISABLE;
    }

    /*  It is possible that a write-back will be generated at a time when it is thought excess data is not left 
         in the cache, causing trouble with the ARM7 state management.
        Discards the buffer cache for all the work as a measure against this. */
    DC_InvalidateRange( wmSysBuf , WM_SYSTEM_BUF_SIZE );
    // Initialization for each buffer
    MI_DmaClear32( dmaNo , wmSysBuf , WM_SYSTEM_BUF_SIZE );
    wm9buf              = (WMArm9Buf*)wmSysBuf;
    wm9buf->WM7         = (WMArm7Buf*)( (u32)  wm9buf             + WM_ARM9WM_BUF_SIZE );
    wm9buf->status      = (WMStatus*) ( (u32)( wm9buf->WM7 )      + WM_ARM7WM_BUF_SIZE );
    wm9buf->fifo9to7    = (u32*)      ( (u32)( wm9buf->status )   + WM_STATUS_BUF_SIZE );
    wm9buf->fifo7to9    = (u32*)      ( (u32)( wm9buf->fifo9to7 ) + WM_FIFO_BUF_SIZE   );

    // Clears the FIFO buffer writable flag
    WmClearFifoRecvFlag();

    // Initializes variables
    wm9buf->dmaNo   = dmaNo;
    wm9buf->ksFlag  = FALSE;

    // Initializes the callback table for each port
    {
        s32     i;
    
        for( i = 0 ; i < WM_NUM_OF_PORT ; i ++ )
        {
            (void)WM_SetPortCallback( (u16)i , NULL , NULL );
        }
    }

    // Initializes the queue for entry registration
    {
        s32     i;
    
        OS_InitMessageQueue( &bufMsgQ , bufMsg , WM_BUF_MSG_NUM );
        for( i = 0 ; i < WM_BUF_MSG_NUM ; i ++ )
        {
            (void)OS_SendMessage( &bufMsgQ , fifoBuf[ i ] , OS_MESSAGE_BLOCK );
        }
    }

    // Sets a FIFO receiving function
    PXI_SetFifoRecvCallback( PXI_FIFO_TAG_WM , WmReceiveFifo );

    return WM_ERRCODE_SUCCESS;
}

/*---------------------------------------------------------------------------*
  Name:         WM_Finish

  Description:  Performs WM library finish processing. Synchronous function.
                Returns to state before WM_Init function call.

  Arguments:    None.

  Returns:      WMErrCode   -   Returns process results.
 *---------------------------------------------------------------------------*/
WMErrCode
WM_Finish( void )
{
    WMErrCode   result;

    // Cannot execute unless initialization is complete
    result = WMi_CheckInitialized();
    if( result != WM_ERRCODE_SUCCESS )
    {
        return WM_ERRCODE_ILLEGAL_STATE;
    }

    // Cannot execute if the state is not READY
    result = WMi_CheckState( WM_STATE_READY );
    WM_CHECK_RESULT( result );

    // Ends the WM library
    WmClearFifoRecvFlag();
    PXI_SetFifoRecvCallback( PXI_FIFO_TAG_WM , NULL );
    wm9buf = 0;
    wmInitialized = 0;

    return WM_ERRCODE_SUCCESS;
}

/*---------------------------------------------------------------------------*
  Name:         WMi_SetCallbackTable

  Description:  Registers the callback function for the asynchronous function.

  Arguments:    id          -   Asynchronous function API ID.
                callback    -   The callback function to be registered.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
WMi_SetCallbackTable( WMApiid id , WMCallbackFunc callback )
{
    SDK_NULL_ASSERT( wm9buf );

    wm9buf->CallbackTable[ id ] = callback;
}

/*---------------------------------------------------------------------------*
  Name:         WMi_SendCommand

  Description:  Transmits a request to ARM7 via FIFO. 
                Specifies the list of parameters 
                for commands accompanying a number of u32-type parameters.

  Arguments:    id          -   API ID for the request.
                paramNum    -   Number of virtual arguments.
                ...         -   Virtual arguments. 

  Returns:      int -   Returns WM_ERRCODE_* type processing results.
 *---------------------------------------------------------------------------*/
WMErrCode
WMi_SendCommand( WMApiid id , u16 paramNum , ... )
{
    va_list     vlist;
    s32         i;
    int         result;
    u32*        tmpAddr;
    static vu32 lockCount = 0;

    SDK_NULL_ASSERT( wm9buf );

    if( FALSE == OS_ReceiveMessage(&bufMsgQ, (OSMessage*)&tmpAddr, OS_MESSAGE_NOBLOCK) )
    {
        return WM_ERRCODE_FIFO_ERROR;
    }

    if ( paramNum == 0 )
    {
        // Copies the buffer set by the caller 
        DC_StoreRange(wm9buf->fifo9to7, WM_FIFO_BUF_SIZE);
        DC_InvalidateRange(tmpAddr, WM_FIFO_BUF_SIZE);
        MI_DmaCopy32(wm9buf->dmaNo, wm9buf->fifo9to7, tmpAddr, WM_FIFO_BUF_SIZE ); 
    }
    
    // API ID
    *(u16*)tmpAddr = (u16)id;

    // Adds the specified number of arguments 
    va_start( vlist , paramNum );
    for( i = 0 ; i < paramNum ; i ++ )
    {
        tmpAddr[ i + 1 ] = va_arg( vlist , u32 );
    }
    va_end( vlist );

    DC_StoreRange(tmpAddr, WM_FIFO_BUF_SIZE);

    // Notification with FIFO
    result = PXI_SendWordByFifo( PXI_FIFO_TAG_WM, (u32)tmpAddr, FALSE );
    
    (void) OS_SendMessage(&bufMsgQ, tmpAddr, OS_MESSAGE_BLOCK);
    
    if( result < 0 )
    {
        WM_WARNING( "Failed to send command through FIFO.\n" );
        return WM_ERRCODE_FIFO_ERROR;
    }

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WMi_GetSystemWork

  Description:  Gets the pointer to the top of the buffer used internally by the WM library. 

  Arguments:    None.

  Returns:      WMArm9Buf*  -   Returns a pointer to the internal work buffer.
 *---------------------------------------------------------------------------*/
WMArm9Buf*
WMi_GetSystemWork( void )
{
    SDK_NULL_ASSERT( wm9buf );
    return wm9buf;
}

/*---------------------------------------------------------------------------*
  Name:         WMi_CheckInitialized

  Description:  Confirms that the WM library initialization is complete. 

  Arguments:    None.

  Returns:      int -   Returns WM_ERRCODE_* type processing results.
 *---------------------------------------------------------------------------*/
WMErrCode
WMi_CheckInitialized( void )
{
    // Confirms that initialization is complete 
    if( ! wmInitialized )
    {
        WM_WARNING( "WM library is not initialized yet.\n" );
        return WM_ERRCODE_ILLEGAL_STATE;
    }
    return WM_ERRCODE_SUCCESS;
}

/*---------------------------------------------------------------------------*
  Name:         WMi_CheckIdle

  Description:  Confirms the internal state of the WM library, and confirms that the wireless hardware has started up.

  Arguments:    None.

  Returns:      int -   Returns WM_ERRCODE_* type processing results.
 *---------------------------------------------------------------------------*/
WMErrCode
WMi_CheckIdle( void )
{
    WMErrCode   result;

    // Confirms that initialization is complete
    result = WMi_CheckInitialized();
    WM_CHECK_RESULT( result );

    // Confirms the current state 
    DC_InvalidateRange( &( wm9buf->status->state ) , 2 );
    if(
        ( wm9buf->status->state == WM_STATE_READY ) ||
        ( wm9buf->status->state == WM_STATE_STOP )
    )
    {
        WM_WARNING( "WM state is \"%d\" now. So can't execute request.\n" , wm9buf->status->state );
        return WM_ERRCODE_ILLEGAL_STATE;
    }

    return WM_ERRCODE_SUCCESS;
}

/*---------------------------------------------------------------------------*
  Name:         WMi_CheckStateEx

  Description:  Confirms the internal state of the WM library. 
                Lists and specifies the WMState type parameters showing the permitted state. 

  Arguments:    paramNum    -   Number of virtual arguments.
                ...         -   Virtual arguments. 

  Returns:      int -   Returns WM_ERRCODE_* type processing results.
 *---------------------------------------------------------------------------*/
WMErrCode
WMi_CheckStateEx( s32 paramNum , ... )
{
    WMErrCode   result;
    u16         now;
    u32         temp;
    va_list     vlist;

    // Confirms that initialization is complete
    result = WMi_CheckInitialized();
    WM_CHECK_RESULT( result );

    // Gets the current state 
    DC_InvalidateRange( &( wm9buf->status->state ) , 2 );
    now = wm9buf->status->state;

    // Match confirmation
    result = WM_ERRCODE_ILLEGAL_STATE;
    va_start( vlist , paramNum );
    for( ; paramNum ; paramNum-- )
    {
        temp = va_arg( vlist , u32 );
        if( temp == now )
        {
            result = WM_ERRCODE_SUCCESS;
        }
    }
    va_end( vlist );

    if( result == WM_ERRCODE_ILLEGAL_STATE )
    {
        WM_WARNING( "WM state is \"%d\" now. So can't execute request.\n" , now );
    }

    return result;
}

/*---------------------------------------------------------------------------*
  Name:         WmReceiveFifo

  Description:  Receives a callback from WM7 via FIFO. 

  Arguments:    tag          - Unused 
                fifo_buf_adr - A pointer to the callback parameter group
                err          - Unused

  Returns:      None.
 *---------------------------------------------------------------------------*/
static void
WmReceiveFifo( PXIFifoTag tag , u32 fifo_buf_adr , BOOL err )
{
#pragma unused( tag )

    WMCallback *callback_p = (WMCallback*)fifo_buf_adr;

    if( err ) return;   // The preparation for the WM_sp_init PXI handler is not ready 

    // Invalidates the FIFO command buffer (9 <- 7) cache
    DC_InvalidateRange( wm9buf->fifo7to9,   WM_FIFO_BUF_SIZE);
    DC_InvalidateRange( wm9buf->status, WM_STATUS_BUF_SIZE);

    if( callback_p->apiid >= WM_NUM_OF_CALLBACK )
    {
        if( callback_p->apiid == WM_APIID_INDICATION )
        {
#if SDK_VERSION_WL >= 21000
            if( callback_p->errcode == WM_ERRCODE_FLASH_ERROR )
            {
                // ARM9 freeze
                OS_Terminate();     // It does not return.
            }
#endif
            if( wm9buf->indCallback != NULL )
            {
                wm9buf->indCallback( (void*)callback_p );
            }
        }
        else if ( callback_p->apiid == WM_APIID_PORT_RECV )
        {
            // Processes the callback according to the port number
            WMPortRecvCallback* cb_Port = (WMPortRecvCallback*)callback_p;
            SDK_ASSERT( cb_Port->port < 16 );
            if ( wm9buf->portCallbackTable[ cb_Port->port ] != NULL )
            {
                cb_Port->arg = wm9buf->portCallbackArgument[ cb_Port->port ];
                DC_InvalidateRange( cb_Port->recvBuf , wm9buf->status->mp_recvBufSize ); // ToDo: Too much invalidation
                ( wm9buf->portCallbackTable[ cb_Port->port ] )( (void*)cb_Port );
            }
#if 0
            else
            {
                OS_Printf("ARM9: no callback function on port %d { %04x %04x ... }\n", cb_Port->port, cb_Port->data[0], cb_Port->data[1]);
            }
#endif
        }
        else if ( callback_p->apiid == WM_APIID_PORT_SEND )
        {
            // Does the callback specified when the data is set
            WMPortSendCallback* cb_Port = (WMPortSendCallback*)callback_p;
            callback_p->apiid = WM_APIID_SET_MP_DATA; // Camouflage
            if ( cb_Port->callback != NULL )
            {
                ( cb_Port->callback )( (void*)cb_Port );
            }
        }
        else {
          OS_Printf("ARM9: no callback function\n");

        }
    }
    else
    {
        // Invalidates the receiving buffer cache 
        // When PORT_RECV is called after MPEND_IND and MP_IND, 
        // the InvalidateRange is already set, so the cache can be ignored
        if ( callback_p->apiid == WM_APIID_START_MP )
        {
            WMStartMPCallback *cb_StartMP = (WMStartMPCallback*)callback_p;
            if ( cb_StartMP->state == WM_STATECODE_MPEND_IND || cb_StartMP->state == WM_STATECODE_MP_IND )
            {
                if ( cb_StartMP->errcode == WM_ERRCODE_SUCCESS )
                {
                    DC_InvalidateRange( cb_StartMP->recvBuf , wm9buf->status->mp_recvBufSize );
                }
            }
        }
        
        // WM_End post-processing
        if( callback_p->apiid == WM_APIID_END )
        {
            if( callback_p->errcode == WM_ERRCODE_SUCCESS )
            {
                WMCallbackFunc  cb = wm9buf->CallbackTable[ callback_p->apiid ];
                // finish WM library
                (void)WM_Finish();
                if( cb != NULL )
                {
                    cb( (void*)callback_p );
                }
                return;
            }
        }
        // callback process accroding to apiid (does nothing if callback not set (NULL))
        if( NULL != wm9buf->CallbackTable[callback_p->apiid] )
        {
            ( wm9buf->CallbackTable[ callback_p->apiid ] )( (void*)callback_p );
        }
        
        // Post-processing
        if ( callback_p->apiid == WM_APIID_START_PARENT || callback_p->apiid == WM_APIID_START_CONNECT )
        {
            u16 state, aid, myAid;
            u8* macAddress;
            u8* ssid;
            
            if ( callback_p->apiid == WM_APIID_START_PARENT )
            {
                WMStartParentCallback *cb = (WMStartParentCallback*)callback_p;
                state = cb->state;
                aid = cb->aid;
                myAid = 0;
                macAddress = cb->macAddress;
                ssid = cb->ssid;
            }
            else if ( callback_p->apiid == WM_APIID_START_CONNECT )
            {
                WMStartParentCallback *cb = (WMStartParentCallback*)callback_p;
                state = cb->state;
                aid = 0;
                myAid = cb->aid;
                macAddress = cb->macAddress;
                ssid = NULL;
            }
            if ( state == WM_STATECODE_CONNECTED || state == WM_STATECODE_DISCONNECTED )
            {
                static WMPortRecvCallback cb_Port;
                u16 iPort;
                
                cb_Port.apiid  = WM_APIID_PORT_RECV;
                cb_Port.errcode = WM_ERRCODE_SUCCESS;
                cb_Port.state  = state;
                cb_Port.recvBuf = NULL;
                cb_Port.data   = NULL;
                cb_Port.length = 0;
                cb_Port.aid    = aid;
                cb_Port.myAid  = myAid;
                cb_Port.seqNo  = 0xffff;
                MI_CpuCopy8( macAddress, cb_Port.macAddress, WM_SIZE_MACADDR );
                if ( ssid != NULL )
                {
                    MI_CpuCopy16( ssid, cb_Port.ssid, WM_SIZE_CHILD_SSID );
                }
                else
                {
                    MI_CpuClear16( cb_Port.ssid, WM_SIZE_CHILD_SSID );
                }
                
                for ( iPort = 0; iPort < WM_NUM_OF_PORT; iPort++ )
                {
                    cb_Port.port = iPort;
                    if ( wm9buf->portCallbackTable[ iPort ] != NULL )
                    {
                        cb_Port.arg = wm9buf->portCallbackArgument[ iPort ];
                        ( wm9buf->portCallbackTable[ iPort ] )( (void*)&cb_Port );
                    }
                }
            }
        }
    }
    // The fifo7to9 region has been written with PORT_SEND and PORT_RECV, so
    // the cache is invalidated so as to not be written back.
    DC_InvalidateRange( wm9buf->fifo7to9, WM_FIFO_BUF_SIZE );
    WmClearFifoRecvFlag();

    return;
}

/*---------------------------------------------------------------------------*
  Name:         WmClearFifoRecvFlag

  Description:  Notifies WM7 that reference to the FIFO data used in 
                the WM7 callback is complete.
                Edits the next callback after waiting for the flag to be unlocked when FIFO is used for the WM7 callback.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
static void
WmClearFifoRecvFlag( void )
{
    if( OS_GetSystemWork()->wm_callback_control & WM_EXCEPTION_CB_MASK )
    {
        // Lowers the CB exclusion flag 
        OS_GetSystemWork()->wm_callback_control &= ~WM_EXCEPTION_CB_MASK;
    }
}

/*---------------------------------------------------------------------------*
  Name:         WMi_DebugPrintSendQueue

  Description:  Outputs the contents of the port transmission queue to print. 

  Arguments:    queue - Specifies the pointer to the port transmission queue. 

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
WMi_DebugPrintSendQueue( WMPortSendQueue* queue )
{
    WMstatus*   status = wm9buf->status;
    WMPortSendQueueData* queueData;
    u16 index;

    DC_InvalidateRange(wm9buf->status, WM_STATUS_BUF_SIZE);    // Invalidates the ARM7 status region cache 
    queueData = status->sendQueueData;

    OS_Printf("head = %d, tail = %d, ", queue->head, queue->tail);
    if ( queue->tail != WM_SEND_QUEUE_END )
    {
        OS_Printf("%s", (queueData[queue->tail].next == WM_SEND_QUEUE_END) ? "valid" : "invalid");
    }
    OS_Printf("\n");
    for ( index = queue->head; index != WM_SEND_QUEUE_END; index = queueData[index].next )
    {
        WMPortSendQueueData* data = &(queueData[index]);
        
        OS_Printf("queueData[%d] -> %d { port=%d, destBitmap=%x, size=%d } \n", index, data->next, data->port, data->destBitmap, data->size );
    }

}

/*---------------------------------------------------------------------------*
  Name:         WMi_DebugPrintAllSendQueue

  Description:  Outputs the contents of all the port transmission queues to print. 

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
WMi_DebugPrintAllSendQueue( void )
{
    WMstatus*   status = wm9buf->status;
#if 0
    int iPrio;
    
    DC_InvalidateRange(wm9buf->status, WM_STATUS_BUF_SIZE);    // Invalidates the ARM7 status region cache 
    for ( iPrio=0; iPrio<WM_PRIORITY_LEVEL; iPrio++ )
    {
        OS_Printf("== send queue [%d]\n", iPrio);
        WMi_DebugPrintSendQueue( &status->sendQueue[iPrio] );
    }
    for ( iPrio=0; iPrio<WM_PRIORITY_LEVEL; iPrio++ )
    {
        OS_Printf("== ready queue [%d]\n", iPrio);
        WMi_DebugPrintSendQueue( &status->readyQueue[iPrio] );
    }
    OS_Printf("== free queue\n");
    OS_Printf(" head: %d, tail: %d\n", status->sendQueueFreeList.head, status->sendQueueFreeList.tail);
//    WMi_DebugPrintSendQueue( &status->sendQueueFreeList );
#else
    DC_InvalidateRange(wm9buf->status, WM_STATUS_BUF_SIZE);    // Invalidates the ARM7 status region cache 
    OS_Printf("== ready queue [2]\n");
    OS_Printf(" head: %d, tail: %d\n", status->readyQueue[2].head, status->readyQueue[2].tail);
#endif

}

/*---------------------------------------------------------------------------*
  Name:         WMi_GetStatusAddress

  Description:  Gets the pointer to the status structure managed internally by WM. 
  	This structure is directly operated by ARM7, so writing by ARM9 is disabled. 
  	Also, note that the cache line containing the portion to be referenced needs 
  	to be discarded before referencing the contents.

  Arguments:    None.

  Returns:      const WMStatus* - Returns a pointer to the status structure.
 *---------------------------------------------------------------------------*/
const WMStatus*
WMi_GetStatusAddress( void )
{
    // Initialization check
    if( WMi_CheckInitialized() != WM_ERRCODE_SUCCESS )
    {
        return NULL;
    }

    return wm9buf->status;
}

#ifndef SDK_FINALROM
#if 0
/*---------------------------------------------------------------------------*
  Name:         WMi_Printf

  Description:  Outputs to debug print. This output consumes less of the stack
                than the default OS_Printf.

  Arguments:    Same as OS_Print.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
WMi_Printf( const char* fmt , ... )
{
    va_list     vlist;
    static char temp[ 256 ];

    va_start( vlist , fmt );
    (void)OS_VSNPrintf( temp , sizeof( temp ) , fmt , vlist );
    va_end( vlist );
    OS_PutString( temp );
}

/*---------------------------------------------------------------------------*
  Name:         WMi_Warning

  Description:  Displays a warning for print output. This consumes less
                of the stack than the default OSi_Warning.

  Arguments:    Same as OSi_Warning. 

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
WMi_Warning( const char* file , int line , const char*fmt , ... )
{
    va_list     vlist;

    WMi_Printf( "%s:%d: WM Warning: ", file, line );

    va_start( vlist, fmt );
    WMi_Printf( fmt, vlist );
    va_end( vlist );

    WMi_Printf( "\n" );
}
#endif
#endif


/*---------------------------------------------------------------------------*
    End of file
 *---------------------------------------------------------------------------*/
