[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.
2014-10-10 12:34 GMT+02:00 Alan Hourihane <alanh@fairlite.co.uk>:
> On 10/10/14 10:49, David Gálvez wrote:
>> 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
> In _ehci_int_handle_asm: I'd probably do this....
>
> subq.l #8,sp
> movem.l d1/a1,(sp)
> move.l a0,-(sp)
> jsr _ehci_interrupt_handle
> addq.l #4,sp
> movem.l (sp),d1/a1
> addq.l #8,sp
> rts
>
> Then ehci_interrupt_handle can be declared like this...
>
> long ehci_interrupt_handle(long param)
> {
> struct ehci *ehci = (struct ehci *)param;
>
> ....
>
> Then you can remove the asm volatile keyword entirely.
>
OK, patch attached with that modification.
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 12:28:11 -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 12:28:12 -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 12:28:12 -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,44 @@
}
while(handle >= 0);
loop_counter++;
}
while(loop_counter <= 2); /* Number of card slots */
return 0;
}
+
+long ehci_interrupt_handle(long param)
+{
+ struct ehci *ehci = (struct ehci *)param;
+ 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();
+ }
+ }
+
+ /* 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 12:28:12 -0000
@@ -0,0 +1,41 @@
+/*
+ * 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:
+ subq.l #8,sp
+ movem.l d1/a1,(sp)
+ move.l a0,-(sp) // PCI_BIOS specification: parameter is in a0
+ jsr _ehci_interrupt_handle
+ addq.l #4,sp
+ movem.l (sp),d1/a1
+ addq.l #8,sp
+ 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 12:28:12 -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(long);
/* Interface with bus/platform */
struct ehci_bus {
long (*init)(void *);
void (*stop)(struct ehci *);
long (*probe)(struct ucdif *);
long (*reset)(struct ehci *);