www.pudn.com > CEWifiDriverAR6000-21374.zip > htc_events.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 routines handling the different events and callbacks 
// from the hardware interface layer. 
// 
// Author(s): ="Atheros" 
//============================================================================== 
  
 
#include "htc_internal.h" 
 
/* ------ Global Variable Declarations ------- */ 
extern A_MUTEX_T instanceCS, counterCS, creditCS,txCS; 
extern A_WAITQUEUE_HEAD htcEvent; 
 
#ifdef DEBUG 
extern A_UINT32 debughtc; 
extern A_UINT32 txcreditsavailable[HTC_MAILBOX_NUM_MAX]; 
extern A_UINT32 txcreditsconsumed[HTC_MAILBOX_NUM_MAX]; 
extern A_UINT32 txcreditintrenable[HTC_MAILBOX_NUM_MAX]; 
extern A_UINT32 txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX]; 
#endif 
 
extern A_UINT32 tx_complete[HTC_MAILBOX_NUM_MAX]; /* Num of tx complete */ 
 
/* ------ Static Variables ------ */ 
 
 
/* ------ Functions ------ */ 
 
 
A_STATUS htcInterruptEnabler(HIF_DEVICE *device) { 
 
	A_STATUS status; 
    A_UINT32 address; 
    HIF_REQUEST request; 
	HTC_TARGET *target; 
	HTC_REG_REQUEST_ELEMENT *element; 
 
    target = getTargetInstance(device); 
    AR_DEBUG_ASSERT(target != NULL); 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC,  
                    "htcInterruptEnabler Enter target: 0x%p\n", target); 
 
	target->table.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) | 
                                      INT_STATUS_ENABLE_CPU_SET(0x01) | 
                                      INT_STATUS_ENABLE_COUNTER_SET(0x01) | 
                                      INT_STATUS_ENABLE_MBOX_DATA_SET(0x0F); 
	/* Reenable Dragon Interrupts */ 
	element = allocateRegRequestElement(target); 
    AR_DEBUG_ASSERT(element != NULL); 
#ifdef ONLY_16BIT 
    FILL_REG_BUFFER(element, (A_UINT16 *)&target->table.int_status_enable, 2,  
                    INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); 
#else 
    FILL_REG_BUFFER(element, &target->table.int_status_enable, 1,  
                    INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); 
#endif 
 
	HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_ASYNCHRONOUS,  
                      HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); 
    address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); 
#ifdef ONLY_16BIT 
    status = HIFReadWrite(target->device, address,  
                          &target->table.int_status_enable, 2,  
                          &request, element); 
#else 
    status = HIFReadWrite(target->device, address,  
                          &target->table.int_status_enable, 1,  
                          &request, element); 
#endif 
 
#ifndef HTC_SYNC 
	AR_DEBUG_ASSERT(status == A_OK); 
#else 
	AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING); 
	if ( status == A_OK ) { 
		element->completionCB(element, status); 
	} 
#endif //HTC_SYNC 
 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC,"htcInterruptEnabler Exit\n"); 
 
	return A_OK; 
} 
 
A_STATUS 
htcRWCompletionHandler(void *context,  
                       A_STATUS status) 
{ 
    HTC_QUEUE_ELEMENT *element; 
 
    element = (HTC_QUEUE_ELEMENT *)context; 
    AR_DEBUG_ASSERT(element != NULL); 
 
    return(element->completionCB(element, status)); 
} 
 
A_STATUS  
htcTxCompletionCB(HTC_DATA_REQUEST_ELEMENT *element, 
                  A_STATUS status)  
{ 
    HTC_TARGET *target; 
    HTC_ENDPOINT_ID endPointId; 
    HTC_ENDPOINT *endPoint; 
    HTC_EVENT_INFO eventInfo; 
    HTC_MBOX_BUFFER *mboxBuffer; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND,  
                    "htcTxCompletionCB - Enter\n"); 
 
    /* Get the context */ 
    mboxBuffer = GET_MBOX_BUFFER(element); 
    AR_DEBUG_ASSERT(mboxBuffer != NULL); 
    endPoint = mboxBuffer->endPoint; 
    AR_DEBUG_ASSERT(endPoint != NULL); 
    target = endPoint->target; 
    AR_DEBUG_ASSERT(target != NULL); 
    endPointId = GET_ENDPOINT_ID(endPoint); 
 
    HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_SEND, 
                    "mboxBuffer: 0x%p, buffer: 0x%p, endPoint(%d): 0x%p, target: 0x%p\n", mboxBuffer, mboxBuffer->buffer, endPointId, endPoint, target); 
 
    /* Return the buffer to the user if the transmission was not successful */ 
    if (status != A_OK) { 
        HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_SEND,  
                        "Frame transmission failed\n"); 
        HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_SEND,  
                        "EndPoint: %d, Tx credits available: %d\n",  
                         endPointId, GET_TX_CREDITS_AVAILABLE(endPoint)); 
        /*  
         * In the failure case it is possible that while queueing of the  
         * request itself it returned an error status in which case we  
         * would have dispatched an event and freed the element there  
         * itself. Ideally if it failed to queue the request then it  
         * should not generate a callback but we are being a little  
         * conservative. 
         */ 
        if (!(IS_ELEMENT_FREE(element))) { 
            mboxBuffer->buffer += HTC_HEADER_LEN; 
            FRAME_EVENT(eventInfo, mboxBuffer->buffer,  
                        mboxBuffer->bufferLength, mboxBuffer->actualLength,  
                        A_ECANCELED, mboxBuffer->cookie); 
            RECYCLE_DATA_REQUEST_ELEMENT(element); 
            dispatchEvent(target, endPointId, HTC_BUFFER_SENT, &eventInfo); 
            HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND,  
                            "htcTxCompletionCB - Exit\n"); 
        } 
        return A_OK; 
    } 
 
    HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_SEND,  
                    "Frame transmission complete\n"); 
 
    /*  
     * The user should see the actual length and buffer length 
     * to be the same. In case of block mode, we use the actual length 
     * parameter to reflect the total number of bytes transmitted after 
     * padding. 
     */ 
    mboxBuffer->actualLength = mboxBuffer->bufferLength; 
    mboxBuffer->buffer += HTC_HEADER_LEN; 
 
    /*  
     * Return the transmit buffer to the user through the HTC_BUFFER_SENT  
     * event indicating that the frame was transmitted successfully. 
     */ 
    FRAME_EVENT(eventInfo, mboxBuffer->buffer, mboxBuffer->bufferLength,  
                mboxBuffer->actualLength, A_OK, mboxBuffer->cookie); 
    RECYCLE_DATA_REQUEST_ELEMENT(element); 
 
    tx_complete[endPointId] += 1; 
 
    dispatchEvent(target, endPointId, HTC_BUFFER_SENT, &eventInfo); 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND,  
                    "htcTxCompletionCB - Exit\n"); 
 
    return A_OK; 
} 
 
