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

Commit 8d9ee35f authored by Robert Sprowson's avatar Robert Sprowson Committed by ROOL

Add support for XHCI that exists on a PCI bus

Ask PCI manager if there are any XHCI controllers to attach to, then continue to HAL described ones once they're all done. Similarly ask around for the PCI root hub name.
xhci.c: Root hub name now in a RAM variable. Workaround for DMA controller problem with VL805 if the array of structure pointers is only 8 byte aligned.
xhcimodule.c/h: Do 2 pass discovery, PCI first, then HAL descriptors. Speed up interrupt despatch a bit by calling the HAL's enable/disable directly rather than via _swix(OS_Hardware). Explicitly clear the interrupt too for the case where it's latched in the PCI peripheral.

Version 0.30. Tagged as 'XHCIDriver-0_30'
parent 841353e9
/* (0.29) /* (0.30)
* *
* This file is automatically maintained by srccommit, do not edit manually. * This file is automatically maintained by srccommit, do not edit manually.
* *
*/ */
#define Module_MajorVersion_CMHG 0.29 #define Module_MajorVersion_CMHG 0.30
#define Module_MinorVersion_CMHG #define Module_MinorVersion_CMHG
#define Module_Date_CMHG 04 Jul 2020 #define Module_Date_CMHG 12 Sep 2020
#define Module_MajorVersion "0.29" #define Module_MajorVersion "0.30"
#define Module_Version 29 #define Module_Version 30
#define Module_MinorVersion "" #define Module_MinorVersion ""
#define Module_Date "04 Jul 2020" #define Module_Date "12 Sep 2020"
#define Module_ApplicationDate "04-Jul-20" #define Module_ApplicationDate "12-Sep-20"
#define Module_ComponentName "XHCIDriver" #define Module_ComponentName "XHCIDriver"
#define Module_FullVersion "0.29" #define Module_FullVersion "0.30"
#define Module_HelpVersion "0.29 (04 Jul 2020)" #define Module_HelpVersion "0.30 (12 Sep 2020)"
#define Module_LibraryVersionInfo "0:29" #define Module_LibraryVersionInfo "0:30"
...@@ -852,9 +852,15 @@ xhci_init(struct xhci_softc *sc) ...@@ -852,9 +852,15 @@ xhci_init(struct xhci_softc *sc)
sc->sc_maxspbuf = XHCI_HCS2_MAXSPBUF(hcs2); sc->sc_maxspbuf = XHCI_HCS2_MAXSPBUF(hcs2);
aprint_debug_dev(sc->sc_dev, "sc_maxspbuf %d\n", sc->sc_maxspbuf); aprint_debug_dev(sc->sc_dev, "sc_maxspbuf %d\n", sc->sc_maxspbuf);
if (sc->sc_maxspbuf != 0) { if (sc->sc_maxspbuf != 0) {
#ifdef RISCOS
err = usb_allocmem(&sc->sc_bus,
sizeof(uint64_t) * sc->sc_maxspbuf, 64, /* Overalign for VL805 */
&sc->sc_spbufarray_dma);
#else
err = usb_allocmem(&sc->sc_bus, err = usb_allocmem(&sc->sc_bus,
sizeof(uint64_t) * sc->sc_maxspbuf, sizeof(uint64_t), sizeof(uint64_t) * sc->sc_maxspbuf, sizeof(uint64_t),
&sc->sc_spbufarray_dma); &sc->sc_spbufarray_dma);
#endif
if (err) if (err)
return err; return err;
...@@ -881,6 +887,15 @@ xhci_init(struct xhci_softc *sc) ...@@ -881,6 +887,15 @@ xhci_init(struct xhci_softc *sc)
config |= sc->sc_maxslots & 0xFF; config |= sc->sc_maxslots & 0xFF;
xhci_op_write_4(sc, XHCI_CONFIG, config); xhci_op_write_4(sc, XHCI_CONFIG, config);
#ifdef RISCOS
/* Disable any SuperSpeed ports since no USB3 yet */
for (i = 0; i < sc->sc_ss_port_count; i++) {
int port = XHCI_PORTSC(sc->sc_ss_port_start + i);
/* Disable port then force RxDetect state to redo link as UBS2 or USB1 */
xhci_op_write_4(sc, port, XHCI_PS_PLS_SET(5) | XHCI_PS_PED);
}
#endif
err = xhci_ring_init(sc, &sc->sc_cr, XHCI_COMMAND_RING_TRBS, err = xhci_ring_init(sc, &sc->sc_cr, XHCI_COMMAND_RING_TRBS,
XHCI_COMMAND_RING_SEGMENTS_ALIGN); XHCI_COMMAND_RING_SEGMENTS_ALIGN);
if (err) { if (err) {
...@@ -2922,7 +2937,7 @@ xhci_root_ctrl_start(usbd_xfer_handle xfer) ...@@ -2922,7 +2937,7 @@ xhci_root_ctrl_start(usbd_xfer_handle xfer)
break; break;
case 1: /* Vendor */ case 1: /* Vendor */
#ifdef RISCOS #ifdef RISCOS
totlen = usb_makestrdesc(sd, len, intl_lookup("RHV")); totlen = usb_makestrdesc(sd, len, g_vendor);
#else #else
totlen = usb_makestrdesc(sd, len, "NetBSD"); totlen = usb_makestrdesc(sd, len, "NetBSD");
#endif #endif
......
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
#include "Global/OSMisc.h" #include "Global/OSMisc.h"
#include "Global/HALEntries.h" #include "Global/HALEntries.h"
#include "Global/ModHand.h" #include "Global/ModHand.h"
#undef Module_Title /* Avoid CMHG clash */
#include "Interface/USBDriver.h" #include "Interface/USBDriver.h"
#include "Interface/PCI.h"
#include "callx/callx.h" #include "callx/callx.h"
...@@ -51,7 +51,9 @@ void *g_pw; ...@@ -51,7 +51,9 @@ void *g_pw;
uint32_t g_msgblock[4]; uint32_t g_msgblock[4];
uint32_t g_instance; uint32_t g_instance;
uint32_t g_controller = 0; uint32_t g_controller = 0;
usbloc_t g_location = LOC_PCI;
usbinfo_t g_device; usbinfo_t g_device;
char g_vendor[32];
barrier_func barriers[3]; /* Write + Read + ReadWrite */ barrier_func barriers[3]; /* Write + Read + ReadWrite */
/* Locals */ /* Locals */
...@@ -60,6 +62,7 @@ static struct xhci_softc xhcisoftc; ...@@ -60,6 +62,7 @@ static struct xhci_softc xhcisoftc;
static struct device *usbstate = NULL; static struct device *usbstate = NULL;
static bool_t driver_up = FALSE; static bool_t driver_up = FALSE;
static bool_t driver_registering = FALSE; static bool_t driver_registering = FALSE;
static void *hal_irqwksp, *hal_irqclear, *hal_irqenable, *hal_irqdisable;
/* /*
* International support functions * International support functions
...@@ -123,13 +126,13 @@ static _kernel_oserror *xhcidriver_registerbus(void *mystate, struct device **yo ...@@ -123,13 +126,13 @@ static _kernel_oserror *xhcidriver_registerbus(void *mystate, struct device **yo
static _kernel_oserror *xhcidriver_spawn(_kernel_swi_regs *r, void *pw, void *arg) static _kernel_oserror *xhcidriver_spawn(_kernel_swi_regs *r, void *pw, void *arg)
{ {
_kernel_oserror *err; _kernel_oserror *err;
char name[sizeof(Module_Title) + 1 + 10 + 1 + 10]; char name[sizeof(Module_Title) + 1 + 10 + 1 + 1 + 10];
/* Try to register this controller */ /* Try to register this controller */
xhcidriver_registerbus(&xhcisoftc, &usbstate); xhcidriver_registerbus(&xhcisoftc, &usbstate);
/* Try for another instance for another controller */ /* Try for another instance for another controller */
sprintf(name, Module_Title "%%%u %u", g_instance + 1, g_controller + 1); sprintf(name, Module_Title "%%%u %c%u", g_instance + 1, g_location, g_controller + 1);
err = _swix(OS_Module, _INR(0,1), ModHandReason_NewIncarnation, name); err = _swix(OS_Module, _INR(0,1), ModHandReason_NewIncarnation, name);
dprintf(("" , "Try instance %u for controller %u -> %s\n", dprintf(("" , "Try instance %u for controller %u -> %s\n",
g_instance + 1, g_controller + 1, (err == NULL) ? "OK" : err->errmess)); g_instance + 1, g_controller + 1, (err == NULL) ? "OK" : err->errmess));
...@@ -230,6 +233,62 @@ void veneer_install(int *vn, int *st, size_t sz) ...@@ -230,6 +233,62 @@ void veneer_install(int *vn, int *st, size_t sz)
entry_table + 2 * (sz / sizeof(void *)) - 1); entry_table + 2 * (sz / sizeof(void *)) - 1);
} }
/*
* Discovery
*/
static bool_t find_pci_controllers(void)
{
_kernel_oserror *err;
size_t size;
uint32_t info[2];
err = _swix(PCI_FindByClass, _INR(0,1) | _IN(3) | _OUT(3),
0x0C0330 /* XHCI */, 0xFFFFFF, g_controller, &g_controller);
if ((err != NULL) || (g_controller == 0)) return false;
err = _swix(PCI_ReadInfo, _INR(0,3) | _OUT(2),
PCI_ReadInfo_Vendor | PCI_ReadInfo_IntDeviceVector, info, sizeof(info), g_controller,
&size);
if ((err != NULL) || (size != sizeof(info))) return false;
err = _swix(PCI_HardwareAddress, _INR(0,1) | _IN(3) | _OUT(4),
0, 0, g_controller, &g_device.hw);
if (err != NULL) return false;
/* Now construct a HAL look-a-like */
g_device.type = HALUSBControllerType_XHCI;
g_device.flags = HALUSBControllerFlag_XHCI_No_Offset;
g_device.devno = info[0];
strcpy(g_vendor, (const char *)info[1]);
return true;
}
static bool_t find_hal_controllers(void)
{
_kernel_oserror *err;
size_t size;
while (1)
{
err = _swix(OS_Hardware, _INR(0,2) | _INR(8,9) | _OUT(0),
g_controller, &g_device, sizeof(g_device),
OSHW_CallHAL, EntryNo_HAL_USBControllerInfo,
&size);
if (err != NULL) return false;
if (size == 0) return false;
if ((size == sizeof(g_device)) && (g_device.type == HALUSBControllerType_XHCI))
{
/* Found another */
break;
}
g_controller++;
}
strcpy(g_vendor, intl_lookup("RHV"));
return true;
}
/* /*
* Module functions * Module functions
*/ */
...@@ -267,38 +326,41 @@ _kernel_oserror *xhcidriver_init(const char *cmd_tail, int podule_base, void *pw ...@@ -267,38 +326,41 @@ _kernel_oserror *xhcidriver_init(const char *cmd_tail, int podule_base, void *pw
MMUCReason_GetARMop + (ARMop_DMB_ReadWrite << 8), &barriers[BARRIER_READ + BARRIER_WRITE - 1]); MMUCReason_GetARMop + (ARMop_DMB_ReadWrite << 8), &barriers[BARRIER_READ + BARRIER_WRITE - 1]);
if (err != NULL) goto initclose; if (err != NULL) goto initclose;
/* Get the direct HAL IRQ routines */
err = _swix(OS_Hardware, _INR(8,9) | _OUTR(0,1),
OSHW_LookupRoutine, EntryNo_HAL_IRQEnable, &hal_irqenable, &hal_irqwksp);
if (err != NULL) goto initclose;
err = _swix(OS_Hardware, _INR(8,9) | _OUT(0),
OSHW_LookupRoutine, EntryNo_HAL_IRQDisable, &hal_irqdisable);
if (err != NULL) goto initclose;
err = _swix(OS_Hardware, _INR(8,9) | _OUT(0),
OSHW_LookupRoutine, EntryNo_HAL_IRQClear, &hal_irqclear);
if (err != NULL) goto initclose;
/* For the first instance, start at 0, otherwise continue from the /* For the first instance, start at 0, otherwise continue from the
* controller number passed in the command_tail string. * controller number passed in the command_tail string.
*/ */
if (g_instance != 0) if (g_instance != 0)
{ {
if (sscanf(cmd_tail, "%u", &g_controller) == 0) if (sscanf(cmd_tail, "%c%u", &g_location, &g_controller) != 2)
{ {
/* Tail missing or not a number */ /* Tail missing or not a number */
err = intl_error(ERR00_SINGLE_INSTANCE); err = intl_error(ERR00_SINGLE_INSTANCE);
goto initclose; goto initclose;
} }
} }
while (1) switch (g_location)
{ {
size_t size; case LOC_PCI:
if (find_pci_controllers()) break;
err = _swix(OS_Hardware, _INR(0,2) | _INR(8,9) | _OUT(0), g_controller = 0;
g_controller, &g_device, sizeof(g_device), g_location = LOC_HAL;
OSHW_CallHAL, EntryNo_HAL_USBControllerInfo, /* Fall through */
&size);
if (err != NULL) goto initclose; case LOC_HAL:
if (size == 0) if (find_hal_controllers()) break;
{
err = intl_error(ERR01_NO_MORE_XHCI); err = intl_error(ERR01_NO_MORE_XHCI);
goto initclose; goto initclose;
}
if ((size == sizeof(g_device)) && (g_device.type == HALUSBControllerType_XHCI))
{
/* Found another */
break;
}
g_controller++;
} }
/* Initialise this one */ /* Initialise this one */
...@@ -400,11 +462,10 @@ int xhcidriver_irq_handler(_kernel_swi_regs *r, void *pw) ...@@ -400,11 +462,10 @@ int xhcidriver_irq_handler(_kernel_swi_regs *r, void *pw)
int handled; int handled;
/* Prevent recursion by masking the device while we handle the interrupt */ /* Prevent recursion by masking the device while we handle the interrupt */
_swix(OS_Hardware, _IN(0) | _INR(8,9), g_device.devno, hal_irqcall(g_device.devno, hal_irqdisable, hal_irqwksp);
OSHW_CallHAL, EntryNo_HAL_IRQDisable);
handled = xhci_intr(&xhcisoftc); handled = xhci_intr(&xhcisoftc);
_swix(OS_Hardware, _IN(0) | _INR(8,9), g_device.devno, if (handled) hal_irqcall(g_device.devno, hal_irqclear, hal_irqwksp);
OSHW_CallHAL, EntryNo_HAL_IRQEnable); hal_irqcall(g_device.devno, hal_irqenable, hal_irqwksp);
UNUSED(r); UNUSED(r);
UNUSED(pw); UNUSED(pw);
......
...@@ -47,6 +47,12 @@ typedef uint8_t bool_t; ...@@ -47,6 +47,12 @@ typedef uint8_t bool_t;
#define FALSE 0 #define FALSE 0
#define TRUE (!FALSE) #define TRUE (!FALSE)
typedef enum
{
LOC_PCI = 'P',
LOC_HAL = 'H'
} usbloc_t;
typedef struct typedef struct
{ {
uint32_t type; uint32_t type;
...@@ -61,6 +67,7 @@ typedef struct ...@@ -61,6 +67,7 @@ typedef struct
extern void *Resources(void); /* Generated by 'resgen' */ extern void *Resources(void); /* Generated by 'resgen' */
void veneer_install(int *, int *, size_t); /* In 'veneer' */ void veneer_install(int *, int *, size_t); /* In 'veneer' */
int *veneer_init(void); /* In 'veneer' */ int *veneer_init(void); /* In 'veneer' */
int hal_irqcall(int, void *, void *); /* In 'veneer' */
const char *intl_lookup(const char *); const char *intl_lookup(const char *);
/* Exported variables */ /* Exported variables */
...@@ -69,5 +76,7 @@ extern uint32_t g_msgblock[4]; ...@@ -69,5 +76,7 @@ extern uint32_t g_msgblock[4];
extern uint32_t g_instance; extern uint32_t g_instance;
extern uint32_t g_controller; extern uint32_t g_controller;
extern usbinfo_t g_device; extern usbinfo_t g_device;
extern char g_vendor[];
extern usbloc_t g_location;
#endif #endif
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
GET Hdr:Proc GET Hdr:Proc
AREA |C$$code|, CODE, READONLY AREA |C$$code|, CODE, READONLY
EXPORT hal_irqcall
EXPORT veneer_init EXPORT veneer_init
EXPORT glue_rt_entry EXPORT glue_rt_entry
IMPORT glue_rt_handler IMPORT glue_rt_handler
...@@ -109,4 +110,14 @@ common Entry "v1,v2,fp" ...@@ -109,4 +110,14 @@ common Entry "v1,v2,fp"
EXIT EXIT
magic_end magic_end
; int hal_irqcall(int devno, void *func, void *wksp);
;
; Call one of the HAL interrupt controller routines directly, putting
; the workspace pointer into sb as required.
hal_irqcall ROUT
Entry "r9"
MOV r9, a3
BLX a2
EXIT
END END
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment