DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦9e581fb6d⟧ Ada Source

    Length: 17408 (0x4400)
    Types: Ada Source
    Notes: 03_class, FILE, R1k_Segment, e3_tag, package body V_Timer_Support, seg_057f7c

Derivation

└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000
    └─ ⟦cfc2e13cd⟧ »Space Info Vol 2« 
        └─⟦this⟧ 

E3 Source Code



with Machine_Code;
with System;
use System;
with Unchecked_Conversion;
with V_Krn_Conf_I;
use V_Krn_Conf_I;
with Krn_Defs;
with V_Bits;
with V_I_Types;
with V_I_Timeop;
with V_Cpu_Conf;
with Link_Block;
with Grp_Table;
with Machine_Types;
with V_Ada_Info;

package body V_Timer_Support is
    use V_I_Types;
    use V_I_Timeop;
    use Machine_Types;

    -- COUNT_DOWN.TIM             (MUST BE CONFIGURED FOR BOARD)
    --
    -- This package body contains the timer support subprograms implementing
    -- the single count down timer model. A count down timer is setup to
    -- generate a timer interrupt after a variable number of seconds (duration
    -- units).  A single timer is used for both maintaining the current time
    -- and scheduling alarms.
    --
    -- Refer to the following package bodies in BOARD_SUPPORT
    -- directory for templates of support routines implemented using different
    -- timer models:
    --  STUB.TIM                  - null, stubbed routines
    --  PERIODIC.TIM      - uses single timer that interrupts at a fixed
    --                      periodic rate
    --
    -- To use a different model, simply delete the source for this
    -- V_TIMER_SUPPORT package body from this file and include one of the
    -- above files.

    One_Msec : constant Duration := 0.001;

    Next_Interrupt_Time : Time_T := (Day => 0, Sec => 0.0);
    -- Time of next timer interrupt

    Alarm_Flag : Boolean := False;
    -- Set if an alarm has been scheduled

    Next_Alarm_Time : Time_T := (Day => 0, Sec => 0.0);
    -- Time of next alarm

    -- *************************************************************
    --
    -- THE FOLLOWING TYPES AND CONSTANTS ARE TO BE CONFIGURED
    -- FOR YOUR BOARD
    --
    -- *************************************************************
    --&&&&&&&&&&&& SUPPRIMER Counter_T du commentaire &&&&&&&&&&
    --  type Counter_T is range 0 .. 255;
    --  for Counter_T'Size use 8;
    --&&&&&&&&&&&& SUPPRIMER Counter_T du commentaire &&&&&&&&&&

    -- Board specific counter type.
    -- ONLY UPDATE the range and size.

    Counts_Per_Msec : constant := 12;
    -- machine 2,4576Mhz and  Timer in delay mode = 200 prescaler

    -- This is the number of ticks per millisecond

    Max_Count : constant := 255;
    -- This is the maximum count that the timer can be set to

    -- The corresponding maximum duration. Where,
    Max_Duration : constant := (Max_Count / Counts_Per_Msec) * 0.001;
    -- Note: maximum duration allowed is 12 hours.
    Min_Count : constant := 1;
    -- This represents the minimum count between timer interrupts
    -- The corresponding minimum duration. Where,
    Min_Duration : constant := (Min_Count / Counts_Per_Msec) * 0.001;


    -- *************************************************************
    --
    -- THE FOLLOWING SUBPROGRAMS ARE TO BE CONFIGURED FOR YOUR BOARD
    --
    -- *************************************************************

    function Get_Interrupt_Vector_Number return System.Address is
    begin
        return System.To_Address (2#1000_1101#);
    end Get_Interrupt_Vector_Number;
    procedure Init_Timer is
        use V_Bits;
        -- Initializes the timer device hardware registers

        -- MC68155 PICU Register
        Register_R0 : Byte;     -- pointer registers CR1/CR6
        Register_R1 : Byte;     --
        Register_R3 : Byte;     -- local interrupt mask register
        Register_R5 : Byte;     -- system bus interrupt mask register
        for Register_R0 use at System.To_Address (16#0301_0020#);
        for Register_R1 use at System.To_Address (16#0301_0022#);
        for Register_R3 use at System.To_Address (16#0301_0026#);
        for Register_R5 use at System.To_Address (16#0301_002A#);

        -- MC68901 Timer register
        Register_Vr : Byte;     -- Vector register
        Register_Iera : Byte;   -- Interrupt enable register A
        Register_Imra : Byte;   -- Interrupt mask register A
        for Register_Vr use at System.To_Address (16#0301_000B#);
        for Register_Iera use at System.To_Address (16#0301_0003#);
        for Register_Imra use at System.To_Address (16#0301_0009#);
    begin

        -- Interrupt handler configuration

        Register_R3 := Machine_Types.Byte
                          (Bit_Or (Machine_Types.Byte'Pos (Register_R3),
                                   2#0000_0100#));
        Register_R5 := Machine_Types.Byte
                          (Bit_Or (Machine_Types.Byte'Pos (Register_R5),
                                   2#0000_0000#));
        Register_R0 := 2#0000_0010#;
        Register_R1 := 2#0000_0000#;


        -- Interrupt Timer configuration
        Register_Vr := 2#1000_0000#;   -- define the most signicant bits of IVR
        Register_Iera :=
           Machine_Types.Byte
              (Bit_Or (Machine_Types.Byte'Pos (Register_Iera), 2#0010_0000#));
        Register_Imra :=
           Machine_Types.Byte
              (Bit_Or (Machine_Types.Byte'Pos (Register_Imra), 2#0010_0000#));

    end Init_Timer;

    procedure Set_Timer (Count : Counter_T) is
        -- Sets the timer to generate an interrupt after count ticks
        Register_Tadr : Byte; -- Timer A data register
        Register_Tacr : Byte; -- Timer A control register
        for Register_Tadr use at System.To_Address (16#0301_000F#);
        for Register_Tacr use at System.To_Address (16#0301_000C#);
    begin
        Register_Tacr := 2#0000_0000#;  -- Stop timer
        Register_Tadr := Byte (Count);  -- load the count
        Register_Tacr := 2#0000_0111#;  -- restore the timer

    end Set_Timer;

    procedure Read_Timer (Count : out Counter_T) is
        -- Reads the remaining timer count until the next interrupt

        Register_Tadr : Byte; -- Timer A data register
        for Register_Tadr use at System.To_Address (16#0301_000F#);
    begin
        Count := Counter_T (Register_Tadr);
    end Read_Timer;

    procedure Clear_Timer_Interrupt is
        -- Clears current timer interrupt
        Register_Iera : Byte;   -- Interrupt enable register A
        Register_Tacr : Byte; -- Timer A control register
        for Register_Tacr use at System.To_Address (16#0301_000C#);
        for Register_Iera use at System.To_Address (16#0301_0003#);
        use V_Bits;
    begin
        Register_Tacr := 2#0000_0000#;  -- Stop timer
        Register_Iera :=
           Machine_Types.Byte
              (Bit_And (Machine_Types.Byte'Pos (Register_Iera), 2#1101_1111#));
        Register_Iera :=
           Machine_Types.Byte
              (Bit_Or (Machine_Types.Byte'Pos (Register_Iera), 2#0010_0000#));
    end Clear_Timer_Interrupt;
    pragma Inline_Only (Clear_Timer_Interrupt);


    -- *************************************************************
    --
    -- END OF BOARD SPECIFIC CONFIGURATION
    --
    -- *************************************************************

    function Duration_To_Count (Sec : Duration) return Counter_T is
        -- Converts duration seconds into timer tick counts
    begin
        return Counter_T (Sec / One_Msec) * Counts_Per_Msec;
    end Duration_To_Count;
    pragma Inline_Only (Duration_To_Count);

    procedure Init is
        -- Resets the clock's current time. Initializes the timer device.
        -- This procedure is called during kernel startup.
    begin
        Next_Interrupt_Time := (Day => 0, Sec => Max_Duration);
        Alarm_Flag := False;

        -- Initialize timer hardware registers
        Init_Timer;

        -- Get timer counting down
        Set_Timer (Max_Count);
    end Init;

    procedure Set_Time (Day : Day_T;
                        Sec : Duration;
                        Timer_Support_Arg : Address := No_Addr) is
        -- Resets the clock's current time with the input parameter.
        -- Cancels active alarm which will be rescheduled later.

        Intr_Status : V_Krn_Conf_I.Intr_Status_T;
    begin
        -- Disable interrupts to inhibit potential interaction with
        -- timer interrupt handler
        V_Krn_Conf_I.Interrupts_Disable (Intr_Status);

        Next_Interrupt_Time := (Day => Day, Sec => Sec) +
                                  (Day => 0, Sec => Max_Duration);
        Alarm_Flag := False;

        -- Get timer counting down
        Set_Timer (Max_Count);
        V_Krn_Conf_I.Interrupts_Restore (Intr_Status);
    end Set_Time;

    procedure Get_Current_Time (Day : out Day_T; Sec : out Duration) is
        -- Gets the clock's current time. The returned time is
        -- normalized so that its seconds component is less than a day.
        -- This function is called both by the kernel for
        -- calculating a time to pass to schedule_alarm and by
        -- CALENDAR package which traps to kernel to get current time.

        Count : Counter_T;
        Intr_Status : V_Krn_Conf_I.Intr_Status_T;
        Time : Time_T;
    begin
        -- Disable interrupts to inhibit potential interaction with
        -- timer interrupt handler
        V_Krn_Conf_I.Interrupts_Disable (Intr_Status);

        -- Current time is the time at the next interrupt minus
        -- the time represented by the remaining ticks to be counted down
        Read_Timer (Count);
        Time := Next_Interrupt_Time -
                   (Day => 0,
                    Sec => Integer (Count / Counts_Per_Msec) * One_Msec);

        V_Krn_Conf_I.Interrupts_Restore (Intr_Status);
        Day := Time.Day;
        Sec := Time.Sec;
    end Get_Current_Time;
    procedure Schedule_Alarm (Alarm_Day : Day_T; Alarm_Sec : Duration) is
        -- Schedules an alarm to be posted some time in the future.
        --
        -- This procedure is called by the kernel whenever a future timing event
        -- must occur. The kernel passes in an absolute (not relative) time in the
        -- future when an alarm should occur. The kernel computes this time by
        -- adding some amount onto the value returned by GET_CURRENT_TIME.
        -- Examples are the expiration of a delay or the end of the time slice.
        --
        -- SCHEDULE_ALARM is always called with the time of the earliest alarm.
        --
        -- When the current time reaches alarm_time,
        -- V_KRN_CONF_I.POST_ALARM should be called to post the alarm.

        Intr_Status : V_Krn_Conf_I.Intr_Status_T;
        Alarm : Time_T;
        Current_Time : Time_T;
        Next_Minus_Min : Time_T;
        Current_Plus_Min : Time_T;
        Alarm_Time : Time_T := (Day => Alarm_Day, Sec => Alarm_Sec);
    begin
        -- Disable interrupts to inhibit potential interaction with
        -- timer interrupt handler
        V_Krn_Conf_I.Interrupts_Disable (Intr_Status);

        Next_Minus_Min := Next_Interrupt_Time - (Day => 0, Sec => Min_Duration);
        if Alarm_Time <= Next_Minus_Min then
            Get_Current_Time (Current_Time.Day, Current_Time.Sec);
            Current_Plus_Min := Current_Time + (Day => 0, Sec => Min_Duration);
            -- reset timer for new interval inserted before current
            -- interval would expire
            if Alarm_Time < Current_Plus_Min then
                Alarm := Current_Plus_Min;
            else
                Alarm := Alarm_Time;
            end if;

            if Alarm < Next_Minus_Min then
                Next_Interrupt_Time := Alarm;
                Set_Timer (Duration_To_Count ("-" (Alarm, Current_Time).Sec));
            end if;
        end if;

        Alarm_Flag := True;
        Next_Alarm_Time := Alarm_Time;

        V_Krn_Conf_I.Interrupts_Restore (Intr_Status);
    end Schedule_Alarm;

    -- Cancels a previously scheduled alarm.
    procedure Cancel_Alarm is
    begin
        Alarm_Flag := False;
    end Cancel_Alarm;

    procedure Process_Timer_Interrupt is
        -- Processes the timer interrupt by advancing the current time and
        -- checking if the time for the next alarm has been reached.

        Delta_Duration : Duration := Max_Duration;
        Delta_Count : Counter_T := Max_Count;
        Delta_Alarm : Time_T;
        Intr_Status : V_Krn_Conf_I.Intr_Status_T;
        Post_Flag : Boolean := False;
    begin
        -- Clears current timer interrupt
        Clear_Timer_Interrupt;

        -- Disable interrupts to inhibit potential interaction with
        -- other handlers that may want to read the current time
        V_Krn_Conf_I.Interrupts_Disable (Intr_Status);

        if Alarm_Flag then
            if Next_Alarm_Time <= Next_Interrupt_Time then
                Alarm_Flag := False;
                Post_Flag := True;
            else
                Delta_Alarm := Next_Alarm_Time - Next_Interrupt_Time;
                if Delta_Alarm.Day /= 0 or
                   Delta_Alarm.Sec >= Max_Duration * 2 then
                    null;
                elsif Delta_Alarm.Sec < Min_Duration then
                    Delta_Duration := Min_Duration;
                    Delta_Count := Min_Count;
                elsif Delta_Alarm.Sec <= Max_Duration then
                    Delta_Duration := Delta_Alarm.Sec;
                    Delta_Count := Duration_To_Count (Delta_Duration);
                else
                    Delta_Duration := Delta_Alarm.Sec / 2;
                    Delta_Count := Duration_To_Count (Delta_Duration);
                end if;
            end if;
        end if;

        Next_Interrupt_Time := Next_Interrupt_Time +
                                  (Day => 0, Sec => Delta_Duration);
        Set_Timer (Delta_Count);

        V_Krn_Conf_I.Interrupts_Restore (Intr_Status);

        if Post_Flag then
            V_Krn_Conf_I.Post_Alarm;
        end if;

    end Process_Timer_Interrupt;

end V_Timer_Support;

E3 Meta Data

    nblk1=10
    nid=c
    hdr6=1e
        [0x00] rec0=22 rec1=00 rec2=01 rec3=02a
        [0x01] rec0=1a rec1=00 rec2=04 rec3=050
        [0x02] rec0=1a rec1=00 rec2=10 rec3=088
        [0x03] rec0=18 rec1=00 rec2=02 rec3=014
        [0x04] rec0=17 rec1=00 rec2=03 rec3=020
        [0x05] rec0=18 rec1=00 rec2=0d rec3=00a
        [0x06] rec0=18 rec1=00 rec2=0b rec3=076
        [0x07] rec0=09 rec1=00 rec2=0a rec3=044
        [0x08] rec0=1c rec1=00 rec2=05 rec3=018
        [0x09] rec0=18 rec1=00 rec2=06 rec3=022
        [0x0a] rec0=14 rec1=00 rec2=07 rec3=036
        [0x0b] rec0=16 rec1=00 rec2=0f rec3=012
        [0x0c] rec0=1e rec1=00 rec2=08 rec3=022
        [0x0d] rec0=18 rec1=00 rec2=0e rec3=01c
        [0x0e] rec0=19 rec1=00 rec2=09 rec3=000
        [0x0f] rec0=19 rec1=00 rec2=09 rec3=000
    tail 0x2176547ae87da833ef640 0x42a00088462060003
Free Block Chain:
  0xc: 0000  00 00 00 04 80 01 49 01 02 03 04 73 74 65 72 5f  ┆      I    ster_┆