A_STATUS 
htcBlkSzNegCompletionCB(HTC_DATA_REQUEST_ELEMENT *element, 
                        A_STATUS status) 
{ 
    HTC_TARGET *target; 
    HTC_ENDPOINT *endPoint; 
    HIF_REQUEST request; 
    HTC_MBOX_BUFFER *mboxBuffer; 
    HTC_REG_REQUEST_ELEMENT *regElement; 
    A_UINT32 address; 
 
    /* Get the context */ 
    mboxBuffer = GET_MBOX_BUFFER(element); 
    AR_DEBUG_ASSERT(mboxBuffer != NULL); 
    endPoint = mboxBuffer->endPoint; 
    AR_DEBUG_ASSERT(endPoint != NULL); 
    target = endPoint->target; 
    AR_DEBUG_ASSERT(target != NULL); 
 
    /* Recycle the request element */ 
    RECYCLE_DATA_REQUEST_ELEMENT(element); 
    element->completionCB = htcTxCompletionCB; 
 
    if (status == A_OK) { 
        /* Mark the state to be ready */ 
        endPoint->enabled = TRUE; 
         
        /* Set the state of the target as ready */ 
        if (target->endPoint[ENDPOINT1].enabled && 
            target->endPoint[ENDPOINT2].enabled && 
            target->endPoint[ENDPOINT3].enabled && 
            target->endPoint[ENDPOINT4].enabled ) 
        { 
            /* Send the INT_WLAN interrupt to the target */ 
            target->table.int_wlan = 1; 
            HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO,  
                              HIF_ASYNCHRONOUS, HIF_BYTE_BASIS,  
                              HIF_FIXED_ADDRESS); 
            address = getRegAddr(INT_WLAN_REG, ENDPOINT_UNUSED); 
            regElement = allocateRegRequestElement(target); 
            AR_DEBUG_ASSERT(regElement != NULL); 
            FILL_REG_BUFFER(regElement, &target->table.int_wlan, sizeof(target->table.int_wlan), 
                            INT_WLAN_REG, ENDPOINT_UNUSED); 
            status = HIFReadWrite(target->device, address,  
                                  (A_UCHAR *)&target->table.int_wlan,  
                                  sizeof(target->table.int_wlan), &request, regElement); 
#ifndef HTC_SYNC 
            AR_DEBUG_ASSERT(status == A_OK); 
#else 
			AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING); 
			if(status == A_OK) { 
				regElement->completionCB(regElement, status); 
			} 
#endif 
        } 
    } 
 
    return A_OK; 
} 
 
A_STATUS 
htcRxCompletionCB(HTC_DATA_REQUEST_ELEMENT *element,  
                  A_STATUS status) 
{ 
    HTC_TARGET *target; 
    HTC_ENDPOINT *endPoint; 
    HTC_EVENT_INFO eventInfo; 
    HTC_ENDPOINT_ID endPointId; 
    HTC_MBOX_BUFFER *mboxBuffer; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV,  
                    "htcRxCompletionCB - Enter\n"); 
 
    /* Get the context */ 
    mboxBuffer = GET_MBOX_BUFFER(element); 
    AR_DEBUG_ASSERT(mboxBuffer != NULL); 
    endPoint = mboxBuffer->endPoint; 
    AR_DEBUG_ASSERT(endPoint != NULL); 
    target = endPoint->target; 
    AR_DEBUG_ASSERT(target != NULL); 
    endPointId = GET_ENDPOINT_ID(endPoint); 
 
    HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_RECV, 
                    "mboxBuffer: 0x%p, buffer: 0x%p, endPoint(%d): 0x%p, target: 0x%p\n", mboxBuffer, mboxBuffer->buffer, endPointId, endPoint, target); 
 
    /* Return the buffer to the user if the reception was not successful */ 
    if (status != A_OK) { 
        HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_RECV,  
                        "Frame reception failed\n"); 
        /*  
         * In the failure case it is possible that while queueing of the  
         * request itself it returned an error status in which case we  
         * would have dispatched an event and freed the element there  
         * itself. Ideally if it failed to queue the request then it  
         * should not generate a callback but we are being a little  
         * conservative. 
         */ 
        if (!(IS_ELEMENT_FREE(element))) { 
            mboxBuffer->actualLength = 0; 
            mboxBuffer->buffer += HTC_HEADER_LEN; 
            FRAME_EVENT(eventInfo, mboxBuffer->buffer,  
                        mboxBuffer->bufferLength, mboxBuffer->actualLength,  
                        A_ECANCELED, mboxBuffer->cookie); 
            RECYCLE_DATA_REQUEST_ELEMENT(element); 
            dispatchEvent(target, endPointId, HTC_BUFFER_RECEIVED, &eventInfo); 
            HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV,  
                            "htcRxCompletionCB - Exit\n"); 
        } 
        return A_OK; 
    } 
 
    HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_RECV,  
                    "Frame reception complete\n"); 
 
    HTC_DEBUG_PRINTBUF(mboxBuffer->buffer, (A_UINT16)mboxBuffer->actualLength); 
 
    /*  
     * Advance the pointer by the size of HTC header and pass the payload 
     * pointer to the upper layer. 
     */ 
    mboxBuffer->actualLength = ((mboxBuffer->buffer[0] << 0) |  
                                (mboxBuffer->buffer[1] << 8)); 
    mboxBuffer->buffer += HTC_HEADER_LEN; 
 
    /*  
     * Frame the HTC_BUFFER_RECEIVED to the upper layer indicating that the  
     * packet has been succesfully received. 
     */ 
    FRAME_EVENT(eventInfo, mboxBuffer->buffer, mboxBuffer->bufferLength,  
                mboxBuffer->actualLength, A_OK, mboxBuffer->cookie); 
 
    /* Recycle the bufferElement structure */ 
    RECYCLE_DATA_REQUEST_ELEMENT(element); 
 
    /* Dispatch the event */ 
    dispatchEvent(target, endPointId, HTC_BUFFER_RECEIVED, &eventInfo); 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV,  
                    "htcRxCompletion - Exit\n"); 
 
    return A_OK; 
} 
 
