[Select]

Hardware


Index

 

Hardware IRQ handler

Introduction

The IRQ module provides the IRQ servicing interface for RISC OS. In the past, this task has always been provided by the Kernel. From Kernel 10.00 onward, the task of decoding and despatching IRQs to devices is handled by the IRQ module.

Developers reading this section should ensure that they are familiar with the OS_ClaimDeviceVector interface and its related documentation (PRM-117, 'Interrupts and handling them').

Core IRQ handler

The Core IRQ handler replaces the SWIs OS_ClaimDeviceVector and OS_ReleaseDeviceVector, providing an interface to claim and release devices. The Core IRQ handler provides the main functions necessary to communicate with the IRQ controllers within the system in order to determine which devices are interrupting and to despatch to the relevant routines.

Registration

In order to register a new IRQ handler with the Kernel, a variation of the standard OS_ClaimDeviceVector call is used. The device number -1 is used to indicate a core IRQ handler replacement. This interface may be provided by the IRQ handler module at its discretion.

OS_ClaimDeviceVector
On entry
   R0 = -1
   R1 = pointer to replacement IRQ handler routine
   R2 = workspace parameter to pass in R12 to IRQ handler routine
On exit
   R1 = default routine to call for all unclaimed IRQs
   R2 = workspace parameter to pass in R12 to the unclaimed IRQ routine

This SWI is used to register a core IRQ handler replacement. The IRQ handler should fill its table of IRQ handlers such that the routine returned in R1 (with R2 as a parameter) will be called if no handler has been provided. The IRQ handler may then enable interrupts.

OS_ReleaseDeviceVector
On entry
   R0 = -1
   R1 = pointer to replacement IRQ handler routine
   R2 = workspace parameter to pass in R12 to IRQ handler routine

This SWI is used to release a core IRQ handler and restore the OS default. The default OS handler will disable IRQs and return to the caller.

Invocation

The core IRQ handler will be called by the Kernel to handle an IRQ. The handler must either handle the IRQ such that the interrupting device ceases interrupting or disable the necessary hardware interrupt lines in order that the interrupt does not recurr. The means by which this is done is that clients will register device handlers with OS_ClaimDeviceVector and these will be dispatched by the core IRQ handler. The interface for this registration and dispatch is described in a later section.

The core IRQ handler is called by the Kernel after the following operations have been performed :

  • The interrupting address, PSR and a number of registers are placed on the stack.
  • IRQs are disabled (and in 26bit systems, IRQ26 mode is entered)
  • Where the interrupt occurred during a deferred page table mapping operation, the cache and TLBs will be flushed.
  • The IRQ semaphore will be set.

After the core IRQ handler returns, the Kernel performs the following operations :

  • The IRQ semaphore is restored.
  • IRQ32 mode is entered.
  • The callback flag is checked for transient and non-transient callbacks. (these will be despatched as usual if so)
  • The registers are restored and the preserved PSR moved to the SPSR.
  • The return address is restored, and the CPSR updated from the SPSR.

The core IRQ handler is entered with the following conditions :

On entry
   R8 = interrupted address (R14 on entry to IRQ handler)
   R9 = interrupted PSR (SPSR on entry to IRQ handler)
   R10 = interrupted value of R10
   R11 = interrupted value of R11
   R12 = workspace parameter as registered with OS_ClaimDeviceVector
On exit
   R0-R3, R8-R12 corrupted

The Core IRQ handler should determine which device is interrupted, using a prioritisation scheme suitable for the hardware, and call the handlers repeatedly until one is claimed. If no handler claims the call the default handler (as returned in R1 on return from the Core IRQ handler registration) should be called and then the interrupt line disabled. The disabling of the interrupt line is necessary to prevent the system entering an infinite loop attempting to service an unhandlable interrupt. The parameters for these device driver routines are described below.

Registering a device driver

Registration of a device driver is performed using the OS_ClaimDeviceVector SWI call. The interface for this is largely unchanged from that of the earlier OS versions (see PRM-1-121). The format of R0 has changed to introduce a number of flags.

OS_ClaimDeviceVector
On entry
   R0 = device number (bits 0-23) and flags (bits 24-31) :
         bit 24-28  Reserved, must be 0
         bit 29 = Return IRQ enable/disable routine details
         bit 30 = Register subchain handler
         bit 31 = Pass on to earlier registrants if not claimed
   R1 = pointer to device driver routine
   R2 = workspace parameter to pass in R12 when driver is called
   R3 = address of interrupt status byte for special handlers
   R4 = mask value for interrupt status byte for special handlers
On exit
   R0, R3, R4 preserved
   R1, R2 preserved if R0 bit 29 clear on entry
   R1 = pointer to routine to call to enable/disable device IRQ if R0
         bit 29 set on entry
   R2 = workspace parameter for routine to enable/disable device IRQ if R0
         bit 29 set on entry

This SWI is used to register device drivers with the Core IRQ handler. The flags set on the device number have the following purpose :

  • Bit 31 ('Pass on')
    If set, the driver registered may ignore the interrupt and return with MOV pc,lr. If they do this, the previous registrant will be called. The driver may accept the interrupt by claiming the call, returning by pulling the return address from the stack. If clear, the driver always claims the call, whether they exit by MOV pc,lr or by pulling the return address from the stack.
    This is useful for devices which share interrupt lines on the controller.
  • Bit 30 ('Sub-chain')
    This bit is intended for specialist use in order to register a special 'subchain' handler.
    If clear, the behaviour is unchanged from that described within the PRMs (with the exception of other flag bits). If set, the address supplied in R2 is the head of the sub-chain list. Once a sub-chain has been registered with the Core IRQ driver, all registrants on that vector will be added to the sub-chain. The Sub-chain indicates that the device is special and that R3 and R4 should be used as described within the PRMs.
    The address supplied in R1 will be called to perform the despatch. If the value in R1 is 0, the default despatch routine will be used. On IOMD systems, this interface is reserved for use by the Podule Manager (although it is currently implemented within the IRQ handler module).
    Other systems may provide similar implementations for their expansion hardware management modules. Contact your supplier for more details on the implementation of expansion management modules.
  • Bit 29 ('Return IRQ enable/disable details')
    If clear, R1 and R2 are preserved on exit from this SWI. If set, R1 and R2 contain a pointer to the routine to enable or disable IRQs within the controllers for a device, and the workspace parameter.
