www.pudn.com > CEWifiDriverAR6000-21374.zip > htc_utils.c


//------------------------------------------------------------------------------ 
//  
//    Copyright (c) 2006 Microsoft Corporation.  All rights reserved. 
//    Copyright (c) 2006 Atheros Corporation.  All rights reserved. 
// 
//    The use and distribution terms for this software are covered by the 
//    Microsoft Limited Permissive License (Ms-LPL)  
//    http://www.microsoft.com/resources/sharedsource/licensingbasics/limitedpermissivelicense.mspx  
//    which can be found in the file MS-LPL.txt at the root of this distribution. 
//    By using this software in any fashion, you are agreeing to be bound by 
//    the terms of this license. 
// 
//    The software is licensed “as-is.”  
//    You must not remove this notice, or any other, from this software. 
//  
//  
//  
//    Windows CE Wifi Driver for AR-6000 
//  
//------------------------------------------------------------------------------ 
//============================================================================== 
// This file contains the utility routines used across the entire HTC module. 
// 
// Author(s): ="Atheros" 
//============================================================================== 
 
 
#include "htc_internal.h" 
 
/* ------ Global Variable Declarations ------- */ 
extern HTC_TARGET *AtherosTargetList[HIF_MAX_DEVICES]; 
extern HTC_GLOBAL_EVENT_TABLE AtherosEventTable; 
extern A_MUTEX_T instanceCS; 
 
#ifdef DEBUG 
extern A_UINT32 debughtc; 
#endif 
 
/* ------ Static Variables ------ */ 
 
/* ------ Functions ------ */ 
void 
dispatchEvent(HTC_TARGET     *target,  
              HTC_ENDPOINT_ID endPointId, 
              HTC_EVENT_ID    eventId,  
              HTC_EVENT_INFO *eventInfo) 
{ 
    EVENT_TABLE_ELEMENT *eventElement; 
 
    if (eventId == HTC_TARGET_AVAILABLE) { 
        eventElement = &AtherosEventTable.element[0]; 
    } else if (eventId == HTC_TARGET_UNAVAILABLE) { 
        eventElement = &AtherosEventTable.element[1]; 
    } else { 
        eventElement =  
            &target->endPoint[endPointId].eventTable.element[eventId];  
    } 
    AR_DEBUG_ASSERT(eventElement != NULL); 
 
    HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                    "dispatchEvent(endpoint: %d, eventId: 0x%d, handler: 0x%p)\n", endPointId, eventElement->id, eventElement->handler); 
    if (eventElement->handler) { 
        eventElement->handler(target, endPointId, eventId, eventInfo, 
                              eventElement->param); 
    } 
} 
 
 
A_STATUS  
addToEventTable(HTC_TARGET       *target, 
                HTC_ENDPOINT_ID   endPointId, 
                HTC_EVENT_ID      eventId, 
                HTC_EVENT_HANDLER handler,  
                void             *param) 
{ 
    EVENT_TABLE_ELEMENT *new; 
 
    if (eventId == HTC_TARGET_AVAILABLE) { 
        new = &AtherosEventTable.element[0]; 
    } else if (eventId == HTC_TARGET_UNAVAILABLE) { 
        new = &AtherosEventTable.element[1]; 
    } else { 
        new = &target->endPoint[endPointId].eventTable.element[eventId];  
    } 
 
    /* Store the event id, the corresponding handler and the param passed */ 
    new->id = eventId; 
    new->handler = handler; 
    new->param = param; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                    "addToEventTable(endpoint: %d, eventId: 0x%d, handler: 0x%p)\n", endPointId, new->id, new->handler); 
 
    return A_OK; 
} 
 
 
A_STATUS  
removeFromEventTable(HTC_TARGET *target, 
                     HTC_ENDPOINT_ID endPointId, 
                     HTC_EVENT_ID  eventId) 
{ 
    EVENT_TABLE_ELEMENT *remove; 
 
    if (eventId == HTC_TARGET_AVAILABLE) { 
        remove = &AtherosEventTable.element[0]; 
    } else if (eventId == HTC_TARGET_UNAVAILABLE) { 
        remove = &AtherosEventTable.element[1]; 
    } else { 
        remove = &target->endPoint[endPointId].eventTable.element[eventId];  
    } 
 
    /* Remove the event handler */ 
    A_MEMZERO(remove, sizeof(EVENT_TABLE_ELEMENT)); 
 
    return A_OK; 
} 
 