A_STATUS 
htcRegCompletionCB(HTC_REG_REQUEST_ELEMENT *element, 
                   A_STATUS status)  
{ 
    A_STATUS ret; 
    HTC_TARGET *target; 
    HTC_ENDPOINT *endPoint; 
    HTC_REG_BUFFER *regBuffer; 
#ifdef ONLY_16BIT 
    A_UINT16 txCreditsConsumed; 
    A_UINT16 txCreditsAvailable; 
#else 
    A_UINT8 txCreditsConsumed; 
    A_UINT8 txCreditsAvailable; 
#endif 
    HTC_ENDPOINT_ID endPointId; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND | ATH_LOG_RECV,  
                    "htcRegCompletion - Enter\n"); 
    AR_DEBUG_ASSERT(status == A_OK); 
 
    /* Get the context */ 
    AR_DEBUG_ASSERT(element != NULL); 
    regBuffer = GET_REG_BUFFER(element); 
    AR_DEBUG_ASSERT(regBuffer != NULL); 
    target = regBuffer->target; 
    AR_DEBUG_ASSERT(target != NULL); 
 
    /* Identify the register and the operation responsible for the callback */ 
    ret = A_OK; 
    switch(regBuffer->base) { 
    case TX_CREDIT_COUNTER_DECREMENT_REG: 
        HTC_DEBUG_PRINTF(ATH_LOG_INF, "TX_CREDIT_COUNTER_DECREMENT_REG\n"); 
        endPointId = regBuffer->offset; 
        endPoint = &target->endPoint[endPointId]; 
 
        HTC_DEBUG_PRINTF(ATH_LOG_SYNC, 
                        "Critical Section (credit): LOCK at line %d in file %s\n", __LINE__, __FILE__); 
        A_MUTEX_LOCK(&creditCS); 
 
        /* Calculate the number of credits available */ 
#ifdef ONLY_16BIT 
        AR_DEBUG_ASSERT((GET_TX_CREDITS_CONSUMED(endPoint)*2) == regBuffer->length); 
#else 
       	AR_DEBUG_ASSERT(GET_TX_CREDITS_CONSUMED(endPoint) == regBuffer->length); 
#endif 
        AR_DEBUG_ASSERT(regBuffer->buffer[0] >=  
                        GET_TX_CREDITS_CONSUMED(endPoint)); 
        SET_TX_CREDITS_AVAILABLE(endPoint, regBuffer->buffer[0] -  
                                 GET_TX_CREDITS_CONSUMED(endPoint)); 
        SET_TX_CREDITS_CONSUMED(endPoint, 0); 
        txCreditsAvailable = GET_TX_CREDITS_AVAILABLE(endPoint); 
        txCreditsConsumed = GET_TX_CREDITS_CONSUMED(endPoint); 
        HTC_DEBUG_PRINTF(ATH_LOG_SYNC, 
                        "Critical Section (credit): UNLOCK at line %d in file %s\n", __LINE__, __FILE__); 
        A_MUTEX_UNLOCK(&creditCS); 
 
        HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_SEND,  
                        "Pulling %d tx credits from the target\n",  
                        txCreditsAvailable); 
 
#ifdef DEBUG 
        txcreditsavailable[endPointId] = txCreditsAvailable; 
        txcreditsconsumed[endPointId] = txCreditsConsumed; 
#endif /* DEBUG */ 
 
        if (txCreditsAvailable) { 
            htcSendFrame(endPoint); 
        } else { 
            /*  
             * Enable the Tx credit counter interrupt so that we can get the 
             * credits posted by the target. 
             */ 
 
            htcEnableCreditCounterInterrupt(target, endPointId); 
 
#ifdef DEBUG 
            txcreditintrenable[endPointId] += 1; 
            txcreditintrenableaggregate[endPointId] += 1; 
#endif /* DEBUG */ 
        } 
        break; 
 
    case TX_CREDIT_COUNTER_RESET_REG: 
        HTC_DEBUG_PRINTF(ATH_LOG_INF, "TX_CREDIT_COUNTER_RESET_REG\n"); 
        endPointId = regBuffer->offset; 
 
        /*  
         * Enable the Tx credit counter interrupt so that we can get the 
         * credits posted by the target. 
         */ 
        htcEnableCreditCounterInterrupt(target, endPointId); 
 
#ifdef DEBUG 
        txcreditintrenable[endPointId] += 1; 
        txcreditintrenableaggregate[endPointId] += 1; 
