|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 24576 (0x6000)
Types: Ada Source
Notes: 03_class, FILE, R1k_Segment, e3_tag, package Krn_Defs, seg_04cdf4
└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000
└─⟦cfc2e13cd⟧ »Space Info Vol 2«
└─⟦this⟧
-- Copyright 1991,1992,1993 Verdix Corporation
with System;
use System;
with Krn_Cpu_Defs;
with Link_Block;
with V_I_Types;
with Unchecked_Conversion;
package Krn_Defs is
pragma Suppress (All_Checks);
pragma Suppress (Exception_Tables);
pragma Not_Elaborated;
pragma Local_Access;
-- The Kernel's type definitions
type A_Boolean is access Boolean;
function To_A_Boolean is new Unchecked_Conversion (Address, A_Boolean);
-- Forward references
type Krn_Tcb_T;
type A_Krn_Tcb_T is access Krn_Tcb_T;
type Krn_Pcb_T;
type A_Krn_Pcb_T is access Krn_Pcb_T;
-- SPORADIC_TASK
type Krn_Sporadic_T;
type A_Krn_Sporadic_T is access Krn_Sporadic_T;
-- SPORADIC_TASK
-- Returned kernel service status
No_Memory : constant := -1;
Success : constant := 0;
Delta_Time : constant Day_T := -1;
-- Record types
type Record_Type_T is (R_Invalid, R_Fifo_Cond, R_Prio_Cond,
R_Fifo_Cond_Attr, R_Prio_Cond_Attr, R_Fifo_Mutex,
R_Prio_Mutex, R_Prio_Inherit_Mutex,
R_Prio_Ceiling_Mutex, R_Intr_Mutex,
R_Fifo_Mutex_Attr, R_Prio_Mutex_Attr,
R_Prio_Inherit_Mutex_Attr, R_Prio_Ceiling_Mutex_Attr,
R_Intr_Mutex_Attr, R_Semaphore,
R_Semaphore_Attr, R_Count_Semaphore, R_Mailbox);
-- Values corresponding to a zero/non-zero for the CPU specific
-- test-and-set instruction
type Test_And_Set_T is new V_I_Types.Test_And_Set_T;
Test_And_Set_False : constant Test_And_Set_T :=
Test_And_Set_T (V_I_Types.Test_And_Set_False);
Test_And_Set_True : constant Test_And_Set_T :=
Test_And_Set_T (V_I_Types.Test_And_Set_True);
--------------------------------------------------------------------------
-- Interrupt types (OS DEPENDENT)
--------------------------------------------------------------------------
-- Exception vector table ID's
subtype Intr_Vector_Id_T is Natural;
-- Interrupt enable/disable status: Interrupt Priority Level (IPL)
-- mask stored in Status Register
subtype Intr_Status_T is Integer;
Disable_Intr_Status : constant Intr_Status_T := 16#0700#;
Enable_Intr_Status : constant Intr_Status_T := 16#0000#;
Level_0_Intr_Status : constant Intr_Status_T := 16#0000#;
Level_1_Intr_Status : constant Intr_Status_T := 16#0100#;
Level_2_Intr_Status : constant Intr_Status_T := 16#0200#;
Level_3_Intr_Status : constant Intr_Status_T := 16#0300#;
Level_4_Intr_Status : constant Intr_Status_T := 16#0400#;
Level_5_Intr_Status : constant Intr_Status_T := 16#0500#;
Level_6_Intr_Status : constant Intr_Status_T := 16#0600#;
Level_7_Intr_Status : constant Intr_Status_T := 16#0700#;
-- Value return for a bad intr_vector passed to the interrupt
-- service routines
Bad_Intr_Vector : constant Address := Memory_Address (16#FFFF_FFFF#);
--------------------------------------------------------------------------
-- Condition variable and mutex types
--------------------------------------------------------------------------
type Cond_Attr_T is
record
Rec_Type : Record_Type_T;
-- valid rec_type are: R_FIFO_COND_ATTR | R_PRIO_COND_ATTR
end record;
type A_Cond_Attr_T is access Cond_Attr_T;
function To_A_Cond_Attr_T is
new Unchecked_Conversion (Address, A_Cond_Attr_T);
function To_Address is new Unchecked_Conversion (A_Cond_Attr_T, Address);
-- DEFAULT_COND_ATTR: constant a_cond_attr_t := null;
function Default_Cond_Attr return A_Cond_Attr_T;
pragma Inline_Only (Default_Cond_Attr);
type Cond_T is
record
Rec_Type : Record_Type_T;
-- valid rec_type are: R_FIFO_COND | R_PRIO_COND
T_Head : A_Krn_Tcb_T;
T_Tail : A_Krn_Tcb_T;
end record;
type A_Cond_T is access Cond_T;
function To_A_Cond_T is new Unchecked_Conversion (Address, A_Cond_T);
function To_Address is new Unchecked_Conversion (A_Cond_T, Address);
type Mutex_Attr_T is
record
Rec_Type : Record_Type_T;
-- valid rec_type are: R_FIFO_MUTEX_ATTR | R_PRIO_MUTEX_ATTR
-- also for PRIORITY_INHERITANCE: R_PRIO_INHERIT_MUTEX_ATTR
Pad : Intr_Status_T; -- must be large enough
-- to accommodate space needed
-- by other mutex attribute
-- record types
end record;
type A_Mutex_Attr_T is access Mutex_Attr_T;
function To_A_Mutex_Attr_T is
new Unchecked_Conversion (Address, A_Mutex_Attr_T);
function To_Address is new Unchecked_Conversion (A_Mutex_Attr_T, Address);
-- DEFAULT_MUTEX_ATTR: constant a_mutex_attr_t := null;
function Default_Mutex_Attr return A_Mutex_Attr_T;
pragma Inline_Only (Default_Mutex_Attr);
type Intr_Attr_T is
record
Rec_Type : Record_Type_T;
-- only valid rec_type is: R_INTR_MUTEX_ATTR
Disable_Status : Intr_Status_T;
end record;
type A_Intr_Attr_T is access Intr_Attr_T;
function To_A_Intr_Attr_T is
new Unchecked_Conversion (Address, A_Intr_Attr_T);
function To_A_Intr_Attr_T is new Unchecked_Conversion
(A_Mutex_Attr_T, A_Intr_Attr_T);
function To_A_Mutex_Attr_T is new Unchecked_Conversion
(A_Intr_Attr_T, A_Mutex_Attr_T);
function To_Address is new Unchecked_Conversion (A_Intr_Attr_T, Address);
-- DEFAULT_INTR_ATTR: constant a_mutex_attr_t :=
--\x09\x09to_a_mutex_attr_t(memory_address(1));
function Default_Intr_Attr return A_Mutex_Attr_T;
pragma Inline_Only (Default_Intr_Attr);
type Prio_Ceiling_Attr_T is
record
Rec_Type : Record_Type_T;
-- only valid rec_type is: R_PRIO_CEILING_MUTEX_ATTR
Ceiling_Prio : Priority;
end record;
type A_Prio_Ceiling_Attr_T is access Prio_Ceiling_Attr_T;
function To_A_Prio_Ceiling_Attr_T is
new Unchecked_Conversion (Address, A_Prio_Ceiling_Attr_T);
function To_A_Prio_Ceiling_Attr_T is
new Unchecked_Conversion (A_Mutex_Attr_T, A_Prio_Ceiling_Attr_T);
function To_A_Mutex_Attr_T is
new Unchecked_Conversion (A_Prio_Ceiling_Attr_T, A_Mutex_Attr_T);
function To_Address is new Unchecked_Conversion
(A_Prio_Ceiling_Attr_T, Address);
type Mutex_Pad_T is array (1 .. 2) of Intr_Status_T;
type Mutex_T;
type A_Mutex_T is access Mutex_T;
type Mutex_T is
record
Rec_Type : Record_Type_T;
-- valid rec_type are: R_FIFO_MUTEX | R_PRIO_MUTEX
-- also for PRIORITY_INHERITANCE: R_PRIO_INHERIT_MUTEX
-- also for PRIORITY_CEILING: R_PRIO_CEILING_MUTEX
T_Head : A_Krn_Tcb_T;
T_Tail : A_Krn_Tcb_T;
Flag : Test_And_Set_T;
Others_Waiting : Boolean;
Owner : A_Krn_Tcb_T; -- for INHERITANCE or CEILING
Q_Next : A_Mutex_T; -- " "
Ceiling_Prio : Integer; -- for R_PRIO_CEILING_MUTEX
Pad : Mutex_Pad_T; -- must be large enough
-- to accommodate space needed
-- by other mutex record types
end record;
function To_A_Mutex_T is new Unchecked_Conversion (Address, A_Mutex_T);
function To_Address is new Unchecked_Conversion (A_Mutex_T, Address);
type Intr_Mutex_T is
record
Rec_Type : Record_Type_T;
-- only valid rec_type is: R_INTR_MUTEX
Disable_Status : Intr_Status_T;
Restore_Status : Intr_Status_T;
end record;
type A_Intr_Mutex_T is access Intr_Mutex_T;
function To_A_Intr_Mutex_T is
new Unchecked_Conversion (A_Mutex_T, A_Intr_Mutex_T);
function To_A_Mutex_T is new Unchecked_Conversion
(A_Intr_Mutex_T, A_Mutex_T);
function To_Address is new Unchecked_Conversion (A_Intr_Mutex_T, Address);
--------------------------------------------------------------------------
-- Semaphore types (Only FIFO queuing)
--------------------------------------------------------------------------
type Semaphore_T is
record
Rec_Type : Record_Type_T;
-- only valid rec_type is: R_SEMAPHORE
T_Head : A_Krn_Tcb_T;
T_Tail : A_Krn_Tcb_T;
Flag : Test_And_Set_T;
Others_Waiting : Boolean;
end record;
type A_Semaphore_T is access Semaphore_T;
function To_A_Semaphore_T is
new Unchecked_Conversion (Address, A_Semaphore_T);
function To_Address is new Unchecked_Conversion (A_Semaphore_T, Address);
type Semaphore_Attr_T is
record
Rec_Type : Record_Type_T := R_Semaphore_Attr;
-- only valid rec_type is: R_SEMAPHORE_ATTR
end record;
type A_Semaphore_Attr_T is access Semaphore_Attr_T;
function To_A_Semaphore_Attr_T is
new Unchecked_Conversion (Address, A_Semaphore_Attr_T);
function To_Address is new Unchecked_Conversion
(A_Semaphore_Attr_T, Address);
-- DEFAULT_SEMAPHORE_ATTR: constant a_semaphore_attr_t := null;
function Default_Semaphore_Attr return A_Semaphore_Attr_T;
pragma Inline_Only (Default_Semaphore_Attr);
--------------------------------------------------------------------------
-- Counting semaphore types
--------------------------------------------------------------------------
type Count_Semaphore_T is
record
Rec_Type : Record_Type_T;
-- only valid rec_type is: R_COUNT_SEMAPHORE
Mutex : Mutex_T;
Cond : Cond_T;
Count : Integer;
end record;
type A_Count_Semaphore_T is access Count_Semaphore_T;
function To_A_Count_Semaphore_T is
new Unchecked_Conversion (Address, A_Count_Semaphore_T);
function To_Address is new Unchecked_Conversion
(A_Count_Semaphore_T, Address);
subtype Count_Semaphore_Attr_T is Mutex_Attr_T;
subtype A_Count_Semaphore_Attr_T is A_Mutex_Attr_T;
function To_A_Count_Semaphore_Attr_T is
new Unchecked_Conversion (Address, A_Count_Semaphore_Attr_T);
-- DEFAULT_COUNT_SEMAPHORE_ATTR: constant a_count_semaphore_attr_t := null;
function Default_Count_Semaphore_Attr return A_Count_Semaphore_Attr_T;
pragma Inline_Only (Default_Count_Semaphore_Attr);
subtype Count_Intr_Attr_T is Intr_Attr_T;
subtype A_Count_Intr_Attr_T is A_Intr_Attr_T;
function To_A_Count_Intr_Attr_T is
new Unchecked_Conversion (Address, A_Count_Intr_Attr_T);
function To_A_Count_Semaphore_Attr_T is
new Unchecked_Conversion (A_Count_Intr_Attr_T, A_Count_Semaphore_Attr_T);
-- DEFAULT_COUNT_INTR_ATTR: constant a_count_semaphore_attr_t :=
--\x09\x09to_a_count_semaphore_attr_t(memory_address(1));
function Default_Count_Intr_Attr return A_Count_Semaphore_Attr_T;
pragma Inline_Only (Default_Count_Intr_Attr);
--------------------------------------------------------------------------
-- Mailbox types
--------------------------------------------------------------------------
type Unit_T is range -2 ** (Storage_Unit - 1) ..
2 ** (Storage_Unit - 1) - 1;
for Unit_T'Size use Storage_Unit;
type Slots_T is array (Positive range <>, Positive range <>) of Unit_T;
type A_Slots_T is access Slots_T;
function To_A_Slots_T is new Unchecked_Conversion (Address, A_Slots_T);
function To_Address is new Unchecked_Conversion (A_Slots_T, Address);
type Mailbox_T is
record
Rec_Type : Record_Type_T;
-- only valid rec_type is: R_MAILBOX
Mutex : Mutex_T;
Read_Cond : Cond_T;
Slots_Cnt : Natural;
Slot_Len : Natural;
Msg_Cnt : Natural;
Bottom : Address;
Top : Address;
Read_Addr : Address;
Write_Addr : Address;
end record;
type A_Mailbox_T is access Mailbox_T;
function To_A_Mailbox_T is new Unchecked_Conversion (Address, A_Mailbox_T);
function To_Address is new Unchecked_Conversion (A_Mailbox_T, Address);
subtype Mailbox_Attr_T is Mutex_Attr_T;
subtype A_Mailbox_Attr_T is A_Mutex_Attr_T;
function To_A_Mailbox_Attr_T is new Unchecked_Conversion (Address, A_Mailbox_Attr_T);
-- DEFAULT_MAILBOX_ATTR: constant a_mailbox_attr_t := null;
function Default_Mailbox_Attr return A_Mailbox_Attr_T;
pragma Inline_Only (Default_Mailbox_Attr);
subtype Mailbox_Intr_Attr_T is Intr_Attr_T;
subtype A_Mailbox_Intr_Attr_T is A_Intr_Attr_T;
function To_A_Mailbox_Intr_Attr_T is
new Unchecked_Conversion (Address, A_Mailbox_Intr_Attr_T);
function To_A_Mailbox_Attr_T is
new Unchecked_Conversion (A_Mailbox_Intr_Attr_T, A_Mailbox_Attr_T);
-- DEFAULT_MAILBOX_INTR_ATTR: constant a_mailbox_attr_t :=
--\x09\x09to_a_mailbox_attr_t(memory_address(1));
function Default_Mailbox_Intr_Attr return A_Mailbox_Attr_T;
pragma Inline_Only (Default_Mailbox_Intr_Attr);
--------------------------------------------------------------------------
-- Callout and task storage types
--------------------------------------------------------------------------
-- Callout events
type Callout_Event_T is
(Exit_Event, Unexpected_Exit_Event, Idle_Event,
Program_Switch_Event, -- stack limit checking must be suppressed
Task_Create_Event, Task_Switch_Event, Task_Complete_Event);
--[ Integer'size ne focntionne pas ]
-- for Callout_Event_T'Size use Integer'Size;
for Callout_Event_T'Size use 32;
-- Id for accessing user defined storage in the task control block
type Task_Storage_Id is new Integer;
No_Task_Storage_Id : constant Task_Storage_Id := Task_Storage_Id (0);
-- Callout Control Block
type Callout_T;
type A_Callout_T is access Callout_T;
type A_A_Callout_T is access A_Callout_T;
type Callout_T is
record
Q_Next : A_Callout_T;
Proc : Address;
Parent_Program : A_Krn_Pcb_T; -- needed for program switch callout
end record;
function To_A_Callout_T is new Unchecked_Conversion (Address, A_Callout_T);
function To_A_A_Callout_T is
new Unchecked_Conversion (Address, A_A_Callout_T);
type Calloutq_Heads_T is array (Callout_Event_T) of A_Callout_T;
--------------------------------------------------------------------------
-- Time event types
--------------------------------------------------------------------------
type Time_State_T is (Time_Stopped, Time_Counting,
Time_Overrun, Time_Canceled);
type Time_Event_T;
type A_Time_Event_T is access Time_Event_T;
type Time_Event_T is
record
Q_Next : A_Time_Event_T;
Q_Prev : A_Time_Event_T;
Time_State : Time_State_T;
Delay_Until_Flag : Boolean;
Day : Day_T;
Sec : Duration;
Proc : Address;
Arg : Address;
end record;
function To_A_Time_Event_T is
new Unchecked_Conversion (Address, A_Time_Event_T);
-- Program Control Block
type Krn_Pcb_T is
record
Q_Next : A_Krn_Pcb_T;
T_Head : A_Krn_Tcb_T;
User_Link_Block : Link_Block.A_Link_Block_T;
Terminated : Boolean; -- program is terminated,
-- but, waiting to be freed
Prio_Inherit_Support : Boolean; -- TRUE if kernel supports
-- PRIORITY_INHERITANCE
Prio_Ceiling_Support : Boolean; -- TRUE if kernel supports
-- PRIORITY_CEILING
Sporadic_Task_Support : Boolean; -- TRUE if kernel supports
-- SPORADIC_TASK
Is_Server : Boolean; -- set via
-- program_is_server()
-- when program contains
-- procedures called from
-- other programs. Inhibits
-- program termination.
-- Allows kernel exit
-- when no other programs
-- are still active.
My_Creator : A_Krn_Pcb_T; -- parent program
Terminate_Callout : Address; -- defined at
-- program create
Exit_Status : Integer; -- passed at program_exit
Alloc_Head : Address; -- krn_alloc.prog_new
-- allocations
Key : Address; -- user defined at
-- program create, main
-- is predefined as NO_ADDR
Sequence_Num : Integer; -- eventhough newly created
-- programs may share the
-- same program control
-- block, they have a
-- unique sequence number
Task_Storage_Avail : Integer; -- index into next avail
-- user storage in tcb
Calloutq_Heads : Calloutq_Heads_T;
Ada_Program_Id : Program_Id;
Exception_Stack_Size : Natural;
end record;
function To_A_Krn_Pcb_T is new Unchecked_Conversion (Address, A_Krn_Pcb_T);
type A_A_Krn_Pcb_T is access A_Krn_Pcb_T;
function To_A_A_Krn_Pcb_T is
new Unchecked_Conversion (Address, A_A_Krn_Pcb_T);
type Tstate_T is (T_Created, T_Ready, T_Executing, T_Waiting,
T_Suspended_At_Cond, T_Suspended_At_Mutex,
T_Suspended_At_Semaphore, T_Suspended_At_Delay,
T_Suspended_At_Name_Resolve, T_Suspended_Idle_Task,
T_In_Transition, T_Terminated);
Cpu_Number_Dont_Care : constant := -1;
Cpu_Number_This_Cpu : constant := -2;
-- Task control block
type Krn_Tcb_T is
record
Cpu_State : Krn_Cpu_Defs.Cpu_State_T;
Tstate : Tstate_T;
Task_Suspended_Flag : Boolean; -- when set, a READY task isn't
-- on the runq
Q_Next : A_Krn_Tcb_T;
Q_Prev : A_Krn_Tcb_T;
T_Link : A_Krn_Tcb_T;
Parent_Program : A_Krn_Pcb_T;
-- The following changes during a usr_prog.program_inter_call().
-- Otherwise, current_program = parent_program and
-- current_stack_limit_p =
-- parent_program.user_link_block.stack_limit_p.
Current_Program : A_Krn_Pcb_T;
Current_Stack_Limit_P : Address;
Cond_Mutex : A_Mutex_T;
Suspended_Queue : Address;
Preemption_Depth : Natural;
Signaled : Boolean;
Cur_Prio : Integer;
Delay_Event : Time_Event_T;
Time_Slice : Duration;
Start_Address : Address;
Stack_Size : Natural;
Stack_Area : Address;
Ada_Task_Id : Task_Id;
-- PRIORITY_INHERITANCE or PRIORITY_CEILING or SPORADIC_TASK
Mutex_Head : A_Mutex_T;
Static_Prio : Integer;
-- PRIORITY_INHERITANCE or PRIORITY_CEILING or SPORADIC_TASK
-- SPORADIC_TASK
Sporadic : A_Krn_Sporadic_T;
-- SPORADIC_TASK
Sequence_Num : Integer; -- task's unique sequence number
-- Storage available for the user follows the last field in the
-- krn_tcb_t record. The size is specified by the configuration
-- parameter, TASK_STORAGE_SIZE. The task's
-- parent_program.task_storage_avail points to the next avail slot.
end record;
type A_A_Krn_Tcb_T is access A_Krn_Tcb_T;
function To_A_A_Krn_Tcb_T is
new Unchecked_Conversion (Address, A_A_Krn_Tcb_T);
-- SPORADIC_TASK begin
type Krn_Replenishment_T;
type A_Krn_Replenishment_T is access Krn_Replenishment_T;
-- Sporadic task control block
type Krn_Sporadic_T is
record
My_Tcb : A_Krn_Tcb_T;
Low_Prio : Priority;
Replenish_Period : Duration;
Initial_Budget : Duration;
Min_Replenishment : Duration;
Replenishment_Count : Natural;
S_Link : A_Krn_Sporadic_T;
Avail_Exec_Time : Duration;
Rep_Addr : Address;
Rep_Head : A_Krn_Replenishment_T;
Rep_Tail : A_Krn_Replenishment_T;
Free_Rep_Head : A_Krn_Replenishment_T;
Rep_Event : Time_Event_T;
Force_High_Prio : Boolean;
-- SPORADIC_TASK_STATISTICS_ENABLED
-- Statistics
Exec_Cnt : Natural;
Background_Exec_Cnt : Natural;
Exec_Timeout_Cnt : Natural;
Rep_Timeout_Cnt : Natural;
-- SPORADIC_TASK_STATISTICS_ENABLED
end record;
Zero_Avail_Exec_Time : constant Duration := 0.0;
-- Sporadic task replenishment
type Krn_Replenishment_T is
record
Next : A_Krn_Replenishment_T;
Rep_Day : Day_T;
Rep_Sec : Duration;
Rep_Amount : Duration;
end record;
-- SPORADIC_TASK end
-- Ring for pending interrupt queue.
type Ring_Entry_T is
record
Proc : Address;
Arg : Address;
end record;
type A_Ring_Entry_T is access Ring_Entry_T;
-- Name services entry
type Name_Entry_T;
type A_Name_Entry_T is access Name_Entry_T;
type Name_Entry_T is
record
Next : A_Name_Entry_T;
Name_Len : Natural;
Name_Addr : Address;
Prg : A_Krn_Pcb_T;
Addr : Address;
end record;
function To_A_Name_Entry_T is
new Unchecked_Conversion (Address, A_Name_Entry_T);
end Krn_Defs;
nblk1=17
nid=0
hdr6=2e
[0x00] rec0=28 rec1=00 rec2=01 rec3=07c
[0x01] rec0=13 rec1=00 rec2=02 rec3=00e
[0x02] rec0=15 rec1=00 rec2=03 rec3=070
[0x03] rec0=19 rec1=00 rec2=04 rec3=05c
[0x04] rec0=17 rec1=00 rec2=05 rec3=00e
[0x05] rec0=15 rec1=00 rec2=06 rec3=064
[0x06] rec0=19 rec1=00 rec2=07 rec3=01c
[0x07] rec0=14 rec1=00 rec2=08 rec3=044
[0x08] rec0=17 rec1=00 rec2=09 rec3=01a
[0x09] rec0=15 rec1=00 rec2=0a rec3=03a
[0x0a] rec0=15 rec1=00 rec2=0b rec3=032
[0x0b] rec0=14 rec1=00 rec2=0c rec3=06a
[0x0c] rec0=1a rec1=00 rec2=0d rec3=002
[0x0d] rec0=14 rec1=00 rec2=0e rec3=012
[0x0e] rec0=17 rec1=00 rec2=0f rec3=09c
[0x0f] rec0=1e rec1=00 rec2=10 rec3=016
[0x10] rec0=17 rec1=00 rec2=11 rec3=046
[0x11] rec0=16 rec1=00 rec2=12 rec3=054
[0x12] rec0=1a rec1=00 rec2=13 rec3=07a
[0x13] rec0=19 rec1=00 rec2=14 rec3=04a
[0x14] rec0=1b rec1=00 rec2=15 rec3=024
[0x15] rec0=21 rec1=00 rec2=16 rec3=00a
[0x16] rec0=16 rec1=00 rec2=17 rec3=000
tail 0x2175420be874f7bd1415b 0x42a00088462060003