GitLab has been upgraded to 13.3.6. If you encounter any issues mail code@riscosopen.org

Commit db8357fa authored by Jeffrey Lee's avatar Jeffrey Lee

Enable part one of the FIQ fix

Detail:
  This change enables the basic 'FIQ fix', where SOF interrupts are handled by a FIQ handler and all other interrupts are delegated to IRQ.
  During testing it was observed that when the FIQ fix was enabled, what appears to be the host-side VCHIQ process would randomly die. It could take anywhere from several seconds (including during ROM init) or several hours for this to happen.
  After much investigation it looks like the cause was the use of the MPHI peripheral as a mechanism to trigger an IRQ from the FIQ handler. Changing the code in dwc_otg_hcd_handle_intr() so that it 'flushes' MPHI more often (after every interrupt instead of after every 60) seemed to reduce the problem, while changing the IRQ generation mechanism to use a different IRQ source (e.g. timer) made the crash go away entirely
  In the end I've settled on the compromise of using the MPHI peripheral, but in a way in which we only need to poke it once on startup, instead of once for every desired IRQ. Once we have it generating an IRQ we then rely on masking/unmasking the IRQ in the interrupt controller to get the desired effect of downgrading FIQs to IRQs. See the RISCOS_FIQ_DOWNGRADE #define.
  Changed files:
  - c/cmodule - Use symbolic constant for the USB controller ID instead of a magic number. Get the MPHI details from HAL_USBControllerInfo. Pay attention to Service_ClaimFIQ/Service_ReleaseFIQ and enable/disable the FIQ fix as appropriate.
  - c/dwc_common_riscos - Disable some debug functions which were accidentally left in non-debug builds. Change work queue/tasklet thread initialisation to fix a deadlock issue seen on reboot.
  - c/dwc_otg_riscos - Set up the MPHI and enable/disable the FIQ handler as required
  - cmhg/modhead - Pay attention to Service_ClaimFIQ/Service_ReleaseFIQ
  - dwc/driver/c/dwc_otg_hcd_intr, dwc/driver/h/dwc_otg_mphi_fix - RISCOS_FIQ_DOWNGRADE code
  - dwc/dwc_common_port/h/dwc_os - Make sure __DWC_WARN, __DWC_ERROR, DWC_EXCEPTION are compiled out in non-debug builds
  - h/dwc_otg_riscos - declare extra functions/variables related to FIQ fix
  - s/regaccess - Routine to install the FIQ handler on the FIQ vector, and simple HAL call wrapper
Admin:
  Tested on Raspberry Pi
  Requires Kernel-5_35-4_79_2_227, BCM2835-0_34