#endif /* DEBUG */ 
        break; 
 
    case COUNTER_INT_STATUS_ENABLE_REG: 
        HTC_DEBUG_PRINTF(ATH_LOG_INF, "COUNTER_INT_STATUS_ENABLE: 0x%x\n", 
                        target->table.counter_int_status_enable); 
        break; 
 
    case COUNTER_INT_STATUS_DISABLE_REG: 
        HTC_DEBUG_PRINTF(ATH_LOG_INF, "COUNTER_INT_STATUS_DISABLE:0x%x\n", 
                        target->table.counter_int_status_enable); 
		 
        HIFAckInterrupt(target->device); 
        HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcDSRHandler - ACK\n"); 
        break; 
 
 
    case INT_WLAN_REG: 
        HTC_DEBUG_PRINTF(ATH_LOG_INF, "INT_WLAN: 0x%x\n", 
                        target->table.int_wlan); 
        target->table.int_wlan = 0; 
 
        /* Mark the target state as ready and signal the waiting sem */ 
        target->ready = TRUE; 
        A_WAKE_UP(&htcEvent); 
        break; 
 
	case INT_STATUS_ENABLE_REG: 
        HTC_DEBUG_PRINTF(ATH_LOG_INF, "INT_STATUS_ENABLE: 0x%x\n", 
                        target->table.int_status_enable); 
        break; 
 
 
    default: 
        HTC_DEBUG_PRINTF(ATH_LOG_ERR,  
                        "Invalid register address: %d\n", regBuffer->base); 
    } 
 
    /* Free the register request structure */ 
    freeRegRequestElement(element); 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcRegCompletion - Exit\n"); 
 
    return ret; 
} 
 
 
A_STATUS 
htcTargetInsertedHandler(HIF_DEVICE *device) 
{ 
    HTC_TARGET *target; 
    HTC_ENDPOINT *endPoint; 
    A_UINT8 count1, count2; 
    HTC_EVENT_INFO eventInfo; 
    HTC_REG_BUFFER *regBuffer; 
    HTC_QUEUE_ELEMENT *element; 
    HTC_MBOX_BUFFER *mboxBuffer; 
    HTC_REG_REQUEST_LIST *regList; 
    HTC_DATA_REQUEST_QUEUE *sendQueue, *recvQueue; 
	HIF_REQUEST request; 
	A_STATUS status; 
    A_UINT32 address; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcTargetInserted - Enter\n"); 
 
    /* Initialize the locks */ 
    A_MUTEX_INIT(&instanceCS); 
    A_MUTEX_INIT(&creditCS); 
    A_MUTEX_INIT(&counterCS); 
    A_MUTEX_INIT(&txCS); 
 
    /* Allocate target memory */ 
    if ((target = (HTC_TARGET *)A_MALLOC(sizeof(HTC_TARGET))) == NULL) { 
        HTC_DEBUG_PRINTF(ATH_LOG_ERR, "Unable to allocate memory\n"); 
        return A_ERROR; 
    } 
    A_MEMZERO(target, sizeof(HTC_TARGET)); 
    target->device = device; 
    target->ready = FALSE; 
 
    /* Initialize the endpoints, mbox queues, event table */ 
    for (count1 = ENDPOINT1; count1 <= ENDPOINT4; count1 ++) { 
        endPoint = &target->endPoint[count1]; 
        HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                        "endPoint[%d]: %p\n", count1, endPoint); 
        A_MEMZERO(endPoint->txCreditsAvailable, HTC_TX_CREDITS_NUM_MAX); 
        endPoint->txCreditsConsumed = 0; 
        endPoint->txCreditsIntrEnable = FALSE; 
        endPoint->rxLengthPending = 0; 
        endPoint->target = target; 
        endPoint->enabled = FALSE; 
        for (count2 = 0; count2sendQueue; 
            sendQueue->head = sendQueue->size = 0; 
            element = &sendQueue->element[count2]; 
            A_MEMZERO(element, sizeof(HTC_DATA_REQUEST_ELEMENT)); 
            element->buffer.free = TRUE; 
            element->completionCB = htcTxCompletionCB; 
            mboxBuffer = GET_MBOX_BUFFER(element); 
            mboxBuffer->endPoint = endPoint; 
 
            /* Receive Queue */ 
            recvQueue = &endPoint->recvQueue; 
            recvQueue->head = recvQueue->size = 0; 
            element = &recvQueue->element[count2]; 
            A_MEMZERO(element, sizeof(HTC_DATA_REQUEST_ELEMENT)); 
            element->buffer.free = TRUE; 
            element->completionCB = htcRxCompletionCB; 
            mboxBuffer = GET_MBOX_BUFFER(element); 
            mboxBuffer->endPoint = endPoint; 
        } 
        A_MEMZERO(&target->endPoint[count1].eventTable,  
                  sizeof(HTC_ENDPOINT_EVENT_TABLE)); 
    } 
 
    /* Populate the block size for each of the end points */ 
    endPoint = &target->endPoint[ENDPOINT1]; 
    endPoint->blockSize = HIF_MBOX0_BLOCK_SIZE; 
    endPoint = &target->endPoint[ENDPOINT2]; 
    endPoint->blockSize = HIF_MBOX1_BLOCK_SIZE; 
    endPoint = &target->endPoint[ENDPOINT3]; 
    endPoint->blockSize = HIF_MBOX2_BLOCK_SIZE; 
    endPoint = &target->endPoint[ENDPOINT4]; 
    endPoint->blockSize = HIF_MBOX3_BLOCK_SIZE; 
 
    /* Initialize the shadow copy of the target register table */ 
    A_MEMZERO(&target->table, sizeof(HTC_REGISTER_TABLE)); 
 
    /* Initialize the register request list */ 
    regList = &target->regList; 
    for (count1 = 0; count1 < HTC_REG_REQUEST_LIST_SIZE; count1 ++) { 
        element = ®List->element[count1]; 
        A_MEMZERO(element, sizeof(HTC_REG_REQUEST_ELEMENT)); 
        element->buffer.free = TRUE; 
        element->completionCB = htcRegCompletionCB; 
        regBuffer = GET_REG_BUFFER(element); 
        regBuffer->target = target; 
    } 
 
    /* Add the target instance to the global list */ 
    addTargetInstance(target); 
 
    /* Disable all the dragon interrupts */ 
    target->table.int_status_enable = 0; 
    target->table.cpu_int_status_enable = 0; 
    target->table.error_status_enable = 0; 
    target->table.counter_int_status_enable = 0; 
    HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, 
                      HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS); 
    address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); 
    status = HIFReadWrite(target->device, address,  
                          &target->table.int_status_enable, 4, &request, NULL); 
    AR_DEBUG_ASSERT(status == A_OK); 
 
    /*  
     * Frame a TARGET_AVAILABLE event and send it to the host. Return the 
     * HIF_DEVICE handle as a parameter with the event. 
     */ 
    FRAME_EVENT(eventInfo, (A_UCHAR *)device, sizeof(HIF_DEVICE *),  
                sizeof(HIF_DEVICE *), A_OK, NULL); 
    dispatchEvent(target, ENDPOINT_UNUSED, HTC_TARGET_AVAILABLE, &eventInfo); 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcTargetInserted - Exit\n"); 
 
    return A_OK; 
} 
 
