language-Modula2-0.1: examples/Modula-2_Libraries/PMOS/sources/general/miscpmos.mod
IMPLEMENTATION MODULE MiscPMOS;
(************************************************)
(* *)
(* Miscellaneous PMOS procedures *)
(* *)
(* Programmer: P. Moylan *)
(* Last edited: 24 August 1994 *)
(* Status: OK *)
(* The FST code is incompletely tested. *)
(* *)
(************************************************)
FROM SYSTEM IMPORT BYTE (*<FST , ASSEMBLER >*);
(*<TopSpeed*)
FROM SYSTEM IMPORT
(* proc *) DI, SetFlags, GetFlags;
FROM Lib IMPORT
(* proc *) Intr;
(*>*)
(*<FST IMPORT System; >*)
FROM LowLevel IMPORT
(* proc *) LowByte, InByte, OutByte;
(************************************************************************)
(* STRING COPY *)
(************************************************************************)
PROCEDURE CopyString (source: ARRAY OF CHAR; VAR (*OUT*) dest: ARRAY OF CHAR);
(* Copies a string, with truncation or null termination as needed. *)
(* This function is provided in order to help software portability, *)
(* i.e. to avoid having to rewrite code for no reason other than *)
(* a change of compilers. *)
VAR j, last: CARDINAL; AddNull: BOOLEAN;
BEGIN
last := HIGH(dest);
AddNull := HIGH(source) < last;
IF AddNull THEN last := HIGH(source) END (*IF*);
FOR j := 0 TO last DO dest[j] := source[j] END (*FOR*);
IF AddNull THEN dest[last+1] := CHR(0) END (*IF*);
END CopyString;
(************************************************************************)
(* PROCEDURES TO ACCESS CMOS *)
(************************************************************************)
CONST
CMOSAddressPort = 70H;
CMOSDataPort = CMOSAddressPort + 1;
(************************************************************************)
PROCEDURE ReadCMOS (location: CMOSaddress): BYTE;
(* Returns the value at the given CMOS location. *)
BEGIN
OutByte (CMOSAddressPort, LowByte(location));
RETURN InByte (CMOSDataPort);
END ReadCMOS;
(************************************************************************)
PROCEDURE WriteCMOS (location: CMOSaddress; value: BYTE);
(* Stores a value at the given CMOS location. *)
BEGIN
OutByte (CMOSAddressPort, LowByte(location));
OutByte (CMOSDataPort, value);
END WriteCMOS;
(************************************************************************)
(* BIOS/MS-DOS CALLS *)
(************************************************************************)
PROCEDURE BIOS (InterruptNumber: CARDINAL;
VAR (*INOUT*) Registers: RegisterPacket);
(* Performs a software interrupt, with the given interrupt number, *)
(* after loading the components of variable "Registers" into the *)
(* machine registers. After the handler returns, the updated *)
(* register values are put back into variable "Registers". *)
BEGIN
(*<TopSpeed*) Intr (Registers, CARDINAL(InterruptNumber)); (*>*)
(*<FST
System.AX := Registers.AX;
System.BX := Registers.BX;
System.CX := Registers.CX;
System.DX := Registers.DX;
System.BP := Registers.BP;
System.SI := Registers.SI;
System.DI := Registers.DI;
System.DS := Registers.DS;
System.ES := Registers.ES;
System.XTrap (InterruptNumber);
Registers.AX := System.AX;
Registers.BX := System.BX;
Registers.CX := System.CX;
Registers.DX := System.DX;
Registers.BP := System.BP;
Registers.SI := System.SI;
Registers.DI := System.DI;
Registers.DS := System.DS;
Registers.ES := System.ES;
>*)
END BIOS;
(************************************************************************)
(* MISCELLANEOUS LOW-LEVEL OPERATIONS *)
(************************************************************************)
PROCEDURE EnterCriticalSection (): CARDINAL;
(* Saves the processor flags word, including the current "interrupt *)
(* enable" status, on the caller's stack, and returns with *)
(* interrupts disabled. NOTE: this procedure and the following *)
(* one should be used as a matched pair. *)
VAR SavedProcessorStatus: CARDINAL;
BEGIN
(*<TopSpeed*)
SavedProcessorStatus := GetFlags ();
DI();
(*>*)
(*<FST
ASM
PUSHF
POP AX
MOV SavedProcessorStatus, AX
CLI
END (*ASM*);
>*)
RETURN SavedProcessorStatus;
END EnterCriticalSection;
(************************************************************************)
PROCEDURE LeaveCriticalSection (SavedProcessorStatus: CARDINAL);
(* Restores the processor flags word, including the "interrupt *)
(* enable" status, from the stack. NOTE: this procedure and the *)
(* one above should be used as a matched pair. *)
BEGIN
(*<TopSpeed*)
SetFlags (SavedProcessorStatus);
(*>*)
(*<FST
ASM
MOV AX, SavedProcessorStatus
PUSH AX
POPF
END (*ASM*);
>*)
END LeaveCriticalSection;
(************************************************************************)
PROCEDURE ProcessorStatus(): CARDINAL;
(* Returns the current value of the processor flags word. *)
VAR result: CARDINAL;
BEGIN
(*<TopSpeed*)
RETURN GetFlags();
(*>*)
(*<FST
ASM
PUSHF
POP AX
MOV result, AX
END (*ASM*);
RETURN result;
>*)
END ProcessorStatus;
(************************************************************************)
PROCEDURE ShortDelay (amount: CARDINAL);
(* Provides a time delay for those cases where the required delay *)
(* is not long enough to justify a Sleep() operation. *)
(* The present version is not entirely satisfactory - needs to be *)
(* re-tuned for different compiler options, different processor *)
(* models, etc. This should be seen as an interim solution only. *)
VAR j: CARDINAL;
BEGIN
FOR j := 1 TO amount DO
END (*FOR*);
END ShortDelay;
(************************************************************************)
END MiscPMOS.