struct XhciTrb {
UINT32 PtrLow;
UINT32 PtrHigh;
UINT32 Status;
UINT32 Control;
}
void
ProcessEvents ()
{
for (;;) {
//取得驱动软件维护的出队指针
UINT32 EvtDequeueIndx = Evts->DequeueIdx;
//取得CCS,Consumer Cycle State
UINT32 Cs = Evts->Cs;
//根据出队指针取出准备处理的Event Ring TRB
XhciTrb *EventTrb = Evts->Ring + EvtDequeueIdx;
//依据CCS判断取得的Event TRB是否有效。也就是CCS要等于PCS。
UINT32 Control = EventTrb->Control;
if ((control & TRB_C) != (cs ? 1 : 0)) {
return;
}
//取得Event TRB类型和Completion code
UINT32 EventType = TRB_TYPE(Control);
UINT32 CompletionCode = (EventTrb->Status >> 24) & 0xff;
//依据不同的Event TRB类型,区别处理。
switch (EventType) {
case EVENT_TRANSFER:
case EVENT_COMMAND_COMPLETE:
//取得产生此Event TRB相应的Command TRB或者Transfer TRB
struct XhciTrb *RingTrb = EventTrb->PtrLow;
//取得Command TRB或者Transfer TRB对应的Ring struct
struct XhciRing *Ring = XHCI_RING(RingTrb);
//取得命令或者传输Ring出队指针,并更新
RingDequeueIdx = RingTrb - Ring->Ring + 1;
Ring->DequeueIdx = RingDequeueIdx;
//取得输出传输结果
XhciTrb *RingEvt = &Ring->Evt;
MemCpy(RingEvt, EventTrb, sizeof(*EventTrb));
break;
case EVENT_PORT_STATUS_CHANGE:
......
}
//更新Event Ring出队指针,因为驱动软件作为consummer已经处理完此Event TRB
EvtDequeueIndx ++
if (EvtDequeueIndx == XHCI_RING_ITEMS) {
EvtDequeueIndx = 0;
Cs = Cs? 0:1;
Evts->Cs = Cs;
}
Evts->DequeueIdx = EvtDequeueIndx;
// 写入Event Ring Dequeue Pointer Register,ERDP
UINT32 Erdp = Evts->Ring + EvtDequeueIndx;
MmioWrite(ErdpLow, Erdp);
MmioWrite(ErdpHigh, 0);
}
}
更新时间:2024-08-19
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号