A_STATUS 
htcTargetRemovedHandler(HIF_DEVICE *device) 
{ 
    HTC_TARGET *target; 
    HTC_EVENT_INFO eventInfo; 
 
    /* Get the target instance bound to this device */ 
    target = getTargetInstance(device); 
 
    if (target != NULL) { 
        /* Frame a TARGET_UNAVAILABLE event and send it to the host */ 
        FRAME_EVENT(eventInfo, NULL, 0, 0, A_OK, NULL); 
        dispatchEvent(target, ENDPOINT_UNUSED, HTC_TARGET_UNAVAILABLE,  
                      &eventInfo); 
    } 
 
    A_MUTEX_DESTROY(&txCS); 
    A_MUTEX_DESTROY(&counterCS); 
    A_MUTEX_DESTROY(&creditCS); 
    A_MUTEX_DESTROY(&instanceCS); 
        
    return A_OK; 
} 
 
/* For shared interrupts, it is unsafe to update the shadow copies of the int_status and int_status_enable values  
 * since, the ar6kisrhandler can be called at any time while the DSR is running due to shared nature of interrupts. 
 * Hence modified to simply read the values off the hardware directly  
 */ 
 
A_STATUS 
htcInterruptPending(HIF_DEVICE *device, A_BOOL *intPending) 
{ 
    A_STATUS status; 
    A_UINT32 address; 
    HTC_TARGET *target; 
    HIF_REQUEST request; 
    A_UCHAR      intStatus[2] = {0,0}; 
    A_UCHAR      intMask[2] = {0,0}; 
 
    target = getTargetInstance(device); 
    AR_DEBUG_ASSERT(target != NULL); 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC,  
                    "htcInterruptPending Enter target: 0x%p\n", target); 
 
    // get the current interrupt status register 
    HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, 
                      HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); 
    address = getRegAddr(INT_STATUS_REG, ENDPOINT_UNUSED); 
 
#ifdef ONLY_16BIT 
    status = HIFReadWrite(target->device, address,  
                          intStatus, 2, &request, NULL); 
#else 
    status = HIFReadWrite(target->device, address,  
                          intStatus, 1, &request, NULL); 
#endif 
    AR_DEBUG_ASSERT(status == A_OK); 
 
    // get the interrupt enable register value  
    HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, 
                      HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); 
 
    address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); 
 
#ifdef ONLY_16BIT 
    status = HIFReadWrite(target->device, address,  
                          intMask, 2, &request, NULL); 
#else 
    status = HIFReadWrite(target->device, address,  
                          intMask, 1, &request, NULL); 
#endif 
    AR_DEBUG_ASSERT(status == A_OK); 
     
     if (!((intMask[0] & intStatus[0]) == 0)) { 
        *intPending = TRUE; 
     } else { 
        *intPending = FALSE; 
     } 
	return A_OK; 
} 
 
 
A_STATUS 
htcInterruptDisabler(HIF_DEVICE *device,A_BOOL *callDsr) 
{ 
    A_STATUS status; 
    A_UINT32 address; 
    HTC_TARGET *target; 
    HIF_REQUEST request; 
    A_BOOL interruptPending; 
 
    target = getTargetInstance(device); 
    AR_DEBUG_ASSERT(target != NULL); 
	 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC,  
	                    "htcInterruptDisabler Enter target: 0x%p\n", target); 
     
    // Check for spurious interrupt 
    status = htcInterruptPending (device, &interruptPending); 
		 
    if (!interruptPending){ 
        *callDsr=FALSE;  
    } else { 
	    /*  
         * Disable the interrupts from Dragon. 
         *  We do the interrupt servicing in the bottom half and reenable the 
         *  Dragon interrupts at the end of the bottom-half 
	     */ 
    
        target->table.int_status_enable = 0; 
        HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, 
                      HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); 
        address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); 
#ifdef ONLY_16BIT 
        status = HIFReadWrite(target->device, address,  
                          &target->table.int_status_enable, 2, &request, NULL); 
#else 
        status = HIFReadWrite(target->device, address,  
                          &target->table.int_status_enable, 1, &request, NULL); 
#endif 
        AR_DEBUG_ASSERT(status == A_OK); 
        *callDsr=TRUE; 
    } 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcInterruptDisabler: Exit\n"); 
    return A_OK; 
} 
 
A_STATUS 
htcDSRHandler(HIF_DEVICE *device) 
{ 
    A_STATUS status; 
    A_UINT32 address; 
    HTC_TARGET *target; 
    HIF_REQUEST request; 
    A_UCHAR host_int_status; 
 
    target = getTargetInstance(device); 
    AR_DEBUG_ASSERT(target != NULL); 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC,  
                    "htcDsrHandler: Enter (target: 0x%p\n", target); 
 
    /*  
     * Read the first 28 bytes of the HTC register table. This will yield us 
     * the value of different int status registers and the lookahead  
     * registers. 
     *    length = sizeof(int_status) + sizeof(cpu_int_status) +  
     *             sizeof(error_int_status) + sizeof(counter_int_status) +  
     *             sizeof(mbox_frame) + sizeof(rx_lookahead_valid) +  
     *             sizeof(hole) +  sizeof(rx_lookahead) + 
     *             sizeof(int_status_enable) + sizeof(cpu_int_status_enable) + 
     *             sizeof(error_status_enable) +  
     *             sizeof(counter_int_status_enable); 
     */ 
    HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS,  
                      HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS); 
    address = getRegAddr(INT_STATUS_REG, ENDPOINT_UNUSED); 
    status = HIFReadWrite(target->device, address,  
                          &target->table.host_int_status, 28,  
                          &request, NULL); 
    AR_DEBUG_ASSERT(status == A_OK); 
 
