Skip to content

Commit

Permalink
Fixed USBD for correctness and for compatibility with the PlayStation…
Browse files Browse the repository at this point in the history
… 3 PS2 BC mode:

1. Interrupts will be cleared with a simple write to their registers, instead of with a logical OR.
2. Added HCR timeout and a clone of the Sony code fragments that load a word from 0xBFC00000 into $zero.
  • Loading branch information
sp193 committed Sep 4, 2014
1 parent c5adad0 commit 6aa81f7
Showing 1 changed file with 20 additions and 7 deletions.
27 changes: 20 additions & 7 deletions iop/usb/usbd/src/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,14 +234,14 @@ void hcdProcessIntr(void) {

if (intrFlags & OHCI_INT_SO) {
dbg_printf("HC: Scheduling overrun\n");
memPool.ohciRegs->HcInterruptStatus |= OHCI_INT_SO;
memPool.ohciRegs->HcInterruptStatus = OHCI_INT_SO;
intrFlags &= ~OHCI_INT_SO;
}

HcTD *doneQueue = (HcTD*)((uint32)memPool.hcHCCA->DoneHead & ~0xF);
if (doneQueue) {
memPool.hcHCCA->DoneHead = NULL;
memPool.ohciRegs->HcInterruptStatus |= OHCI_INT_WDH;
memPool.ohciRegs->HcInterruptStatus = OHCI_INT_WDH;

// reverse queue
HcTD *prev = NULL;
Expand All @@ -265,20 +265,20 @@ void hcdProcessIntr(void) {
}

if (intrFlags & OHCI_INT_SF) {
memPool.ohciRegs->HcInterruptStatus |= OHCI_INT_SF;
memPool.ohciRegs->HcInterruptStatus = OHCI_INT_SF;
handleTimerList();
intrFlags &= ~OHCI_INT_SF;
}

if (intrFlags & OHCI_INT_UE) {
printf("HC: Unrecoverable error\n");
memPool.ohciRegs->HcInterruptStatus |= OHCI_INT_UE;
memPool.ohciRegs->HcInterruptStatus = OHCI_INT_UE;
intrFlags &= ~OHCI_INT_UE;
}

if (intrFlags & OHCI_INT_RHSC) {
dbg_printf("RHSC\n");
memPool.ohciRegs->HcInterruptStatus |= OHCI_INT_RHSC;
memPool.ohciRegs->HcInterruptStatus = OHCI_INT_RHSC;
handleRhsc();
intrFlags &= ~OHCI_INT_RHSC;
}
Expand All @@ -290,6 +290,13 @@ void hcdProcessIntr(void) {
}
}

static void PostIntrEnableFunction(void)
{
memPool.ohciRegs->HcInterruptDisable = OHCI_INT_MIE;
asm volatile("lw $zero, 0xffffffffbfc00000\n");
memPool.ohciRegs->HcInterruptEnable = OHCI_INT_MIE;
}

void hcdIrqThread(void *arg) {
u32 eventRes;
while (1) {
Expand All @@ -298,6 +305,7 @@ void hcdIrqThread(void *arg) {
usbdLock();
hcdProcessIntr();
EnableIntr(IOP_IRQ_USB);
PostIntrEnableFunction();
usbdUnlock();
}
}
Expand All @@ -308,12 +316,17 @@ int usbdIntrHandler(void *arg) {
}

int initHardware(void) {
unsigned int i;

dbg_printf("Host Controller...\n");
memPool.ohciRegs->HcInterruptDisable = ~0;
memPool.ohciRegs->HcCommandStatus = OHCI_COM_HCR;
memPool.ohciRegs->HcControl = 0;
while (memPool.ohciRegs->HcCommandStatus & OHCI_COM_HCR) {
// add timeout stuff

for (i=0; memPool.ohciRegs->HcCommandStatus & OHCI_COM_HCR; i++) {
if(i==1000) return -1;

asm volatile("lw $zero, 0xffffffffbfc00000\n");
}
dbg_printf("HC reset done\n");
*(volatile uint32*)0xBF801570 |= 0x800 << 16;
Expand Down

0 comments on commit 6aa81f7

Please sign in to comment.