The RISC OS 5 USB stack consists of the following software components:
Debug versions of the modules can be built by adding
DEBUG=TRUE to the
-options string in the components file.
Debug output is handled by the DebugLib library; check each module’s initialisation to make sure a suitable output device is in use. The USB modules can produce a large quantity of debug output, often from within interrupt handlers. A device which provides low-latency output and works correctly with interrupts disabled is therefore desirable (e.g. the DADebug module).
When debugging is enabled, each module provides a few extra *commands. Check the *help text or the CMHG files for details.
The debug level can be altered at runtime via *commands, or set at load time by altering the module’s initialisation function. Generally speaking, if the debug level is above 10, you can expect to receive a lot of output.
TODO – This is probably out of date since the EHCI code was updated to the latest BSD version.
The USB hardware drivers register themselves with the main USB module by using the USBDriver_RegisterBus SWI. The hardware driver supplies the USB module with a pointer to its
usbd_bus struct (see NetBSD.dev.usb.h.usbdivar), and the USB module responds with a pointer to its
device struct (see NetBSD.sys.h.device; not to be confused with the HAL device struct!)
Presently the only purpose the
device struct services is to allow the USB modules to deregister themselves with the USB driver on shutdown. All communication from USBDriver to the hardware drivers is done via function pointers contained in the
usbd_bus struct, and all communication between the hardware driver and the USBDriver is done via SWI calls.
These functions in *.c.port are used by the NetBSD sources to disable & restore interrupts. Note that splusb() is actually #defined to splbio().
This function in *.c.port is used by the USB drivers whenever they want to block waiting for an interrupt-triggered event to occur (e.g. completion of a USB transfer)
These functions in *.c.port use the PCI module to allocate & free noncacheable, nonbufferable blocks of memory suitable for use as DMA buffers. The PCI module ensures that only contiguous physical pages are used, greatly simplifying the process of setting up DMA transfers.
The USB drivers can also be built as a set of static libraries suitable for linking with a HAL implementation. The main reason for doing this is to simplify the task of implementing the HAL keyboard API that RISC OS uses to perform the keyboard scan on boot. The HAL build of the libraries differs from the regular module build in several ways:
USBHALpreprocessor directive is defined, to allow the code to identify the build
USBHALdefined the header provides the following:
__global_regdirective to prevent the compiler from utilising
sbas a general purpose register
usbhal_wsstruct which is used to store the static data required by the drivers (regular global/static variables won’t work, as the C compiler won’t understand where to store them)
USBHALWSmacro is provided to obtain a pointer to the structure.
OSentriesmacro for any code that needs to call one of the OS entry points
USBHAL_*functions that the HAL uses to interface with the drivers/keyboard scan code
The HAL build of the drivers is built automatically by the “export libs” build phase, whether the HAL requires the drivers or not.
For an example of how to implement the HAL build of the drivers, see the OMAP3 HAL, specifically OMAP3.s.KbdScan.
Note: Currently HAL builds are not supported by DWCDriver nor XHCIDriver.