#ifdef DEBUG 
    dumpRegisters(target); 
#endif /* DEBUG */ 
     
    /* Update only those registers that are enabled */ 
	/* This is not required as we have Already checked for  
	 * spuriours interrupt in htcInterruptDisabler 
	 */ 
    host_int_status = target->table.host_int_status;// & 
                      //target->table.int_status_enable; 
		 
    HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                    "Valid interrupt source(s) in INT_STATUS: 0x%x\n",  
                    host_int_status); 
 
    if (HOST_INT_STATUS_CPU_GET(host_int_status)) { 
        /* CPU Interrupt */ 
        htcServiceCPUInterrupt(target); 
    } 
  
    if (HOST_INT_STATUS_ERROR_GET(host_int_status)) { 
        /* Error Interrupt */ 
        htcServiceErrorInterrupt(target); 
    } 
 
    if (HOST_INT_STATUS_MBOX_DATA_GET(host_int_status)) { 
        /* Mailbox Interrupt */ 
        htcServiceMailboxInterrupt(target); 
    } 
 
 
    if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) { 
        /* Counter Interrupt */ 
        htcServiceCounterInterrupt(target); 
    } else { 
        /* Ack the interrupt */ 
        HIFAckInterrupt(target->device); 
 
    } 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcDSRHandler: Exit\n"); 
    return A_OK; 
} 
 
void 
htcServiceCPUInterrupt(HTC_TARGET *target) 
{ 
    A_STATUS status; 
    A_UINT32 address; 
    HIF_REQUEST request; 
    A_UINT8 cpu_int_status; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_INF, "CPU Interrupt\n"); 
    cpu_int_status = target->table.cpu_int_status & 
                     target->table.cpu_int_status_enable; 
    AR_DEBUG_ASSERT(cpu_int_status); 
    HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                    "Valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n", 
                    cpu_int_status); 
 
    /* Figure out the interrupt number */ 
    HTC_DEBUG_PRINTF(ATH_LOG_INF, "Interrupt Number: 0x%x\n",  
                    htcGetBitNumSet(cpu_int_status)); 
 
    /* Clear the interrupt */ 
    target->table.cpu_int_status = cpu_int_status; /* W1C */ 
    HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS,  
                      HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); 
    address = getRegAddr(CPU_INT_STATUS_REG, ENDPOINT_UNUSED); 
    status = HIFReadWrite(target->device, address,  
                          &target->table.cpu_int_status, 1, &request, NULL); 
 
    AR_DEBUG_ASSERT(status == A_OK); 
} 
 
 
void 
htcServiceErrorInterrupt(HTC_TARGET *target) 
{ 
    A_STATUS status; 
    A_UINT32 address; 
    HIF_REQUEST request; 
    A_UINT8 error_int_status; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_INF, "Error Interrupt\n"); 
    error_int_status = target->table.error_int_status & 
                       target->table.error_status_enable; 
    AR_DEBUG_ASSERT(error_int_status); 
    HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                    "Valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n", 
                    error_int_status); 
 
    if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) { 
        /* Wakeup */ 
        HTC_DEBUG_PRINTF(ATH_LOG_INF, "Wakeup\n"); 
    } 
         
    if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) { 
        /* Rx Underflow */ 
        HTC_DEBUG_PRINTF(ATH_LOG_INF, "Rx Underflow\n"); 
    } 
         
    if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) { 
        /* Tx Overflow */ 
        HTC_DEBUG_PRINTF(ATH_LOG_INF, "Tx Overflow\n"); 
    } 
 
    /* Clear the interrupt */ 
    target->table.error_int_status = error_int_status; /* W1C */ 
    HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS,  
                      HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); 
    address = getRegAddr(ERROR_INT_STATUS_REG, ENDPOINT_UNUSED); 
    status = HIFReadWrite(target->device, address,  
                          &target->table.error_int_status, 1, 
                          &request, NULL); 
 
    AR_DEBUG_ASSERT(status == A_OK); 
} 
 
void 
htcServiceCounterInterrupt(HTC_TARGET *target) 
{ 
    A_STATUS status; 
    A_UINT32 address; 
    HIF_REQUEST request; 
    HTC_ENDPOINT *endPoint; 
    HTC_ENDPOINT_ID endPointId; 
    A_UINT8 counter_int_status; 
    A_UINT8 reset_credit_int_status; 
    A_UINT8 update_credit_int_status; 
    HTC_REG_REQUEST_ELEMENT *element; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_INF, "Counter Interrupt\n"); 
 
    counter_int_status = target->table.counter_int_status & 
                         target->table.counter_int_status_enable; 
    AR_DEBUG_ASSERT(counter_int_status); 
    HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                    "Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", 
                    counter_int_status); 
 
    /* Service the reset credit counter interrupt */ 
    reset_credit_int_status = (counter_int_status & 0x0F); 
    while(reset_credit_int_status) { 
        endPointId = htcGetBitNumSet(reset_credit_int_status); 
        endPoint = &target->endPoint[endPointId]; 
        AR_DEBUG_ASSERT(endPoint != NULL); 
 
        HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                        "endPoint(%d): %p\n", endPointId, endPoint); 
 
        /* Initialize the number of credits available to zero */ 
	    HTC_DEBUG_PRINTF(ATH_LOG_SYNC, 
                   "Critical Section (credit): LOCK at line %d in file %s\n", __LINE__, __FILE__); 
		A_MUTEX_LOCK(&creditCS); 
        SET_TX_CREDITS_AVAILABLE(endPoint, 0); 
	    HTC_DEBUG_PRINTF(ATH_LOG_SYNC, 
                  "Critical Section (credit): UNLOCK at line %d in file %s\n", __LINE__, __FILE__); 
		A_MUTEX_UNLOCK(&creditCS); 
 
        /* Clear the interrupt */ 
        HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO,  
                          HIF_ASYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); 
        address = getRegAddr(TX_CREDIT_COUNTER_RESET_REG, endPointId); 
        element = allocateRegRequestElement(target); 
        AR_DEBUG_ASSERT(element != NULL); 
        FILL_REG_BUFFER(element, &endPoint->txCreditsAvailable[1], sizeof(endPoint->txCreditsAvailable[1]), 
                        TX_CREDIT_COUNTER_RESET_REG, endPointId); 
        status = HIFReadWrite(target->device, address,  
                              (A_UCHAR *)&endPoint->txCreditsAvailable[1], 
                              sizeof(endPoint->txCreditsAvailable[1]), &request, element); 
 
