(* Version 1.10, Nov 1984 *)
DEFINITION MODULE Devices;
(*
   Additional facilities for device and interrupt handling

The MODULA-2/86 system (i.e. the run-time support)
maintains a device mask that indicates from which devices
interrupts are enabled. When the program is running at no
priority, this device mask is identical to the mask
register of the interrupt controller. If the program is
running at some priority, then the mask register of the
interrupt controller is set to the logical OR of the
device mask and the corresponding priority mask. When
the priority or the device mask changes, the MODULA-2/86
system will set the mask register of the interrupt
controller in this way. At any point in time, all the
interrupts masked out, either in the device mask or in the
current priority mask, are disabled. The priority mask for
'no priority' does not mask out any interrupt, i.e. its
value is all zeros.

When writing interrupt handlers in MODULA-2/86, it is
strongly recommended to use only the procedures provided
by this module, and not to access directly the mask
register of the interrupt controller.

The following should be performed in order to install an
interrupt handler: First save the old interrupt vector,
then set up the interrupt handler (IOTRANSFER), and if
necessary, save the current device status (interrupts
enabled or disabled) and enable interrupts from the
device.

Before the program terminates, or in order to remove an
interrupt handler, the following sequence of procedure
calls should be performed: If necessary, restore the old
device status or disable interrupts from the device, and
then restore the old interrupt vector.

At the end of a program the MODULA-2/86 system will reset
the mask register of the interrupt controller to its
initial value.
*)


FROM SYSTEM IMPORT ADDRESS;

EXPORT QUALIFIED
   GetDeviceStatus, SetDeviceStatus,
   SaveInterruptVector, RestoreInterruptVector;


PROCEDURE GetDeviceStatus(device: CARDINAL;
                          VAR enabled: BOOLEAN);
(*
- Return the status of a device in the device mask

in:   device    device to be checked

out:  enabled   TRUE if interrupts from the device are
                enabled, FALSE otherwise
*)


PROCEDURE SetDeviceStatus(device: CARDINAL;
                          enable: BOOLEAN);
(*
- Set the status of a device in the device mask

in:   device    device to enable or disable
      enable    if TRUE, enable interrupts from the
                device, otherwise disable them

The mask register of the interrupt controller will
be updated according to the current priority and
the new device mask.
*)


PROCEDURE SaveInterruptVector(vectorNr: CARDINAL;
                              VAR vector: ADDRESS);
(*
- Save the current value of an interrupt vector

in:   vectorNr   interrupt vector number

out:  vector     value of current interrupt vector
*)


PROCEDURE RestoreInterruptVector(vectorNr: CARDINAL;
                                 vector: ADDRESS);
(*
- Restore the value of an interrupt vector

in:   vectorNr   interrupt vector number
      vector     value to restore (previously saved
                 with 'SaveInterruptVector')
*)


END Devices.