On entry
   R0 = device number, bit 31 set to disable or clear to enable
   R12 = workspace parameter supplied in R2
On exit
   R0 preserved
   R1-R3 corrupt

Not all devices can be enabled and disabled for all IRQ controllers. Consult your hardware for specific details.

Note about special handlers: Although the definition of R3 and R4 is that a byte is referenced, it is dependant on the Core IRQ handler (or sub-chain handler) whether the memory will be accessed with a byte, half-word or word access. Consult the documentation for the hardware specific core IRQ handler.

Deregistering a device driver

Deregistration of a device driver is performed with OS_ReleaseDeviceVector, using the interface provided in PRM1-123. The device number supplied in R0 has been extended to include a number of flags.

OS_ReleaseDeviceVector
On entry
   R0 = device number (bits 0-23) and flags (bits 24-31) :
         bit 24-28  Reserved, must be 0
         bit 29 = Ignored
         bit 30 = De-register subchain handler
         bit 31 = Ignored
   R1 = pointer to device driver routine
   R2 = workspace parameter to pass in R12 when driver is called
   R3 = address of interrupt status byte for special handlers
   R4 = mask value for interrupt status byte for special handlers
On exit
   R0-R4 preserved

This SWI is used to remove a device handler from the list. The parameters supplied must match those given on registration.

Bit 30 is used to remove the top-level sub-chain handler. It is reserved for use by expansion hardware management modules.

Re-registering device drivers

If the core IRQ module is restarted (or replaced) it will be necessary for devices to re-register themselves. Device drivers must watch for Service_DeviceRegister, documented below, and re-register them device claims appropriately.

Device driver routines

The device driver routines called by the IRQ module are approximately equivalent to those used by earlier versions of RISC OS. In earlier versions of RISC OS the only registers defined on entry were R3 and R12 (the IOC memory space and the workspace parameter supplied at registration), and on exit the routine may corrupt R0-R3 and R12. The new API provides additional information to the handler routine :

On entry
   R0 = device number
   R1 = parameter to pass in R0 to clear IRQ
   R2 = pointer to routine to call to clear IRQ
   R3 = pointer to IRQ handler dependant workspace
   R12 = workspace parameter as supplied on claim
On exit
   R0-R3, R12 may be corrupted if claimed
   R0 preserved, R1-R3 and R12 corrupted if not claimed

The device driver may claim the interrupt by loading the return parameter from the stack, just as would be done to claim a software vector. For example :

   LDR     pc, [sp], #4

Routines registered with the old interface ('pass on' bit 31 unset) will be treated as having claimed the interrupt regardless of how they return.

Clearing IRQs

The routine and parameter provided by the IRQ handler in R1 and R2 may be used to clear the IRQ state from the controller. This feature may not be supported by all IRQ controllers, and may not be available for all devices. Where no operation is provided by the core IRQ handler to clear IRQs this will be documented with the IRQ handler and the routine will merely return immediately. The routine corrupts R0-R3 and R12.

It is important that IRQs be cleared from their controller's state in the correct order for the hardware. If the hardware must be serviced before the IRQ is cleared, this must be done first.

Service calls

The core IRQ handler will issue a new service call as it initialises. This should allow clients to re-register themselves with the core handler. An indication is passed in R0 of the devices which should be re-registered. If this device number is -1, all devices except special handlers should re-register themselves. Special handlers (those which require R3 and R4 to be supplied) should only register when they receive an explicit service call.

On entry
   R0 = device number, or -1 for all devices except special handlers
   R1 = &E2 (service call Service_DeviceReregister)
On exit
   All registers preserved

This service call is issued by the core IRQ handler or by any special sub-chain handlers on their registration. Device drivers should check the device number in R0 for devices they service and re-register themselves with OS_ClaimDeviceVector. All device drivers except special handlers should register themselves if the device number is -1.

Hardware-specific Core IRQ handler information

IOMD Core IRQ handler

The core IRQ handler for IOMD conforms to the devices list given in PRM 5a-31. All devices can be enabled and disabled using the interface returned by OS_ClaimDeviceVector with R0 bit 29 set.

Only devices 0-7 can have their IRQs cleared by the interface returned through the the device vector.

Special sub-chain handlers are registered for devices 8 (podule FIQ downgrade) and 13 (podule IRQ) and R3 and R4 must be set up appropriately.

If a Service_DeviceRegister is received podule device handlers should only register for devices in R0 of 8 and 13. Other device handlers should re-register for their device number or device -1. Most of the extant podule and system device drivers do not obey the Service_DeviceRegister service and replacement of the core IRQ handler on IOMD systems is not recommended.

Access to the memory for the special devices used by the sub-chain handlers will be byte-based.


This documentation is copyright 3QD Developments Ltd 2013 and may not be reproduced or published in any form without the copyright holders permission. RISC OS is subject to continuous development and improvement as such all information is reproduced by 3QD Developments Ltd in good faith and is believed to be correct at the time of publication E&OE. 3QD Developments Ltd cannot accept any liability for any loss or damage arising from the use of any information provided as part of the RISC OS Documentation.

HTML document version 1.03 3rd November 2015