📄 hostctrl.c
字号:
}
else
{
if (val & OHCI_HC_RH_DESCRIPTOR_A_NPS)
{
val &= ~OHCI_HC_RH_DESCRIPTOR_A_NPS;
val |= OHCI_HC_RH_DESCRIPTOR_A_PSM;
}
}
break;
case OHCI_HC_RH_DESCRIPTOR_B:
val = OTG242HC_ReadReg(hc, OTG242HC_RH_DESCRIPTOR_B);
break;
case OHCI_HC_RH_STATUS:
val = OTG242HC_ReadReg(hc, OTG242HC_RH_STATUS);
break;
case OHCI_HC_RH_PORT_STATUS(1):
val = OTG242HC_ReadReg(hc, OTG242HC_RH_PORT_STATUS(1));
#if OTG242HC_PORTCHANGE_FIX
val |= OTG242HC_PortCSC[0] & OTG242HC_RH_PORT_STATUS_CSC;
#endif
break;
case OHCI_HC_RH_PORT_STATUS(2):
val = OTG242HC_ReadReg(hc, OTG242HC_RH_PORT_STATUS(2));
#if OTG242HC_PORTCHANGE_FIX
val |= OTG242HC_PortCSC[1] & OTG242HC_RH_PORT_STATUS_CSC;
#endif
break;
case OHCI_HC_RH_PORT_STATUS(3):
val = 0;
break;
case 0x60:
val = OTG242HC_ReadReg(hc, OTG242_CLOCK_CONTROL);
break;
case 0x64:
val = OTG242HC_ReadReg(hc, OTG242_RESET_CONTROL);
break;
default:
OS_DEBUG_MSG2(OS_ZONE_ERR, "Unknown OHCI register 0x%0x\r\n", index);
break;
}
return val;
}
void Ohci_PM_WriteRegister(unsigned long* reg, U32 val)
{
U32 index;
Otg242Hc *hc;
U32 tmp;
tmp = (U32)reg;
index = tmp & 0x7F;
tmp = (tmp & ~0x7F) + OTG242HC_HC_BASE;
hc = (Otg242Hc*)(*((U32*)tmp));
switch (index)
{
case OHCI_HC_REVISION:
break;
case OHCI_HC_CTRL:
*reg = val;
OTG242HC_WriteReg
(
hc,
OTG242HC_CTRL,
OTG242HC_CTRL_HCFS_FROM_OHCI(val) | OTG242HC_CTRL_RWE_FROM_OHCI(val)
);
if ((val & OHCI_HC_CTRL_HCFS) == OHCI_HC_CTRL_HCFS_OPERATIONAL)
{
OTG242HC_Operational(hc);
}
break;
case OHCI_HC_CMD_STATUS:
OTG242HC_CommandStatusWrite(hc, (U32*)reg, val);
break;
case OHCI_HC_INTR_STATUS:
*reg &= ~val;
break;
case OHCI_HC_INTR_ENABLE:
*reg |= val;
hc->intrEnable |= val & ~(OHCI_HC_INTR_STATUS_OC | OHCI_HC_INTR_STATUS_MIE);
OTG242HC_WriteReg( hc, OTG242HC_INTR_ENABLE, hc->intrEnable);
break;
case OHCI_HC_INTR_DISABLE:
hc->ohciReg[OHCI_HC_INTR_ENABLE / sizeof(U32)] &= ~val;
hc->intrEnable &= ~val;
/* SOF and Port Status Change interrupts should remain on */
hc->intrEnable |= OTG242HC_INTR_START_OF_FRAME |
OTG242HC_INTR_ROOT_HUB_STATUS_CHANGE;
OTG242HC_WriteReg( hc, OTG242HC_INTR_ENABLE, hc->intrEnable);
break;
case OHCI_HC_HCCA:
#if HC_MASS_STORAGE_NEW
hc->hcca = (U32 *)OS_PhysicalToVirtual((void*)val);
#else
hc->hcca = (U32 *)OS_PhysicalToVirtual(val);
#endif
*reg = val;
break;
case OHCI_HC_PERIOD_CURRENT_ED:
break;
case OHCI_HC_CTRL_HEAD_ED:
*reg = val;
break;
case OHCI_HC_CTRL_CURRENT_ED:
if (!(hc->ohciReg[OHCI_HC_CTRL / sizeof(U32)] & OHCI_HC_CTRL_CLE))
{
*reg = val;
}
break;
case OHCI_HC_BULK_HEAD_ED:
*reg = val;
break;
case OHCI_HC_BULK_CURRENT_ED:
if (!(hc->ohciReg[OHCI_HC_CTRL / sizeof(U32)] & OHCI_HC_CTRL_BLE))
{
*reg = val;
}
break;
case OHCI_HC_DONE_HEAD:
break;
case OHCI_HC_FM_INTERVAL:
OTG242HC_WriteReg(hc, OTG242_FRAMEINTERVAL, val);
break;
case OHCI_HC_FM_REMAINING:
break;
case OHCI_HC_FM_NUMBER:
break;
case OHCI_HC_PERIODIC_START:
*reg = val;
break;
case OHCI_HC_LS_THRESHOLD:
OTG242HC_WriteReg(hc, OTG242HC_LS_THRESHOLD, val);
break;
case OHCI_HC_RH_DESCRIPTOR_A:
if (val & OHCI_HC_RH_DESCRIPTOR_A_PSM)
{
if (0 == (val & OHCI_HC_RH_DESCRIPTOR_A_NPS))
{
val &= ~OHCI_HC_RH_DESCRIPTOR_A_PSM;
val |= OHCI_HC_RH_DESCRIPTOR_A_NPS;
}
}
else
{
if (val & OHCI_HC_RH_DESCRIPTOR_A_NPS)
{
val &= ~OHCI_HC_RH_DESCRIPTOR_A_NPS;
val |= OHCI_HC_RH_DESCRIPTOR_A_PSM;
}
}
*reg = val;
OTG242HC_WriteReg(hc, OTG242HC_RH_DESCRIPTOR_A, val);
break;
case OHCI_HC_RH_DESCRIPTOR_B:
*reg = val;
OTG242HC_WriteReg(hc, OTG242HC_RH_DESCRIPTOR_B, val);
break;
case OHCI_HC_RH_STATUS:
OTG242HC_RhStatusWrite(hc, val);
break;
case OHCI_HC_RH_PORT_STATUS(1):
#if OTG242HC_PORTCHANGE_FIX
val &= ~OTG242HC_RH_PORT_STATUS_CSC;
OTG242HC_PortCSC[0] &= ~OTG242HC_RH_PORT_STATUS_CSC;
#endif
OTG242HC_WriteReg(hc, OTG242HC_RH_PORT_STATUS(1), val);
break;
case OHCI_HC_RH_PORT_STATUS(2):
#if OTG242HC_PORTCHANGE_FIX
val &= ~OTG242HC_RH_PORT_STATUS_CSC;
OTG242HC_PortCSC[1] &= ~OTG242HC_RH_PORT_STATUS_CSC;
#endif
OTG242HC_WriteReg(hc, OTG242HC_RH_PORT_STATUS(2), val);
break;
case OHCI_HC_RH_PORT_STATUS(3):
break;
case 0x60:
{
/* Write the higher 16 bits first. */
U16* address = (U16*)((U8*)hc->regBase + OTG242_CLOCK_CONTROL);
U16 lowPart = (U16)(val & 0xFFFF);
U16 highPart = (U16)((val >> 16) & 0xFFFF);
HW_WriteOtg242Register16((U16*)hc->regBase, (U32)(((U16*)OTG242_CLOCK_CONTROL) + 1), highPart);
HW_WriteOtg242Register16((U16*)hc->regBase, (U32)OTG242_CLOCK_CONTROL, lowPart);
}
break;
case 0x64:
OTG242HC_WriteReg(hc, OTG242_RESET_CONTROL, val);
break;
default:
OS_DEBUG_MSG3(OS_ZONE_ERR, "Write to Unknown OHCI register 0x%0x with 0x%0x\r\n", index, val);
break;
}
}
void OTG242HC_RhStatusWrite(Otg242Hc *hc, U32 val)
{
U32 desc;
U32 i;
U32 status;
OTG242HC_WriteReg(hc, OTG242HC_RH_STATUS, val);
if (val & (OHCI_HC_RH_STATUS_LPS | OHCI_HC_RH_STATUS_LPSC))
{
if (val & OHCI_HC_RH_STATUS_LPS)
{
/* Clear port power, and disable port */
status = OTG242HC_RH_PORT_STATUS_CCS | OTG242HC_RH_PORT_STATUS_LSDA;
}
else
{
/* Set port power and enable port */
status = OTG242HC_RH_PORT_STATUS_PES | OTG242HC_RH_PORT_STATUS_PPS;
}
desc = hc->ohciReg[OHCI_HC_RH_DESCRIPTOR_A / sizeof(U32)];
if (desc & OHCI_HC_RH_DESCRIPTOR_A_PSM)
{
U32 pos;
pos = OHCI_HC_RH_DESCRIPTOR_B_PPCM0;
/* Check each port to determine if that port should be set/clear */
desc = hc->ohciReg[OHCI_HC_RH_DESCRIPTOR_B / sizeof(U32)];
for (i = 1; i <= OTG242HC_RH_PORT_MAX; i++, pos <<= 1)
{
if (!(desc & pos))
{
OTG242HC_WriteReg(hc, OTG242HC_RH_PORT_STATUS(i), status);
}
}
}
else
{
for (i = 1; i <= OTG242HC_RH_PORT_MAX; i++)
{
OTG242HC_WriteReg(hc, OTG242HC_RH_PORT_STATUS(i), status);
}
}
}
}
void OTG242HC_CommandStatusWrite(Otg242Hc *hc, U32 *reg, U32 val)
{
U32 Read;
if (val & OHCI_HC_CMD_STATUS_HCR)
{
Read = OTG242HC_ReadReg(hc, OTG242HC_CTRL);
OTG242HC_WriteReg(hc, OTG242HC_CTRL, Read | OTG242HC_CMD_STATUS_HCR);
}
*reg |= val & ~OHCI_HC_CMD_STATUS_SOC;
if (val & OHCI_HC_CMD_STATUS_OCR)
{
hc->ohciReg[OHCI_HC_INTR_STATUS / sizeof(U32)] |= OHCI_HC_INTR_STATUS_OC;
}
}
#if HC_MASS_STORAGE_NEW
void OTG242HC_CancelEtd(Otg242Hc *hc)
{
OhciEd* ed;
Otg242EtdBank* etd;
U32 slot;
U32 ped;
for (slot = 0, etd = hc->etdBank; slot < OTG242ETD_MAX; slot++, etd++)
{
if (NULL == etd->ed)
{
continue;
}
switch (etd->type)
{
case EpTypeIntr:
for (slot = 0; slot < 0x20; slot++)
{
ped = *(hc->hcca + slot);
if (0 == ped)
{
continue;
}
for
(
ed = (OhciEd*)OS_PhysicalToVirtual((void*)ped);
ed;
ped = ed->nextEd,
ed = (OHCIED_IsEof(ped)) ? 0 :
(OhciEd*)OS_PhysicalToVirtual((void*)(ped & OHCIED_POINTER))
)
{
if (etd->ed == ed)
{
break;
}
}
if (NULL != ed)
{
break;
}
}
break;
case EpTypeIsoc:
ped = *(hc->hcca + slot);
if (0 == ped)
{
continue;
}
for
(
ed = (OhciEd*)OS_PhysicalToVirtual((void*)ped);
ed;
ped = ed->nextEd,
ed = (OHCIED_IsEof(ped)) ? 0 :
(OhciEd*)OS_PhysicalToVirtual((void*)(ped & OHCIED_POINTER))
)
{
if (etd->ed == ed)
{
break;
}
}
break;
case EpTypeCtrl:
ped = OTG242HC_GetHcControlHeadEd(hc);
for
(
ed = (OhciEd*)OS_PhysicalToVirtual((void*)ped);
ed;
ped = ed->nextEd,
ed = (OHCIED_IsEof(ped)) ? 0 :
(OhciEd*)OS_PhysicalToVirtual((void*)(ped & OHCIED_POINTER))
)
{
if (etd->ed == ed)
{
break;
}
}
break;
case EpTypeBulk:
ped = OTG242HC_GetHcBulkHeadEd(hc);
for
(
ed = (OhciEd*)OS_PhysicalToVirtual((void*)ped);
ed;
ped = ed->nextEd,
ed = (OHCIED_IsEof(ped)) ? 0 :
(OhciEd*)OS_PhysicalToVirtual((void*)(ped & OHCIED_POINTER))
)
{
if (etd->ed == ed)
{
break;
}
}
break;
default:
continue;
}
if (NULL == ed || (ed->desc & OHCIED_SKIP || ed->headP & OHCIED_HALTED))
{
OS_DEBUG_MSG3(OS_ZONE_INTR, "OTG243HC_CancelEtd index=%d ed=%x cancelled\r\n", slot, etd->ed);
if( OTG242ETD_ReadReg(etd, OTG242HC_ETD_ENABLE) & (1 << slot) )
{
OTG242ETD_WriteReg( etd, OTG242HC_ETD_ENABLE, (1 << slot));
}
OTG242ETD_Free(etd);
}
}
}
#endif
U32 OTG242HC_IntrHandler(Otg242Hc *hc)
{
S32 index;
U32 status;
U32 val;
U32 ohciIntStatus;
U32 doneQueue;
U32 doneHead;
U32 oldOhciStatus;
U32 etdIntrStatusX, etdIntrStatusY;
U32 pos;
Otg242EtdBank* etd;
OhciTd* td;
U32 Read;
status = OTG242HC_ReadReg(hc, OTG242HC_INTR_STATUS);
OTG242HC_WriteReg(hc, OTG242HC_INTR_STATUS,
status & ~OTG242HC_INTR_WRITE_DONE_HEAD);
status &= hc->intrEnable ;
etdIntrStatusX = OTG242HC_ReadReg(hc, OTG242HC_XBUFFERINTERRUPTSTATUS);
etdIntrStatusY = OTG242HC_ReadReg(hc, OTG242HC_YBUFFERINTERRUPTSTATUS);
etdIntrStatusX &= hc->etdIntrEnable;
etdIntrStatusY &= hc->etdIntrEnable;
if (etdIntrStatusX || etdIntrStatusY)
{
if( etdIntrStatusX )
{
OTG242HC_WriteReg(hc, OTG242HC_XBUFFERINTERRUPTSTATUS, etdIntrStatusX);
}
if( etdIntrStatusY )
{
OTG242HC_WriteReg(hc, OTG242HC_YBUFFERINTERRUPTSTATUS, etdIntrStatusY);
}
pos = 0x1;
index = 0;
while (etdIntrStatusX)
{
if (etdIntrStatusX & pos)
{
OTG242ETD_NextPacket(&hc->etdBank[index]);
etdIntrStatusX &= ~pos;
}
pos <<= 1;
index++;
}
pos = 0x1;
index = 0;
while (etdIntrStatusY)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -