[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[MiNT] [PATCH] Make EHCI driver interrupt handler follow PCI-BIOS specification.
In EHCI USB host driver when PCI-BIOS function hook_interrupt( ) is
used to install the interrupt vector the caller passes a parameter for
private use by the driver, when a interrupt occurs the PCI-BIOS
specification says that this parameter must be passed to the interrupt
handler in register A0, but under FireTOS PCI_BIOS it's passed in the
stack. So we fix the driver to follow PCI-BIOS specification.
Didier says that will modify FireTOS to follow the specification too
(it did before).
-----------------------------------------------------------------
Commit message:
Make interrupt handler compliant with PCI-BIOS specification instead
of following FireTOS PCI_BIOS behaviour, move the handler to
ehci-pci.c file because contains PCI specific code.
Index: sys/usb/src.km/ucd/ehci/ehci-hcd.c
===================================================================
RCS file: /mint/freemint/sys/usb/src.km/ucd/ehci/ehci-hcd.c,v
retrieving revision 1.5
diff -u -8 -r1.5 ehci-hcd.c
--- sys/usb/src.km/ucd/ehci/ehci-hcd.c 8 Oct 2014 07:41:09 -0000 1.5
+++ sys/usb/src.km/ucd/ehci/ehci-hcd.c 8 Oct 2014 09:28:43 -0000
@@ -863,47 +863,16 @@
unknown:
DEBUG(("requesttype=%x, request=%x, value=%x, index=%x, length=%x",
req->requesttype, req->request, le2cpu16(req->value), le2cpu16(req->index), le2cpu16(req->length)));
dev->act_len = 0;
dev->status = USB_ST_STALLED;
return -1;
}
-long ehci_interrupt_handle(struct ehci *ehci)
-{
- unsigned long status;
-
- /* flush caches */
- cpush(ehci, -1);
-
- status = ehci_readl(&ehci->hcor->or_usbsts);
- if(status & STS_PCD) /* port change detect */
- {
- unsigned long reg = ehci_readl(&ehci->hccr->cr_hcsparams);
- unsigned long i = HCS_N_PORTS(reg);
- while(i--)
- {
- unsigned long pstatus = ehci_readl(&ehci->hcor->or_portsc[i-1]);
- if(pstatus & EHCI_PS_PO)
- continue;
- if(ehci->companion & (1 << i))
- {
- /* Low speed device, give up ownership. */
- pstatus |= EHCI_PS_PO;
- ehci_writel(&ehci->hcor->or_portsc[i-1], pstatus);
- }
- else if((pstatus & EHCI_PS_CSC))
- usb_rh_wakeup();
- }
- }
- ehci_writel(&ehci->hcor->or_usbsts, status);
- return 1; /* clear interrupt, 0: disable interrupt */
-}
-
static void hc_free_buffers(struct ehci *ehci)
{
long i;
if(ehci->descriptor != NULL)
{
kfree(ehci->descriptor);
ehci->descriptor = NULL;
}
Index: sys/usb/src.km/ucd/ehci/ehci-pci.c
===================================================================
RCS file: /mint/freemint/sys/usb/src.km/ucd/ehci/ehci-pci.c,v
retrieving revision 1.3
diff -u -8 -r1.3 ehci-pci.c
--- sys/usb/src.km/ucd/ehci/ehci-pci.c 17 Jul 2014 10:42:04 -0000 1.3
+++ sys/usb/src.km/ucd/ehci/ehci-pci.c 8 Oct 2014 09:28:43 -0000
@@ -258,8 +258,57 @@
}
while(handle >= 0);
loop_counter++;
}
while(loop_counter <= 2); /* Number of card slots */
return 0;
}
+
+long ehci_interrupt_handle(void)
+{
+ struct ehci *ehci = NULL;
+ unsigned long status;
+
+ /* PCI_BIOS specification: only a0 and d0 are allowed
+ * to be changed in interrupt handler.
+ */
+ asm volatile("move.l d1,-(SP)\n\t" : : : );
+ asm volatile("move.l a1,-(SP)\n\t" : : : );
+
+ /* PCI_BIOS specification: parameter is in a0 */
+ asm volatile("move.l a0,%0\n\t" : "=g"(ehci) : : "a0");
+
+ /* flush caches */
+ cpush(ehci, -1);
+
+ status = ehci_readl(&ehci->hcor->or_usbsts);
+ if(status & STS_PCD) /* port change detect */
+ {
+ unsigned long reg = ehci_readl(&ehci->hccr->cr_hcsparams);
+ unsigned long i = HCS_N_PORTS(reg);
+ while(i--)
+ {
+ unsigned long pstatus = ehci_readl(&ehci->hcor->or_portsc[i-1]);
+ if(pstatus & EHCI_PS_PO)
+ continue;
+ if(ehci->companion & (1 << i))
+ {
+ /* Low speed device, give up ownership. */
+ pstatus |= EHCI_PS_PO;
+ ehci_writel(&ehci->hcor->or_portsc[i-1], pstatus);
+ }
+ else if((pstatus & EHCI_PS_CSC))
+ (*uinf->usb_rh_wakeup)();
+ }
+ }
+
+ /* Disable interrupt */
+ ehci_writel(&ehci->hcor->or_usbsts, status);
+
+ /* Restore registers */
+ asm volatile("move.l (SP)+,a1\n\t" : : : );
+ asm volatile("move.l (SP)+,d1\n\t" : : : );
+
+ /* PCI_BIOS specification: if interrupt was for us set D0.0 */
+ return 1;
+}