A_STATUS 
addToMboxQueue(HTC_DATA_REQUEST_QUEUE *queue, 
               A_UCHAR        *buffer, 
               A_UINT32        bufferLength, 
               A_UINT32        actualLength, 
               void           *cookie) 
{ 
    A_STATUS status; 
    HTC_DATA_REQUEST_ELEMENT *element; 
 
    AR_DEBUG_ASSERT(queue != NULL); 
    AR_DEBUG_ASSERT(bufferLength); 
 
    HTC_DEBUG_PRINTF(ATH_LOG_SYNC,  
                    "Critical Section (queue): LOCK at line %d in file %s\n", __LINE__, __FILE__); 
    A_MUTEX_LOCK(&instanceCS); 
    element = GET_QUEUE_TAIL(queue); 
    if (!(IS_DATA_QUEUE_FULL(queue)) && IS_ELEMENT_FREE(element)) { 
        element->buffer.free = FALSE; 
        FILL_MBOX_BUFFER(element, buffer, bufferLength, actualLength, cookie); 
        queue->size += 1; 
 
        HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                        "addToMboxQueue (index: %d, size: %d, bufferElement: 0x%p, bufferElement->buffer: 0x%p, bufferElement->cookie: 0x%p)\n", (queue->head + queue->size - 1) % HTC_DATA_REQUEST_RING_BUFFER_SIZE, queue->size, element, (GET_MBOX_BUFFER(element))->buffer, (GET_MBOX_BUFFER(element))->cookie); 
        status = A_OK; 
    } else { 
        HTC_DEBUG_PRINTF(ATH_LOG_ERR, "Queue size: %d\n", queue->size); 
        status = A_ERROR; 
    } 
    HTC_DEBUG_PRINTF(ATH_LOG_SYNC,  
                    "Critical Section (queue): UNLOCK at line %d in file %s\n", __LINE__, __FILE__); 
    A_MUTEX_UNLOCK(&instanceCS); 
 
    return status; 
} 
 
HTC_DATA_REQUEST_ELEMENT * 
removeFromMboxQueue(HTC_DATA_REQUEST_QUEUE *queue) { 
    HTC_DATA_REQUEST_ELEMENT *element; 
    AR_DEBUG_ASSERT(queue != NULL); 
 
    HTC_DEBUG_PRINTF(ATH_LOG_SYNC,  
                    "Critical Section (queue): LOCK at line %d in file %s\n", __LINE__, __FILE__); 
    A_MUTEX_LOCK(&instanceCS); 
    if (!(IS_DATA_QUEUE_EMPTY(queue))) { 
        element = GET_QUEUE_HEAD(queue); 
        queue->head = (queue->head + 1) % HTC_DATA_REQUEST_RING_BUFFER_SIZE; 
        queue->size -= 1; 
 
        HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                        "removeFromMboxQueue (index: %d, size: %d, bufferElement: 0x%p, bufferElement->buffer: 0x%p, bufferElement->cookie: 0x%p)\n", queue->head, queue->size, element, (GET_MBOX_BUFFER(element))->buffer, (GET_MBOX_BUFFER(element))->cookie); 
    } else { 
        element = NULL; 
    } 
    HTC_DEBUG_PRINTF(ATH_LOG_SYNC,  
                    "Critical Section (queue): UNLOCK at line %d in file %s\n", __LINE__, __FILE__); 
    A_MUTEX_UNLOCK(&instanceCS); 
 
    return element; 
} 
 
