[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MiNT] Aw: Re: [PATCH] Make EHCI driver interrupt handler follow PCI-BIOS specification.



I have redone the patch.

Could someone with more experience with inline assembly (Alan, Vincent
or Markus) review again please? I'm concern with the asm keyword left
inside the C function.

Thanks
Index: sys/usb/src.km/ucd/ehci/SRCFILES
===================================================================
RCS file: /mint/freemint/sys/usb/src.km/ucd/ehci/SRCFILES,v
retrieving revision 1.1
diff -u -8 -r1.1 SRCFILES
--- sys/usb/src.km/ucd/ehci/SRCFILES	30 Apr 2014 19:59:29 -0000	1.1
+++ sys/usb/src.km/ucd/ehci/SRCFILES	10 Oct 2014 09:38:38 -0000
@@ -4,10 +4,11 @@
 HEADER = \
 	ehci.h \
 
 COBJS = \
 	ehci-hcd.c \
 	ehci-pci.c
 
 SSOBJS = \
+	ehci.S \
 
 SRCFILES = $(HEADER) $(COBJS) $(SSOBJS)
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	10 Oct 2014 09:38:38 -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	10 Oct 2014 09:38:38 -0000
@@ -58,16 +58,18 @@
 # define DEBUG(x)
 # define TRACE(x)
 # define ASSERT(x)	assert x
 
 #endif
 
 extern struct usb_module_api   *api;
 
+extern void ehci_int_handle_asm(void);
+
 /*
  * Function prototypes
  */
 long ehci_pci_init	(void *);
 void ehci_pci_stop	(struct ehci *);
 long ehci_pci_probe	(struct ucdif *);
 long ehci_pci_reset	(struct ehci *);
 void ehci_pci_error	(struct ehci *);
@@ -170,17 +172,17 @@
 		{
 			case PCI_VENDOR_ID_NEC: gehci->slot_name = "uPD720101"; break;
 			case PCI_VENDOR_ID_PHILIPS: gehci->slot_name = "isp1561"; break;
 			default: gehci->slot_name = "generic"; break;
 		}
 	}
 
 	/* hook interrupt handler */
-	Hook_interrupt(((struct ehci_pci *)gehci->bus)->handle, (void *)ehci_interrupt_handle, (unsigned long *)gehci);
+	Hook_interrupt(((struct ehci_pci *)gehci->bus)->handle, (void *)ehci_int_handle_asm, (unsigned long *)gehci);
 
 	return 0;
 }
 
 void ehci_pci_stop(struct ehci *gehci)
 {
 	Unhook_interrupt(((struct ehci_pci *)gehci->bus)->handle);
 }
@@ -258,8 +260,47 @@
 		}
 		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: parameter is in a0 */
+	asm volatile("move.l	a0,%0\n\t" : "=g"(ehci) : : "a0","memory");
+
+	/* 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();
+		}
+	}
+
+	/* Disable interrupt */
+	ehci_writel(&ehci->hcor->or_usbsts, status);
+
+	/* PCI_BIOS specification: if interrupt was for us set D0.0 */
+	return 1;
+}
Index: sys/usb/src.km/ucd/ehci/ehci.S
===================================================================
RCS file: sys/usb/src.km/ucd/ehci/ehci.S
diff -N sys/usb/src.km/ucd/ehci/ehci.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/usb/src.km/ucd/ehci/ehci.S	10 Oct 2014 09:38:38 -0000
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2014 David Galvez.
+ *
+ * This file belongs to FreeMiNT. It's not in the original MiNT 1.12
+ * distribution. See the file CHANGES for a detailed log of changes.
+ *
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+.global _ehci_interrupt_handle
+.global _ehci_int_handle_asm
+
+/* PCI_BIOS specification: only a0 and d0 are allowed 
+ * to be changed in interrupt handler, so we need to 
+ * preserve a1 and d1 since GCC use them too as scratch
+ * registers.
+ */
+
+_ehci_int_handle_asm:
+	move.l d1,-(SP)
+	move.l a1,-(SP)
+	jsr _ehci_interrupt_handle
+	move.l (SP)+,a1
+	move.l (SP)+,d1
+	rts
Index: sys/usb/src.km/ucd/ehci/ehci.h
===================================================================
RCS file: /mint/freemint/sys/usb/src.km/ucd/ehci/ehci.h,v
retrieving revision 1.4
diff -u -8 -r1.4 ehci.h
--- sys/usb/src.km/ucd/ehci/ehci.h	17 Jul 2014 10:42:04 -0000	1.4
+++ sys/usb/src.km/ucd/ehci/ehci.h	10 Oct 2014 09:38:38 -0000
@@ -198,17 +198,17 @@
 	unsigned short companion;
 };
 
 /* Functions prototypes */
 
 long ehci_hcd_init(void);
 long ehci_hcd_stop(void);
 long ehci_alloc_ucdif(struct ucdif **);
-long ehci_interrupt_handle(struct ehci *ehci);
+long ehci_interrupt_handle(void);
 
 /* Interface with bus/platform */
 
 struct ehci_bus {
 	long (*init)(void *);
 	void (*stop)(struct ehci *);
 	long (*probe)(struct ucdif *);
 	long (*reset)(struct ehci *);