#ifndef HTC_SYNC 
        AR_DEBUG_ASSERT(status == A_OK); 
#else 
        AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING); 
		if (status == A_OK) { 
        	/* Enable the Tx credit counter interrupt so that we can get the 
             * credits posted by the target */ 
        	htcEnableCreditCounterInterrupt(target, endPointId); 
		} 
#endif 
        reset_credit_int_status &=  
            ~(1 << htcGetBitNumSet(reset_credit_int_status)); 
    } 
 
    /* Disable the credit counter interrupt */ 
    htcDisableCreditCounterInterrupt(target, ENDPOINT_UNUSED); 
 
    /* Service the credit counter interrupt */ 
    update_credit_int_status = counter_int_status & 0xF0; 
    while(update_credit_int_status) { 
        endPointId = htcGetBitNumSet(update_credit_int_status) -  
                     HTC_MAILBOX_NUM_MAX; 
        endPoint = &target->endPoint[endPointId]; 
        AR_DEBUG_ASSERT(endPoint != NULL); 
 
        /* This is the minimum number of credits that we would have got */ 
        AR_DEBUG_ASSERT(GET_TX_CREDITS_AVAILABLE(endPoint) == 0); 
	    HTC_DEBUG_PRINTF(ATH_LOG_SYNC, 
                   "Critical Section (credit): LOCK at line %d in file %s\n", __LINE__, __FILE__); 
		A_MUTEX_LOCK(&creditCS); 
        SET_TX_CREDITS_AVAILABLE(endPoint, 1); 
		HTC_DEBUG_PRINTF(ATH_LOG_SYNC, 
                   "Critical Section (credit): UNLOCK at line %d in file %s\n", __LINE__, __FILE__); 
		A_MUTEX_UNLOCK(&creditCS); 
 
 
#ifdef DEBUG 
        txcreditsavailable[endPointId] = GET_TX_CREDITS_AVAILABLE(endPoint); 
        txcreditintrenable[endPointId] -= 1; 
#endif /* DEBUG */ 
 
        HTC_DEBUG_PRINTF(ATH_LOG_INF, "Tx Credits Available: %d\n",  
                                        GET_TX_CREDITS_AVAILABLE(endPoint)); 
 
        if (!target->ready) { 
            htcSendBlkSize(endPoint); 
        } else { 
            htcSendFrame(endPoint); 
        } 
 
        update_credit_int_status &=  
            ~(1 << htcGetBitNumSet(update_credit_int_status)); 
    } 
} 
 
void 
htcEnableCreditCounterInterrupt(HTC_TARGET *target,  
                                HTC_ENDPOINT_ID endPointId) 
{ 
    A_STATUS status; 
    A_UINT32 address; 
    HIF_REQUEST request; 
    HTC_ENDPOINT *endPoint; 
    HTC_REG_REQUEST_ELEMENT *element; 
#ifdef ONLY_16BIT 
	A_UINT16 counter_int_enable16; 
#endif 
	A_UCHAR	counter_int_enable; 
 
 
    endPoint = &target->endPoint[endPointId]; 
    AR_DEBUG_ASSERT(endPoint != NULL); 
 
    A_MUTEX_LOCK(&counterCS); 
 
    endPoint->txCreditsIntrEnable = TRUE; 
    HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO,  
                      HIF_ASYNCHRONOUS, HIF_BYTE_BASIS,  
                      HIF_FIXED_ADDRESS); 
    element = allocateRegRequestElement(target); 
    AR_DEBUG_ASSERT(element != NULL); 
 
    counter_int_enable = ((target->endPoint[0].txCreditsIntrEnable << (4)) | 
                         (target->endPoint[1].txCreditsIntrEnable << (5)) | 
                         (target->endPoint[2].txCreditsIntrEnable << (6)) | 
                         (target->endPoint[3].txCreditsIntrEnable << (7)) | 
                         0x0F); 
	 
 
#ifdef ONLY_16BIT 
    counter_int_enable16 = (counter_int_enable << 8) | target->table.error_status_enable; 
 
    FILL_REG_BUFFER(element, NULL, 2, COUNTER_INT_STATUS_ENABLE_REG, counter_int_enable16); 
	address = getRegAddr(ERROR_STATUS_ENABLE_REG, ENDPOINT_UNUSED); 
    status = HIFReadWrite(target->device, address,  
                          (A_UCHAR *)&((GET_REG_BUFFER(element))->offset), 
                          2, &request, element); 
#else 
    FILL_REG_BUFFER(element, NULL, 1, COUNTER_INT_STATUS_ENABLE_REG, counter_int_enable); 
    address = getRegAddr(COUNTER_INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); 
    status = HIFReadWrite(target->device, address,  
                          (A_UCHAR *)&((GET_REG_BUFFER(element))->offset), 
                          1, &request, element); 
#endif 
 
#ifndef HTC_SYNC 
    AR_DEBUG_ASSERT(status == A_OK); 
#else 
    AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING); 
    if (status == A_OK) {  
        element->completionCB(element, status); 
    } 