void 
flushMboxQueue(HTC_ENDPOINT *endPoint, 
               HTC_DATA_REQUEST_QUEUE *queue,  
               HTC_EVENT_ID eventId) 
{ 
    HTC_DATA_REQUEST_ELEMENT *curr; 
    HTC_EVENT_INFO eventInfo; 
    HTC_ENDPOINT_EVENT_TABLE *eventTable; 
    HTC_ENDPOINT_ID endPointId; 
    EVENT_TABLE_ELEMENT *eventElement; 
    HTC_MBOX_BUFFER *mboxBuffer; 
 
    eventTable = &endPoint->eventTable; 
    endPointId = GET_ENDPOINT_ID(endPoint); 
 
    /*  
     * Release the buffer to WMI using the registered event handler. If WMI  
     * has not registered any callbacks for a particular endpoint then it  
     * means that its queues will not have any buffers so we skip that  
     * endpoint. 
     */ 
    if ((eventElement = &eventTable->element[eventId]) != NULL) { 
        while ((curr = removeFromMboxQueue(queue)) != NULL) { 
            /* Frame the event and dispatch it */ 
            mboxBuffer = GET_MBOX_BUFFER(curr); 
            FRAME_EVENT(eventInfo, mboxBuffer->buffer,  
                        mboxBuffer->bufferLength, mboxBuffer->actualLength,  
                        A_ECANCELED, mboxBuffer->cookie); 
            if (eventElement->handler) { 
                eventElement->handler(endPoint->target, endPointId, eventId,  
                                      &eventInfo, eventElement->param); 
            } 
            RECYCLE_DATA_REQUEST_ELEMENT(curr); 
        } 
    } 
 
    /* Initialize the head and tail pointer */ 
    queue->head = 0; 
    queue->size = 0; 
} 
 
HTC_REG_REQUEST_ELEMENT * 
allocateRegRequestElement(HTC_TARGET *target) { 
    A_UINT32 count; 
    HTC_REG_REQUEST_ELEMENT *element; 
 
    A_MUTEX_LOCK(&instanceCS); 
    element = NULL; 
    for (count = 0; count < HTC_REG_REQUEST_LIST_SIZE; count ++) { 
        element = &target->regList.element[count]; 
        if (IS_ELEMENT_FREE(element)) { 
            element->buffer.free = FALSE; 
            break; 
        } 
    } 
    A_MUTEX_UNLOCK(&instanceCS); 
 
    return element; 
} 
 
void 
freeRegRequestElement(HTC_REG_REQUEST_ELEMENT *element) { 
    A_MUTEX_LOCK(&instanceCS); 
    FILL_REG_BUFFER(element, NULL, 0, 0, 0); 
    element->buffer.free = TRUE; 
    A_MUTEX_UNLOCK(&instanceCS); 
} 
 
HTC_TARGET * 
getTargetInstance(void *device) 
{ 
    return AtherosTargetList[0]; 
} 
 
void 
addTargetInstance(HTC_TARGET *target) 
{ 
    AtherosTargetList[0] = target; 
} 
 
void 
delTargetInstance(HTC_TARGET *target) 
{ 
    AtherosTargetList[0] = NULL; 
} 
 
