[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;
+}