Version 0.15. Tagged as 'DWCDriver-0_15'
parent 689a0ad0
/* (0.14)
/* (0.15)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.14
#define Module_MajorVersion_CMHG 0.15
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 01 Jun 2014
#define Module_Date_CMHG 19 Jun 2014
#define Module_MajorVersion "0.14"
#define Module_Version 14
#define Module_MajorVersion "0.15"
#define Module_Version 15
#define Module_MinorVersion ""
#define Module_Date "01 Jun 2014"
#define Module_Date "19 Jun 2014"
#define Module_ApplicationDate "01-Jun-14"
#define Module_ApplicationDate "19-Jun-14"
#define Module_ComponentName "DWCDriver"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/USB/Controllers/DWCDriver"
#define Module_FullVersion "0.14"
#define Module_HelpVersion "0.14 (01 Jun 2014)"
#define Module_LibraryVersionInfo "0:14"
#define Module_FullVersion "0.15"
#define Module_HelpVersion "0.15 (19 Jun 2014)"
#define Module_LibraryVersionInfo "0:15"
......@@ -47,6 +47,8 @@
#include "dwc_otg_riscos.h"
#include "dwc/driver/dwc_otg_hcd_if.h"
#include "dwc/driver/dwc_otg_regs.h"
#include "dwc/driver/dwc_otg_mphi_fix.h"
/*****************************************************************************
* Function prototypes - Private to this file
......@@ -65,8 +67,10 @@ static int instance = 0; /* Module instance no. */
static int* veneer_code = NULL; /* Pointer to USBDriver call veneer code */
static int hal_device = 0; /* Index of USB device in HAL */
static int device_number; /* IRQ number */
static int usb_device_number; /* USB IRQ number */
static void *dwc_base=NULL; /* HW registers */
static void *mphi_base=NULL; /* MPHI registers */
static int mphi_device_number; /* MPHI IRQ number */
int dma_offset; /* ARM phys addr -> DMA addr offset */
static dwc_softc_t dwc_soft; /* Bus device we register with USBDriver */
......@@ -180,7 +184,7 @@ static _kernel_oserror *init_driver()
if(e)
return e;
e = dwc_otg_riscos_init((const uint32_t *) dwc_base, device_number, &dwc_soft);
e = dwc_otg_riscos_init((const uint32_t *) dwc_base, (const uint8_t *) mphi_base, usb_device_number, mphi_device_number, &dwc_soft);
if(e)
{
dwc_common_riscos_shutdown();
......@@ -254,6 +258,8 @@ _kernel_oserror* module_init (const char *cmd_tail, int podule_base, void *pw)
void *hw;
int devno;
int dmaoffset;
void *hw_mphi;
int devno_mphi;
} usbinfo;
size_t usbinfolen;
......@@ -261,11 +267,13 @@ _kernel_oserror* module_init (const char *cmd_tail, int podule_base, void *pw)
hal_device, &usbinfo, sizeof usbinfo,
0, EntryNo_HAL_USBControllerInfo,
&usbinfolen);
if (!e && (usbinfolen == sizeof(usbinfo)) && usbinfo.type == 3)
if (!e && (usbinfolen == sizeof(usbinfo)) && usbinfo.type == HALUSBControllerType_SynopsysDWC)
{
device_number = usbinfo.devno;
usb_device_number = usbinfo.devno;
dwc_base = usbinfo.hw;
dma_offset = usbinfo.dmaoffset;
mphi_base = usbinfo.hw_mphi;
mphi_device_number = usbinfo.devno_mphi;
break;
}
else
......@@ -275,7 +283,7 @@ _kernel_oserror* module_init (const char *cmd_tail, int podule_base, void *pw)
return (_kernel_oserror*) "\0\0\0\0No DWC devices found";
} while (1);
dprintf (("", "Found DWC controller at %08x IRQ %d on device %d\n", dwc_base, device_number, hal_device));
dprintf (("", "Found DWC controller at %08x IRQ %d on device %d\n", dwc_base, usb_device_number, hal_device));
if ((veneer_code = init_veneer ()) == NULL)
{
......@@ -379,6 +387,28 @@ void module_services(int service_number, _kernel_swi_regs *r, void *pw)
usb_soft = NULL;
shutdown_driver();
}
break;
case Service_ClaimFIQ:
if(own_fiq_vector)
{
/* Someone is kicking us off the FIQ vector. How rude. */
dprintf(("","Service_ClaimFIQ\n"));
dwc_otg_riscos_release_fiq(&dwc_soft);
r->r[1] = Service_Serviced;
}
break;
case Service_ReleaseFIQ:
if(reclaim_fiq_vector)
{
dprintf(("","Service_ReleaseFIQ\n"));
dwc_otg_riscos_try_use_fiqs(&dwc_soft,false);
if(own_fiq_vector)
{
r->r[1] = Service_Serviced;
}
}
break;
default:break;
}
}
......@@ -409,15 +439,37 @@ int usb_irq_handler(_kernel_swi_regs *r, void *pw)
{
int ret;
#ifdef RISCOS_FIQ_DOWNGRADE
if(fiq_fix_enable)
{
/* Flag to the FIQ routine that we want the IRQ to be off */
fiq_downgrade.irq_masked = true;
}
#endif
/* Prevent recursion by masking the IRQ while we handle the interrupt */
_swix(OS_Hardware, _IN(0)|_INR(8,9), device_number, 0, EntryNo_HAL_IRQDisable);
_swix(OS_Hardware, _IN(0)|_INR(8,9), dwc_soft.device_number, 0, EntryNo_HAL_IRQDisable);
ret = dwc_otg_riscos_irq(&dwc_soft);
#ifdef RISCOS_FIQ_DOWNGRADE
if(fiq_fix_enable)
{
/* Flag to the FIQ routine that it can enable the IRQ again */
fiq_downgrade.irq_masked = false;
/* Re-enable the IRQ if we still have more work to do */
if(!fiq_downgrade.fiq_trigger)
{
return 0;
}
ret = 0;
}
#endif
if(!ret)
{
_swix(OS_Hardware, _IN(0)|_INR(8,9), device_number, 0, EntryNo_HAL_IRQClear);
_swix(OS_Hardware, _IN(0)|_INR(8,9), device_number, 0, EntryNo_HAL_IRQEnable);
_swix(OS_Hardware, _IN(0)|_INR(8,9), dwc_soft.device_number, 0, EntryNo_HAL_IRQClear);
_swix(OS_Hardware, _IN(0)|_INR(8,9), dwc_soft.device_number, 0, EntryNo_HAL_IRQEnable);
}
else
{
......
......@@ -71,6 +71,7 @@ dwc_bool_t DWC_IN_BH(void)
/* Diagnostic messages */
#ifdef DEBUG
void __DWC_WARN(char *format,...)
{
va_list a;
......@@ -87,7 +88,6 @@ void __DWC_ERROR(char *format,...)
va_end(a);
}
#ifdef DEBUG
void DWC_EXCEPTION(char *format,...)
{
ensure_irqs_off();
......@@ -522,6 +522,8 @@ dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
DWC_FREE(q);
return NULL;
}
q->idle = 0;
q->pollword = 1; /* Give it a kick on startup so that it can disable interrupts. If interrupts are left enabled it can cause problems when we try and shut down during Service_PreReset */
q->name = (name?DWC_STRDUP(name):0);
q->stack = stack;
stack->sc_mark = 0xF60690FF;
......@@ -537,6 +539,7 @@ dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
DWC_FREE(stack);
return NULL;
}
_swix(RT_Yield,_IN(1),&q->idle);
return q;
}
......@@ -920,12 +923,15 @@ _kernel_oserror *dwc_common_riscos_init(void)
LIST_INIT(&tasklets.list);
tasklets.stop = 0;
tasklets.stopped = 0;
tasklets.idle = 1;
tasklets.idle = 0;
tasklets.pollword = 1; /* Give it a kick on startup so that it can disable interrupts. If interrupts are left enabled it can cause problems when we try and shut down during Service_PreReset */
_kernel_stack_chunk *stack = (_kernel_stack_chunk *) tasklet_stack;
stack->sc_mark = 0xF60690FF;
stack->sc_size = THREAD_STACK_SIZE;
memcpy(stack+1, _kernel_current_stack_chunk()+1, 28);
_kernel_oserror *e = _swix(RT_Register,_INR(0,7),0,tasklet_wrapper,&tasklets,private_word,&tasklets.pollword, ((int) stack) + 560, ((int) stack) + THREAD_STACK_SIZE, "DWCDriver_Tasklet:145");
if(!e)
_swix(RT_Yield,_IN(1),&tasklets.idle);
dwc_common_init = (e?NO:YES);
return e;
}
......
......@@ -33,6 +33,7 @@
#include "cmodule.h"
#include "modhead.h"
#include "Global/HALEntries.h"
#include "Global/Services.h"
#include "callx/callx.h"
#include <sys/callout.h>
......@@ -50,6 +51,8 @@
#include "dwc/driver/dwc_otg_hcd_if.h"
#include "dwc/driver/dwc_otg_dbg.h"
#include "dwc/driver/dwc_otg_driver.h"
#include "dwc/driver/dwc_otg_regs.h"
#include "dwc/driver/dwc_otg_mphi_fix.h"
/* CIL & HCD interface for RISC OS */
......@@ -100,6 +103,21 @@ struct dwc_otg_driver_module_params {
int32_t adp_enable;
};
bool use_fiq_fix = true; /* True if we're allowed to use the FIQ fix */
bool reclaim_fiq_vector = false; /* True if we should attempt to claim FIQs (i.e. driver is initialised and use_fiq_fix) */
bool own_fiq_vector = false; /* True if we currently own the FIQ vector */
extern bool fiq_fix_enable;
extern volatile uint8_t *dwc_regs_base;
extern mphi_regs_t c_mphi_regs;
extern void *dummy_send;
static uint32_t fiq_stack[512];
#ifdef RISCOS_FIQ_DOWNGRADE
fiq_downgrade_t fiq_downgrade;
#endif
/*
Misc
......@@ -470,7 +488,7 @@ static struct {
softc_root_intr_methods_entry,
softc_device_methods_entry;
_kernel_oserror *dwc_otg_riscos_init(const uint32_t *hw_base,int device_number,dwc_softc_t *softc)
_kernel_oserror *dwc_otg_riscos_init(const uint32_t *hw_base,const uint8_t *mphi_base,int usb_device_number,int mphi_device_number,dwc_softc_t *softc)
{
/* Initialise veneers */
#if defined (__riscos) && !defined(USBHAL)
......@@ -490,7 +508,8 @@ _kernel_oserror *dwc_otg_riscos_init(const uint32_t *hw_base,int device_number,d
softc->sc_bus.methods = &softc_bus_methods;
softc->sc_bus.pipe_size = sizeof(struct dwc_softc_pipe);
softc->device_number = device_number;
softc->usb_device_number = softc->device_number = usb_device_number;
softc->mphi_device_number = mphi_device_number;
SIMPLEQ_INIT(&softc->sc_free_xfers);
/* Initialise the common interface layer */
......@@ -567,13 +586,40 @@ _kernel_oserror *dwc_otg_riscos_init(const uint32_t *hw_base,int device_number,d
return (_kernel_oserror *) "\0\0\0\0Incorrect device parameters";
}
/* Set up variables needed by the FIQ code */
dprintf(("","Registers at %08x %08x\n",hw_base,mphi_base));
dwc_regs_base = (volatile uint8_t *) hw_base;
c_mphi_regs.base = (volatile void *) (mphi_base);
c_mphi_regs.ctrl = (volatile void *) (mphi_base + 0x4c);
c_mphi_regs.outdda = (volatile void *) (mphi_base + 0x28);
c_mphi_regs.outddb = (volatile void *) (mphi_base + 0x2c);
c_mphi_regs.intstat = (volatile void *) (mphi_base + 0x50);
dummy_send = malloc(16);
/* Enable MPHI peripheral */
DWC_WRITE_REG32(c_mphi_regs.ctrl,0x80000000);
#ifdef RISCOS_FIQ_DOWNGRADE
fiq_downgrade.fiq_downgrade_device = mphi_device_number;
/* Get the MPHI generating an interrupt now */
FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send);
FIQ_WRITE( c_mphi_regs.outddb, (1 << 29));
_swix(OS_Hardware,_INR(8,9)|_OUTR(0,1),1,EntryNo_HAL_IRQEnable,&fiq_downgrade.hal_irqenable,&fiq_downgrade.hal_sb);
_swix(OS_Hardware,_INR(8,9)|_OUT(0),1,EntryNo_HAL_IRQDisable,&fiq_downgrade.hal_irqdisable);
#endif
/* Disable global interrupts */
dprintf(("","Setting up IRQs\n"));
dwc_otg_disable_global_interrupts(softc->dwc_dev.core_if);
/* Claim IRQ */
_swix (OS_ClaimDeviceVector, _INR(0,4), softc->device_number, usb_irq_entry, private_word, 0, 0);
_swix (OS_Hardware, _IN(0) | _INR(8,9), softc->device_number, 0, EntryNo_HAL_IRQEnable);
_swix (OS_ClaimDeviceVector, _INR(0,4), softc->usb_device_number, usb_irq_entry, private_word, 0, 0);
_swix (OS_Hardware, _IN(0) | _INR(8,9), softc->usb_device_number, 0, EntryNo_HAL_IRQEnable);
/* Try using FIQs */
dwc_otg_riscos_try_use_fiqs(softc,true);
/* Initialise CIL */
dprintf(("","dwc_otg_core_init\n"));
......@@ -639,8 +685,22 @@ void dwc_otg_riscos_shutdown(dwc_softc_t *softc)
softc->dwc_dev.core_if = NULL;
}
/* Relase IRQ */
_swix (OS_ReleaseDeviceVector, _INR(0,4), softc->device_number, usb_irq_entry, private_word, 0, 0);
/* Release FIQ */
if(own_fiq_vector)
{
/* Prevent automatically reclaiming the vector when we try to release it */
reclaim_fiq_vector = false;
dwc_otg_riscos_release_fiq(softc);
_swix(OS_ServiceCall,_IN(1),Service_ReleaseFIQ);
}
if(dummy_send)
{
free(dummy_send);
dummy_send = NULL;
}
/* Release IRQ */
_swix (OS_ReleaseDeviceVector, _INR(0,4), softc->usb_device_number, usb_irq_entry, private_word, 0, 0);
/* Free remaining memory */
usbd_xfer_handle xfer;
......@@ -669,5 +729,90 @@ int dwc_otg_riscos_irq(dwc_softc_t *softc)
if(ret)
return 0;
return 1;
/* Unhandled (spurious?) IRQs may happen every so often when using the FIQ fix. Try not to worry about it! */
return (use_fiq_fix?0:1);
}
extern void install_fiq(uint32_t *stack,uint32_t stacksize);
void dwc_otg_riscos_try_use_fiqs(dwc_softc_t *softc, bool need_to_claim)
{
if(!use_fiq_fix)
{
reclaim_fiq_vector = false;
return;
}
dprintf(("","Claiming FIQ vector\n"));
if(need_to_claim)
{
/* Claim FIQs (from foreground, guaranteed to succeed) */
_swix(OS_ServiceCall,_IN(1),Service_ClaimFIQ);
}
/* Ensure any previous interrupts are disabled */
_swix (OS_Hardware, _INR(8,9), 0, EntryNo_HAL_FIQDisableAll);
/* Install FIQ handler */
install_fiq(fiq_stack,sizeof(fiq_stack));
/* Disable IRQs+FIQs while we switch state */
int flags;
local_irq_save(flags);
local_fiq_disable();
/* Switch the IRQ handler from USB to MPHI */
_swix (OS_ReleaseDeviceVector, _INR(0,4), softc->usb_device_number, usb_irq_entry, private_word, 0, 0);
_swix (OS_ClaimDeviceVector, _INR(0,4), softc->mphi_device_number, usb_irq_entry, private_word, 0, 0);
softc->device_number = softc->mphi_device_number;
#if defined(RISCOS_FIQ_DOWNGRADE)
/* Ensure the FIQ routine will enable the interrupt */
fiq_downgrade.irq_masked = false;
fiq_downgrade.fiq_trigger = false;
#else
/* Enable MPHI IRQ */
_swix (OS_Hardware, _IN(0) | _INR(8,9), softc->mphi_device_number, 0, EntryNo_HAL_IRQEnable);
#endif
/* Enable FIQ interrupt from USB */
_swix (OS_Hardware, _IN(0) | _INR(8,9), softc->usb_device_number, 0, EntryNo_HAL_FIQEnable);
/* Flag to DWC that the FIQ code is enabled */
fiq_fix_enable = use_fiq_fix;
/* Flag that we own the vector, and should reclaim it if we lose it */
own_fiq_vector = reclaim_fiq_vector = true;
local_irq_restore(flags);
}
void dwc_otg_riscos_release_fiq(dwc_softc_t *softc)
{
dprintf(("","Releasing FIQ vector\n"));
/* Release our claim on the FIQ vector */
int flags;
local_irq_save(flags);
local_fiq_disable();
/* Disable the interrupt */
_swix (OS_Hardware, _INR(8,9), 0, EntryNo_HAL_FIQDisableAll);
/* Flag to DWC that the FIQ code is no longer active */
fiq_fix_enable = false;
/* Flag that we no longer own the vector */
own_fiq_vector = false;
/* Switch the IRQ handler from MPHI to USB */
_swix (OS_ReleaseDeviceVector, _INR(0,4), softc->mphi_device_number, usb_irq_entry, private_word, 0, 0);
_swix (OS_ClaimDeviceVector, _INR(0,4), softc->usb_device_number, usb_irq_entry, private_word, 0, 0);
softc->device_number = softc->usb_device_number;
/* Enable USB IRQ */
_swix (OS_Hardware, _IN(0) | _INR(8,9), softc->usb_device_number, 0, EntryNo_HAL_IRQEnable);
local_irq_restore(flags);
}
......@@ -22,7 +22,9 @@ finalisation-code: module_final
service-call-handler: module_services Service_USB,
Service_PreReset,
Service_ModulePostFinal
Service_ModulePostFinal,
Service_ClaimFIQ,
Service_ReleaseFIQ
title-string: COMPONENT
......
......@@ -477,11 +477,18 @@ void notrace dwc_otg_hcd_handle_fiq(void)
// Clear and save any unhandled interrupts and trigger the interrupt
if(gintsts_saved.d32)
{
#ifdef RISCOS_FIQ_DOWNGRADE
/* Flag that we're downgrading an FIQ */
fiq_downgrade.fiq_trigger = true;
/* Enable the IRQ now if the IRQ routine says it's safe to do so */
if(!fiq_downgrade.irq_masked)
halcall(fiq_downgrade.fiq_downgrade_device,fiq_downgrade.hal_irqenable,fiq_downgrade.hal_sb);
#else
/* To enable the MPHI interrupt (INT 32)
*/
FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send);
FIQ_WRITE( c_mphi_regs.outddb, (1 << 29));
#endif
mphi_int_count++;
}
}
......@@ -622,6 +629,7 @@ exit_handler_routine:
{
local_fiq_disable();
// Make sure that we don't clear the interrupt if we've still got pending work to do
#ifndef RISCOS_FIQ_DOWNGRADE
if(gintsts_saved.d32 == 0)
{
/* Clear the MPHI interrupt */
......@@ -636,6 +644,14 @@ exit_handler_routine:
}
int_done++;
}
#else
if(!gintsts_saved.d32)
{
/* No more interrupts left to process, clear the downgrade flag so that we will leave the IRQ disabled on exit from the IRQ handler */
fiq_downgrade.fiq_trigger = false;
int_done++;
}
#endif
// Unmask handled interrupts
FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);
......
#ifndef __DWC_OTG_MPHI_FIX_H__
#define __DWC_OTG_MPHI_FIX_H__
#ifdef __riscos
/* Use the proper memory barriers! Not sure why Linux doesn't run into problems without them */
#define FIQ_WRITE(_addr_,_data_) DWC_WRITE_REG32((uint32_t volatile *) (_addr_),_data_)
#define FIQ_READ(_addr_) DWC_READ_REG32((uint32_t volatile *) (_addr_))
#else
#define FIQ_WRITE(_addr_,_data_) (*(volatile uint32_t *) (_addr_) = (_data_))
#define FIQ_READ(_addr_) (*(volatile uint32_t *) (_addr_))
#endif
typedef struct {
volatile void* base;
......@@ -49,4 +55,18 @@ void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...);
extern bool fiq_fix_enable, nak_holdoff_enable, fiq_split_enable;
#ifdef __riscos
#define RISCOS_FIQ_DOWNGRADE
typedef struct {
void *hal_sb;
void *hal_irqenable;
void *hal_irqdisable;
int fiq_downgrade_device;
volatile bool irq_masked;
volatile bool fiq_trigger;
} fiq_downgrade_t;
extern fiq_downgrade_t fiq_downgrade;
extern int halcall(int arg,void *func,void *sb);
#endif
#endif
......@@ -217,12 +217,16 @@ static inline char *dwc_bh(void) {
*
* Use the DWC_WARN macro to call this function.
*/
#if defined(DEBUG) || !defined(__riscos)
extern void __DWC_WARN(char *format, ...)
#ifdef __GNUC__
__attribute__ ((format(printf, 1, 2)));
#else
;
#endif
#else
#define __DWC_WARN(...)
#endif
/**
* Prints an error message. On systems that don't differentiate between errors
......@@ -231,12 +235,16 @@ extern void __DWC_WARN(char *format, ...)
*
* Use the DWC_ERROR macro to call this function.
*/
#if defined(DEBUG) || !defined(__riscos)
extern void __DWC_ERROR(char *format, ...)
#ifdef __GNUC__
__attribute__ ((format(printf, 1, 2)));
#else
;
#endif
#else
#define __DWC_ERROR(...)
#endif
/**
* Prints an exception error message and takes some user-defined action such as
......@@ -246,12 +254,16 @@ extern void __DWC_ERROR(char *format, ...)
* printing capability, some action should be taken to notify the developer of
* it. Works like printf().
*/
#if defined(DEBUG) || !defined(__riscos)
extern void DWC_EXCEPTION(char *format, ...)
#ifdef __GNUC__
__attribute__ ((format(printf, 1, 2)));
#else
;
#endif
#else
#define DWC_EXCEPTION(...)
#endif
#define dwc_exception DWC_EXCEPTION
#ifndef DWC_OTG_DEBUG_LEV
......
......@@ -57,7 +57,9 @@ struct dwc_softc_pipe {
typedef struct dwc_softc {
struct usbd_bus sc_bus; /* Base USBDriver struct */
int device_number; /* IRQ device number */
int device_number; /* Current IRQ device number (USB or MPHI) */
int usb_device_number;
int mphi_device_number;
/* USBDriver bits */
......@@ -80,11 +82,18 @@ typedef struct dwc_softc {
#define DWC_SOFTC_INTR_ENDPT 1
extern _kernel_oserror *dwc_otg_riscos_init(const uint32_t *hw_base,int device_number,dwc_softc_t *softc);
extern bool use_fiq_fix;
extern bool reclaim_fiq_vector;
extern bool own_fiq_vector;
extern _kernel_oserror *dwc_otg_riscos_init(const uint32_t *hw_base,const uint8_t *mphi_base,int usb_device_number,int mphi_device_number,dwc_softc_t *softc);
extern void dwc_otg_riscos_shutdown(dwc_softc_t *softc);
extern int dwc_otg_riscos_irq(dwc_softc_t *softc);
extern void dwc_otg_riscos_try_use_fiqs(dwc_softc_t *softc, bool need_to_claim);
extern void dwc_otg_riscos_release_fiq(dwc_softc_t *softc);
/* softc_root.c */
extern usbd_status softc_root_ctrl_transfer(usbd_xfer_handle);
......
......@@ -29,6 +29,8 @@
GET Hdr:ListOpts
GET Hdr:CPU.Arch
GET Hdr:CPU.Generic32
GET Hdr:Macros
GET Hdr:System
AREA |C$$code|, CODE, READONLY
......@@ -44,6 +46,10 @@
EXPORT |_local_irq_save|
EXPORT local_irq_restore
EXPORT install_fiq
IMPORT dwc_otg_hcd_handle_fiq
EXPORT halcall
MACRO
myDSB
[ NoARMv6
......@@ -127,5 +133,56 @@ local_fiq_enable
local_irq_restore
MSR CPSR_c, a1
MOV pc, lr
; void install_fiq(uint32_t *stack,uint32_t stacksize)
; Install our FIQ handler on the FIQ vector
install_fiq ROUT
STMFD sp!, {a1-a2,lr}
MOV a1, #0
SWI XOS_PlatformFeatures
TST a1, #1<<20
LDRNE lr, =&FFFF001C
MOVEQ lr, #&1C
ADR a1, FIQcode
ADR a2, FIQcode_end
MOV a3, lr
10
LDR a4, [a1], #4
STR a4, [a3], #4
CMP a1, a2
BNE %BT10
MOV a1, #1
MOV a2, lr
SWI XOS_SynchroniseCodeAreas
; Set up the C relocation offsets in the FIQ stack
LDMIA sp, {a1-a2}
SUB a3, sl, #540
LDMIA a3, {a3-a4}
STMIA a1, {a3-a4}
; Set up the FIQ mode registers
MRS a3, CPSR
EOR a4, a3, #FIQ32_mode :EOR: SVC32_mode
MSR CPSR_c, a4
ADD sp, a1, a2
ADD sl, a1, #540
MOV fp, #0
ADRL v5, dwc_otg_hcd_handle_fiq ; i.e. r8
MSR CPSR_c, a3
LDMFD sp!, {a1-a2,pc}
FIQcode