A_UINT32  
getRegAddr(TARGET_REGISTERS base,  
           HTC_ENDPOINT_ID endPointId)  
{ 
    A_UINT32 address; 
 
    switch(base) { 
    case TX_CREDIT_COUNTER_RESET_REG: 
        address = COUNT_DEC_ADDRESS + endPointId * 4; 
        break; 
 
    case TX_CREDIT_COUNTER_DECREMENT_REG: 
        address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + endPointId) * 4; 
        break; 
 
    case TX_CREDIT_COUNTER_REG: 
        address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + endPointId) * 4; 
        break; 
 
    case INT_STATUS_ENABLE_REG: 
        address = INT_STATUS_ENABLE_ADDRESS; 
        break; 
 
    case ERROR_STATUS_ENABLE_REG: 
		address = ERROR_STATUS_ENABLE_ADDRESS; 
		break; 
 
    case COUNTER_INT_STATUS_ENABLE_REG: 
    case COUNTER_INT_STATUS_DISABLE_REG: 
        address = COUNTER_INT_STATUS_ENABLE_ADDRESS; 
        break; 
 
    case INT_STATUS_REG: 
        address = HOST_INT_STATUS_ADDRESS; 
        break; 
 
    case CPU_INT_STATUS_REG: 
        address = CPU_INT_STATUS_ADDRESS; 
        break; 
 
    case ERROR_INT_STATUS_REG: 
        address = ERROR_INT_STATUS_ADDRESS; 
        break; 
 
    case INT_WLAN_REG: 
        address = INT_WLAN_ADDRESS; 
        break; 
 
    case WINDOW_DATA_REG: 
        address = WINDOW_DATA_ADDRESS; 
        break; 
 
    case WINDOW_WRITE_ADDR_REG: 
        address = WINDOW_WRITE_ADDR_ADDRESS; 
        break; 
 
    case WINDOW_READ_ADDR_REG: 
        address = WINDOW_READ_ADDR_ADDRESS; 
        break; 
 
    default: 
        HTC_DEBUG_PRINTF(ATH_LOG_ERR, "Invalid register: %d\n", base); 
        AR_DEBUG_ASSERT(0); 
        address = 0; 
        break; 
    } 
 
    return address; 
} 
 
void 
dumpBytes(A_UCHAR *buffer, A_UINT16 length) 
{ 
    A_CHAR stream[60]; 
    A_UINT32 i; 
    A_UINT16 offset, count; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Dumping %d Bytes : ------>\n", length); 
 
    count = 0; 
    offset = 0; 
    for(i = 0; i < length; i++) { 
        sprintf(stream + offset, "%2x ", buffer[i]); 
	count ++; 
	offset += 3; 
 
	if(count == 16) { 
	    count = 0; 
	    offset = 0; 
	    HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "[H]: %s\n", stream); 
	    A_MEMZERO(stream, 60); 
	} 
    } 
 
    if(offset != 0) { 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "[H]: %s\n", stream); 
    } 
} 
 
void 
dumpRegisters(HTC_TARGET *target) 
{ 
    HTC_REGISTER_TABLE *reg; 
 
    reg = &target->table; 
    HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "\n<------- Register Table -------->\n"); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Int Status:                0x%x\n", reg->host_int_status); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "CPU Int Status:            0x%x\n", reg->cpu_int_status); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Error Int Status:          0x%x\n", reg->error_int_status); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Counter Int Status:        0x%x\n", reg->counter_int_status); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Mbox Frame:                0x%x\n", reg->mbox_frame); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Rx Lookahead Valid:        0x%x\n", reg->rx_lookahead_valid); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Rx Lookahead 0:            0x%x\n", reg->rx_lookahead[ENDPOINT1]); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Rx Lookahead 1:            0x%x\n", reg->rx_lookahead[ENDPOINT2]); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Rx Lookahead 2:            0x%x\n", reg->rx_lookahead[ENDPOINT3]); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Rx Lookahead 3:            0x%x\n", reg->rx_lookahead[ENDPOINT4]); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Int Status Enable:         0x%x\n", reg->int_status_enable); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "Counter Int Status Enable: 0x%x\n", reg->counter_int_status_enable); 
	HTC_DEBUG_PRINTF(ATH_LOG_DUMP, "<------------------------------->\n"); 
} 
 
A_UINT8 
htcGetBitNumSet(A_UINT32 data) 
{ 
    A_UINT8 count; 
 
    count = 0; 
    while(!(data % 2)) { 
        count += 1; 
        data >>= 1; 
    } 
 
    return count; 
}