📄 hostctrl.c
字号:
if (etdIntrStatusY & pos)
{
OTG242ETD_NextPacket(&hc->etdBank[index]);
etdIntrStatusY &= ~pos;
}
pos <<= 1;
index++;
}
}
ohciIntStatus= 0;
hc->frameNo = OTG242HC_ReadReg(hc, OTG242HC_FRAME_NUMBER);
if (NULL != hc->hcca)
{
*OTG242HC_HCCA_FRAME_NUMBER(hc) = (U16)hc->frameNo;
}
/***********************************************************
Receiving Resume detect event.
************************************************************/
if (status & OTG242HC_INTR_RESUME_DETECT)
{
OS_DEBUG_MSG1(OS_ZONE_INIT, "Otg242Hc: HC resume S32\r\n");
ohciIntStatus |= OHCI_HC_INTR_STATUS_RD;
}
/************************************************************
if there was an interrupt due to a completed TD list, or
a lingering TD from an IRP cancel is on the Done queue and
must be removed before we signal the client driver
************************************************************/
if (status & OTG242HC_INTR_WRITE_DONE_HEAD)
{
/* Return pointer to done ETD */
doneQueue = OTG242HC_ReadReg(hc, OTG242HC_ENDPOINTDONESTATUS);
if (doneQueue)
{
for (index = 0, pos = 1; index < OTG242ETD_MAX; index++, pos <<= 1)
{
if (doneQueue & pos)
{
/* Clear endpoint done status */
OTG242HC_WriteReg(hc, OTG242HC_ENDPOINTDONESTATUS, doneQueue & pos);
/* Clear endpoint done enable */
Read = OTG242HC_ReadReg(hc, OTG242HC_ETDDONEENABLE);
OTG242HC_WriteReg(hc, OTG242HC_ETDDONEENABLE, Read & ~(doneQueue & pos));
hc->etdIntrEnable &= ~(OTG242ETD_XYIntrEnable(index));
/* Adjust iso TD sequence */
etd = &hc->etdBank[index];
if (etd->nextEtd != NULL)
{
#if HC_MASS_STORAGE_NEW
td = (OhciTd*)OS_PhysicalToVirtual((void*)etd->nextEtd->td->nextTd);
#else
td = (OhciTd*)OS_PhysicalToVirtual(etd->nextEtd->td->nextTd);
#endif
if (td == etd->td)
{
etd = etd->nextEtd;
hc->etdIntrEnable &= ~(OTG242ETD_XYIntrEnable(etd->index));
OTG242ETD_EtdDone(etd);
doneQueue &= ~(1 << etd->index);
etd = &hc->etdBank[index];
}
}
OTG242ETD_EtdDone(etd);
doneQueue &= ~pos;
if (0 == doneQueue)
{
break;
}
}
}
}
OTG242HC_WriteReg(hc, OTG242HC_INTR_STATUS, OTG242HC_INTR_WRITE_DONE_HEAD);
}
doneHead = OTG242HC_GetHcDoneHead(hc);
if (doneHead)
{
oldOhciStatus = OTG242HC_GetHcIntrStatus(hc);
if (!(oldOhciStatus & OHCI_HC_INTR_STATUS_DH))
{
*OTG242HC_HCCA_DONE_HEAD(hc) = OTG242HC_GetHcDoneHead(hc);
OTG242HC_SetHcDoneHead(hc, 0);
if (status & ~OTG242HC_INTR_WRITE_DONE_HEAD)
{
*OTG242HC_HCCA_DONE_HEAD(hc) |= 1;
}
ohciIntStatus |= OHCI_HC_INTR_STATUS_DH;
}
else
{
OS_DEBUG_MSG1(OS_ZONE_INTR, "Otg242Hc: Previous DoneQueue not finished\r\n");
}
}
/*****************************************************************
this code must follow the HandleWriteback done code so that
all TD associated with the EDs listed in the removal procedures
are removed from the done list
*******************************************************************/
if (status & OTG242HC_INTR_START_OF_FRAME)
{
U32 control;
control = hc->ohciReg[OHCI_HC_CTRL / sizeof(U32)];
if ((control & OHCI_HC_CTRL_IE) && hc->freeEtdCount > 0)
{
OTG242HC_DoIsocList(hc);
}
if ((control & OHCI_HC_CTRL_PLE) && hc->freeEtdCount > 0)
{
OTG242HC_DoPeriodicList(hc);
}
if ((control & OHCI_HC_CTRL_CLE) && hc->freeEtdCount > 0)
{
OTG242HC_DoCtrlList(hc);
}
if ((control & OHCI_HC_CTRL_BLE) && hc->freeEtdCount > 0)
{
OTG242HC_DoBulkList(hc);
}
#if HC_MASS_STORAGE_NEW
OTG242HC_CancelEtd(hc);
#endif
ohciIntStatus |= OHCI_HC_INTR_STATUS_SF;
}
if (status & OTG242HC_INTR_ROOT_HUB_STATUS_CHANGE)
{
U32 hnpStatus;
/*
PRINTI1("Otg242Hc: RootHub Status Change\n");
*/
/********************************************************
This will happen when a mini A is plugged in and we
are in A_WAIT_BCON state. After checking this is
plugged to otg downstream port, we will enter A_HOST
state. we will enable the pull down resister and the
disable pull up resister, however those have set as
default. Sof is generated already This doesn't tally
with spec. Spec says SOF should only be generated
after entering A_HOST stage.
*********************************************************/
val = OTG242HC_ReadReg(hc, OTG242HC_RH_PORT_STATUS(OTG242HC_RH_OTG_PORT));
if (val & OTG242HC_RH_PORT_STATUS_CSC) /* Connect Status Change */
{
/*************************************************
We got a connection event on otg port, go to
host stage.
**************************************************/
if (val & OTG242HC_RH_PORT_STATUS_CCS) /* Cur Connect Status */
{
hnpStatus = OTG242HC_ReadReg(hc, OTG242HNP_CTRL);
OS_DEBUG_MSG2(OS_ZONE_INTR, "Otg242Hc:Connect on otg port 0x%08X\r\n", hnpStatus);
if ((hnpStatus & OTG242HNP_CTRL_HNP_STATE) == OTG242HNP_CTRL_HNP_A_VBUS_ERR)
{
/*********************************************
A temporary hnp condition vbus error, just
clear it by writing 1 to hnpcontrol status
*********************************************/
hnpStatus |= OTG242HNP_CTRL_CLEAR_ERROR;
OTG242HC_WriteReg(hc, OTG242HNP_CTRL, hnpStatus);
OS_DEBUG_MSG1(OS_ZONE_INTR, "Otg242Hc: ClearErr Restart Srp \r\n");
}
}
else
{
/********************************************************
We got a disconnection event on otg port, and we
are in A-DEVICE at this time, if we are in B-DEVICE,
we can't get this interrupt. Disconnection means a
transition to B-device, therefore, we need to power
off the otg port, and also remove the bus request.
********************************************************/
OS_DEBUG_MSG1(OS_ZONE_INTR, "Otg242Hc:Disconnect on otg port \r\n");
hnpStatus = OTG242HC_ReadReg(hc, OTG242HNP_CTRL);
hnpStatus &= ~OTG242HNP_CTRL_BUS_REQUEST;
OTG242HC_WriteReg(hc, OTG242HNP_CTRL, hnpStatus);
}
}
for( index = 0; index < OTG242HC_RH_PORT_MAX; index++ )
{
val = OTG242HC_ReadReg(hc,
OTG242HC_RH_PORT_STATUS(OTG242HC_RH_OTG_PORT+index));
val &= OTG242HC_RH_PORT_STATUS_CHANGE;
OTG242HC_PortStatusChange[index] |= val;
if(val)
{
OTG242HC_WriteReg(hc,
OTG242HC_RH_PORT_STATUS(OTG242HC_RH_OTG_PORT+index), val);
}
}
ohciIntStatus |= OHCI_HC_INTR_STATUS_RHSC;
}
if (status & OTG242HC_INTR_SCHEDULE_OVERRUN)
{
OS_DEBUG_MSG1(OS_ZONE_INTR, "Otg242Hc: Schedule overrun\r\n");
ohciIntStatus |= OHCI_HC_INTR_STATUS_SO;
}
if (status & OTG242HC_INTR_UNRECOVERABLE_ERROR)
{
OS_DEBUG_MSG1(OS_ZONE_INTR, "Otg242Hc: Unrecoverable Error\r\n");
ohciIntStatus |= OHCI_HC_INTR_STATUS_UE;
}
if (status & OTG242HC_INTR_FRAME_NO_OVERFLOW)
{
OS_DEBUG_MSG1(OS_ZONE_INTR, "Otg242Hc: Frame number overflow\r\n");
ohciIntStatus |= OHCI_HC_INTR_STATUS_FNO;
}
OTG242HC_SetHcIntrStatus(hc, ohciIntStatus);
return(0);
}
void OTG242HC_DoIsocList(Otg242Hc *hc)
{
OhciEd* ed;
OhciTd* td;
Otg242EtdBank* etd;
for
(
#if HC_MASS_STORAGE_NEW
ed = (OhciEd*)OS_PhysicalToVirtual((void*)(*(hc->hcca)));
#else
ed = (OhciEd*)OS_PhysicalToVirtual(*(hc->hcca));
#endif
ed;
ed = (OHCIED_IsEof(ed->nextEd)) ? 0 :
#if HC_MASS_STORAGE_NEW
(OhciEd*)OS_PhysicalToVirtual((void*)(ed->nextEd & OHCIED_POINTER))
#else
(OhciEd*)OS_PhysicalToVirtual(ed->nextEd & OHCIED_POINTER)
#endif
)
{
if ((ed->desc & OHCIED_SKIP) || !(ed->desc & OHCIED_FORMAT) ||
(ed->headP & OHCIED_HALTED))
{
continue;
}
if ((ed->headP & OHCIED_POINTER) == (ed->tailP & OHCIED_POINTER))
{
/* No TD for this ED */
continue;
}
#if HC_MASS_STORAGE_NEW
td = (OhciTd*)OS_PhysicalToVirtual((void*)(ed->headP & OHCIED_POINTER));
#else
td = (OhciTd*)OS_PhysicalToVirtual((U32)ed->headP & OHCIED_POINTER);
#endif
etd = OTG242ETD_IsInChip(hc->etdBank, ed);
if (NULL == etd)
{
/* Find TD, find an empty slot */
etd = OTG242ETD_Allocate(hc->etdBank);
if (NULL == etd)
{
/* Run out of ETDs */
break;
}
etd->ed = ed;
etd->td = td;
etd->type = EpTypeIsoc;
OTG242ETD_FillEtdIsoc(etd);
hc->etdIntrEnable |= OTG242ETD_XYIntrEnable(etd->index) ;
if (hc->freeEtdCount == 0)
{
/* Can't process more TD, exit */
return;
}
}
if (NULL != etd->nextEtd)
{
continue;
}
if (td->nextTd == (ed->tailP & OHCIED_POINTER))
{
continue;
}
etd->nextEtd = OTG242ETD_Allocate(hc->etdBank);
if (NULL == etd->nextEtd)
{
break;
}
etd->nextEtd->nextEtd = etd;
etd = etd->nextEtd;
etd->ed = ed;
#if HC_MASS_STORAGE_NEW
td = (OhciTd*)OS_PhysicalToVirtual((void*)td->nextTd);
#else
td = (OhciTd*)OS_PhysicalToVirtual((U32)td->nextTd);
#endif
etd->td = td;
etd->type = EpTypeIsoc;
OTG242ETD_FillEtdIsoc(etd);
hc->etdIntrEnable |= OTG242ETD_XYIntrEnable(etd->index) ;
if (hc->freeEtdCount == 0)
{
return;
}
}
}
U32 OTG242HC_DoList(Otg242Hc *hc, U32 startEd, EpType type)
{
U32 currentEd;
OhciEd* ed;
Otg242EtdBank* etd;
SctBool rc;
currentEd = startEd;
for
(
#if HC_MASS_STORAGE_NEW
ed = (OhciEd*)OS_PhysicalToVirtual((void*)currentEd);
#else
ed = (OhciEd*)OS_PhysicalToVirtual(currentEd);
#endif
ed;
currentEd = ed->nextEd,
ed = (OHCIED_IsEof(currentEd)) ? 0 :
#if HC_MASS_STORAGE_NEW
(OhciEd*)OS_PhysicalToVirtual((void*)(currentEd & OHCIED_POINTER))
#else
(OhciEd*)OS_PhysicalToVirtual(currentEd & OHCIED_POINTER)
#endif
)
{
if (ed->desc & OHCIED_SKIP)
{
continue;
}
if (ed->headP & OHCIED_HALTED)
{
continue;
}
if ((ed->headP & OHCIED_POINTER) == (ed->tailP & OHCIED_POINTER) ||
(ed->headP & OHCIED_POINTER) == 0)
{
/* No TD for this ED */
continue;
}
if (type == EpTypeCtrl)
{
OTG242HC_AddHcCommandStatus(hc, OHCI_HC_CMD_STATUS_CLF);
}
else
{
OTG242HC_AddHcCommandStatus(hc, OHCI_HC_CMD_STATUS_BLF);
}
etd = OTG242ETD_IsInChip(hc->etdBank, ed);
if (etd != NULL)
{
continue;
}
/* Find TD, find an empty slot */
etd = OTG242ETD_Allocate(hc->etdBank);
if (NULL == etd)
{
/* Run out of ETDs */
return currentEd;
}
etd->ed = ed;
#if HC_MASS_STORAGE_NEW
etd->td = (OhciTd*)OS_PhysicalToVirtual((void*)(ed->headP & OHCIED_POINTER));
#else
etd->td = (OhciTd*)OS_PhysicalToVirtual((U32)ed->headP & OHCIED_POINTER);
#endif
etd->type = type;
rc = OTG242ETD_FillEtd(etd);
if (rc == SCC_FALSE)
{
/* Run out of memory etc. */
OTG242ETD_Free(etd);
return currentEd;
}
hc->etdIntrEnable |= OTG242ETD_XYIntrEnable(etd->index) ;
if (hc->freeEtdCount == 0)
{
/* Can't process more TD, exit */
return currentEd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -