[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 *);