#endif 
 
    A_MUTEX_UNLOCK(&counterCS); 
} 
 
void 
htcDisableCreditCounterInterrupt(HTC_TARGET *target,  
                                 HTC_ENDPOINT_ID unused) 
{ 
    A_STATUS status; 
    A_UINT32 address; 
    HIF_REQUEST request; 
    HTC_ENDPOINT *endPoint; 
    HTC_ENDPOINT_ID endPointId; 
    A_UINT8 update_credit_int_status; 
    HTC_REG_REQUEST_ELEMENT *element; 
#ifdef ONLY_16BIT 
	A_UINT16 counter_int_enable16; 
#endif 
	A_UCHAR	counter_int_enable; 
 
    A_MUTEX_LOCK(&counterCS); 
 
    /* The Tx credit counter update bits are reflected in the upper nibble */ 
    update_credit_int_status = target->table.counter_int_status & 0xF0; 
 
    while(update_credit_int_status) { 
        endPointId = htcGetBitNumSet(update_credit_int_status) -  
                     HTC_MAILBOX_NUM_MAX; 
        endPoint = &target->endPoint[endPointId]; 
        AR_DEBUG_ASSERT(endPoint != NULL); 
 
        HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                        "endPoint(%d): %p\n", endPointId, endPoint); 
 
        /* Disable the tx credit interrupt */ 
        endPoint->txCreditsIntrEnable = FALSE; 
 
        update_credit_int_status &=  
            ~(1 << htcGetBitNumSet(update_credit_int_status)); 
    } 
 
 
    HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_ASYNCHRONOUS,  
                      HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); 
 
    element = allocateRegRequestElement(target); 
    AR_DEBUG_ASSERT(element != NULL); 
 
    counter_int_enable = ((target->endPoint[0].txCreditsIntrEnable << (4)) | 
						 (target->endPoint[1].txCreditsIntrEnable << (5)) | 
						 (target->endPoint[2].txCreditsIntrEnable << (6)) | 
                         (target->endPoint[3].txCreditsIntrEnable << (7)) | 0x0F); 
 
#ifdef ONLY_16BIT 
    counter_int_enable16 = (counter_int_enable << 8) | target->table.error_status_enable; 
 
    FILL_REG_BUFFER(element, NULL, 2, COUNTER_INT_STATUS_DISABLE_REG,  
					counter_int_enable16); 
	address = getRegAddr(ERROR_STATUS_ENABLE_REG, ENDPOINT_UNUSED); 
    status = HIFReadWrite(target->device, address,  
                          (A_UCHAR *)&((GET_REG_BUFFER(element))->offset), 
                          2, &request, element); 
#else 
    FILL_REG_BUFFER(element, NULL, 1, COUNTER_INT_STATUS_DISABLE_REG,  
					counter_int_enable); 
	address = getRegAddr(COUNTER_INT_STATUS_DISABLE_REG, ENDPOINT_UNUSED); 
    status = HIFReadWrite(target->device, address,  
                          (A_UCHAR *)&((GET_REG_BUFFER(element))->offset), 
                          1, &request, element); 
#endif 
 
#ifndef HTC_SYNC 
    AR_DEBUG_ASSERT(status == A_OK); 
#else 
    AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING); 
	if ( status == A_OK ) { 
		element->completionCB(element, status); 
	} 
#endif 
 
    A_MUTEX_UNLOCK(&counterCS); 
} 
 
void 
htcServiceMailboxInterrupt(HTC_TARGET *target) 
{ 
    A_STATUS status; 
    A_UINT32 address; 
    HIF_REQUEST request; 
    HTC_ENDPOINT *endPoint; 
    HTC_ENDPOINT_ID endPointId; 
    A_UINT8 mailbox_int_status; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_INF, "Mailbox Interrupt\n"); 
 
    /* The Rx interrupt bits are reflected in the lower nibble */ 
    mailbox_int_status = target->table.host_int_status &  
                         HOST_INT_STATUS_MBOX_DATA_MASK; 
    HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                    "Valid mailbox interrupt source(s) in INT_STATUS: 0x%x\n", 
                    mailbox_int_status); 
 
    /* Disable the receive interrupt for all four mailboxes */ 
    target->table.int_status_enable &= ~(HOST_INT_STATUS_MBOX_DATA_MASK); 
 
    do { 
        while(mailbox_int_status) { 
            endPointId = htcGetBitNumSet(mailbox_int_status); 
            endPoint = &target->endPoint[endPointId]; 
            AR_DEBUG_ASSERT(endPoint != NULL); 
     
            HTC_DEBUG_PRINTF(ATH_LOG_INF,  
                            "endPoint(%d): %p\n", endPointId, endPoint); 
 
            /* Service the Rx interrupt */ 
            htcReceiveFrame(endPoint); 
            mailbox_int_status &= ~(1 << htcGetBitNumSet(mailbox_int_status)); 
        } 
 
        /*  
         * Read the register table again. Repeat the process until there are 
         * no more valid packets queued up on receive. It is assumed that 
         * the following request will be serialized along with the request 
         * above and will be completed in the order in which it is received 
         * by the bus driver. 
         */ 
        HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO,  
                          HIF_SYNCHRONOUS, HIF_BYTE_BASIS,  
                          HIF_INCREMENTAL_ADDRESS); 
        address = getRegAddr(INT_STATUS_REG, ENDPOINT_UNUSED); 
        status = HIFReadWrite(target->device, address,  
                              &target->table.host_int_status,  
                              24, &request, NULL); 
        AR_DEBUG_ASSERT(status == A_OK); 
 
        // Hack for CF card surprise removal crash. 
 
        if(target->table.host_int_status == 0xff) { 
            target->table.host_int_status = 0; 
            return; 
        } 
        mailbox_int_status = target->table.host_int_status &  
                             HOST_INT_STATUS_MBOX_DATA_MASK; 
    } while (mailbox_int_status); 
 
    target->table.int_status_enable |= HOST_INT_STATUS_MBOX_DATA_MASK; 
}