📄 htc_events.c
字号:
"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; count2<HTC_DATA_REQUEST_RING_BUFFER_SIZE; count2 ++) {
/* Send Queue */
sendQueue = &endPoint->sendQueue;
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -