|
|
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: 25600 (0x6400)
Types: Ada Source
Notes: 03_class, FILE, R1k_Segment, e3_tag, generic, package Enp_Driver, pragma Module_Name Module_Names.Vpid_For_Kernel 449, pragma Subsystem Kernel, seg_002fd7
└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000
└─⟦5a81ac88f⟧ »Space Info Vol 1«
└─⟦this⟧
with Module_Names;
with Processor_Manager;
with Substrate;
with System;
with Virt_Mem_Defs;
--
package Enp_Driver is
-- Primitives to access an ENP-100 series Ethernet controller in the IOP.
-- The ENP-100 is manufactured by Communication Machinery Corporation.
pragma Subsystem (Kernel, Private_Part => Closed);
pragma Module_Name (Module_Names.Vpid_For_Kernel, 449);
-- pragma Assert (449 = Kernel_Module_Names.Segment_for_Enp_Driver);
-- avoid compilation dependency on Kernel_Module_Names.
subtype Byte is System.Byte;
subtype Byte_String is System.Byte_String;
Null_Byte_String : constant Byte_String (1 .. 0) := (others => 0);
Forever : constant Duration := Duration'Last;
type Status_Type is (Ok, No_Hardware, Not_Configured, Already_Open,
Not_Open, Not_Registered, Too_Many_Clients, Timed_Out);
-- OK: operation succeeded.
-- No_Hardware: Enp_Driver.Installed = False.
-- Not_Configured: Configure has not been called since Reset.
-- Not_Open: Channel is not open.
-- Not_Registered: some task other than the caller is registered.
-- Too_Many_Clients: another task is executing the same operation.
-- Timed_Out: Max_Wait elapsed, and the operation was not performed.
procedure Reset (Status : out Status_Type);
-- Cause a hardware reset in the ENP controller board.
-- The immediate outcome is returned by Installed and
-- Driver_Version (below); in addition you should read
-- Startup.Control_Status to see if self-test succeeds.
-- A side-effect of Reset is to Close all open channels.
-- If another task is presently executing Reset, return
-- Status := Too_Many_Clients and do nothing.
function Installed return Boolean;
-- Return true iff the ENP hardware is installed in this machine,
-- and responded correctly to Reset.
function Driver_Version return Natural;
-- If Installed = True, return the version of the ENP driver
-- software that is presently running in the IOP; otherwise return
Null_Driver_Version : constant Natural := 0;
type Address is range 0 .. (2 ** 24) - 1;
-- These are linear byte addresses: Address'(0) denotes the first
-- byte of ENP RAM (controller memory), and consecutive values
-- denote consecutive ENP RAM bytes.
procedure Read (Status : out Status_Type;
First : Address;
Data : out Byte_String;
Count : out Natural);
-- Read Data from controller memory, starting at First.
-- Return Count = the number of bytes actually read.
-- If another task is presently executing Read, return
-- Status := Too_Many_Clients and do nothing.
procedure Write (Status : out Status_Type;
First : Address;
Data : Byte_String;
Count : out Natural);
-- Write Data into controller memory, starting at First.
-- Return Count = the number of bytes actually written.
-- If another other task executed Reset most recently,
-- or another task is presently excecuting Write, return
-- Status := Too_Many_Clients and do nothing.
-- If Read or Write fails entirely, return Count = 0.
-- Count may be less than Data'Length if there isn't
-- that much ENP RAM, or Data won't fit into a page.
type Channel_Number is range 0 .. 63;
procedure Configure (Status : out Status_Type;
Max_Channel : Channel_Number;
Byte_12 : Byte := 0; -- reserved
Max_Small_Buffers : Byte;
Max_Medium_Buffers : Byte;
Max_Large_Buffers : Byte;
Max_Wait : Duration := Forever);
-- Exchange a CONFIGURE command with the IOP.
-- Max_Channel is the largest Channel_Number that may be used for I/O.
-- Max_@_Buffers is the maximum number of @-sized buffers that may be
-- allocated to a single channel.
-- If another other task executed Reset most recently, or another task
-- is presently executing Configure, return Status := Too_Many_Clients.
-- Otherwise, write the correct value into SHARED.Hostbase, write zero
-- into SHARED.Enpbase, and interrupt the ENP. If any of this cannot
-- be done, return Status := Not_Configured. Wait for the ENP to pass
-- a WAKE_BFRTYPE (and interrupt) to the IOP. If Max_Wait elapses
-- first, call Reset and then return Status := Timed_Out. Otherwise,
-- return Status := OK; the caller must read Shared.Status to see if
-- the controller configuration succeeded, and if it did call
procedure Configured;
-- The controller has been successfully downloaded and configured.
-- Until the controller crashes or is Reset, allow Open/Put/Get/etc.
-- If another task executed Reset most recently, do nothing.
subtype Unique_Id is Integer;
Null_Unique_Id : constant Unique_Id := Unique_Id'First;
type Channel_Id is
record
Number : Channel_Number;
Unique : Unique_Id; -- to catch dangling (stale) Channel_Id's
end record;
Null_Channel_Id : constant Channel_Id :=
(Channel_Number'First, Null_Unique_Id);
procedure Open (Channel : Channel_Id;
Status : out Status_Type;
Type_Dependent_Bytes : Byte);
-- If Is_Open (Channel.Number) then return Status := Already_Open;
-- otherwise open Channel.
-- Subsequent buffers delivered from the controller via e_tohost
-- with b_type = BFRTYPE or TO_BFRTYPE will be returned from Get
-- with Type_Dependent_Bytes following the BFR part of the header;
-- Get.Header_Length will return 32 + Type_Dependent_Bytes for a
-- verbose input buffer, or Type_Dependent_Bytes for a terse buffer.
procedure Close (Channel : Channel_Id; Status : out Status_Type);
-- If Is_Open (Channel) then close it;
-- otherwise return Status := Not_Open.
procedure Put (Channel : Channel_Id;
Status : out Status_Type;
Header, Data : Byte_String;
Immediate : Boolean := False;
Max_Wait : Duration := Forever);
-- Pass one buffer, containing Header & Data, to the ENP controller.
-- Header & Data contain a BCH, space for protocol headers, and a BDB.
-- Data ordinarily contains the BDB, but this is NOT required: Header
-- and Data are catentated before splitting them into their parts.
-- If no buffer space is available, wait as long as Max_Wait for it.
-- Immediate => this buffer should be passed to the ENP immediately,
-- even if there is no buffer space available for non-Immediate buffers.
-- Use Immediate = True only if the buffer will be returned promptly:
-- an Immediate Put will block if there is another outstanding.
procedure Put (Channel : Channel_Id;
Status : out Status_Type;
B_Msglen : Natural;
B_Type : Byte; -- BFRTYPE or TO_BFRTYPE only
Header_Bytes : Byte;
Header, Data : Byte_String;
Max_Wait : Duration := Forever);
-- Pass one buffer, containing Header & Data, to the ENP controller.
-- Header & Data contain the type-dependent part of a BCH and a BDB,
-- but neither the type-independent BFR nor space for protocol headers.
-- Although less flexible, this form of Put uses less time and space.
-- It has the same effect as:
-- Put (Channel, Status,
-- Header & Data => BFR'(B_Device => Channel.Number,
-- B_Flags => 0,
-- B_Msglen => B_Msglen,
-- B_Type => B_Type)
-- & (Header & Data) (1..B_Type_Bytes)
-- & (1..Header_Bytes => <dont care>)
-- & (Header & Data) (B_Type_Bytes+1..Last),
-- Max_Wait => Max_Wait);
-- where B_Type_Bytes is a function of B_Type: 0 if B_Type=BFRTYPE,
-- or 16 if B_Type=TO_BFRTYPE. Other values of B_Type are not supported.
-- Data ordinarily contains the BDB, but this is NOT required: Header
-- and Data are catentated before splitting them into their parts.
procedure Get (Channel : Channel_Id;
Status : out Status_Type;
Header, Data : out Byte_String;
Header_Length, Data_Length : out Natural;
Fragment : Boolean := False;
Max_Wait : Duration := Forever);
-- Get (..., Preview => True, ...).
-- See the more general form of Get, below.
Get_Buffer_Ready : array (Channel_Number) of Boolean := (others => False);
-- Get_Buffer_Ready (C) = true iff at least one input buffer is buffered,
-- ready to be returned by Get. Use this as a hint: it may change before
-- you take action on it (call Get, for example).
procedure Register_To_Put (Channel : Channel_Id;
Client : Processor_Manager.Task_Id);
procedure Register_To_Get (Channel : Channel_Id;
Client : Processor_Manager.Task_Id);
procedure Un_Register_To_Put (Channel : Channel_Id);
procedure Un_Register_To_Get (Channel : Channel_Id);
function Channel (Number : Channel_Number) return Channel_Id;
-- Return a presently-open channel with the specified Number,
-- or Null_Channel_Id if there is no such channel open.
function Is_Open (Channel : Channel_Id) return Boolean;
-- Return true iff Channel is presently open.
-- Is_Open (Null_Channel_Id) = False.
function Is_Open (Number : Channel_Number) return Boolean;
-- Return Is_Open (Channel (Number));
generic
with procedure Put_Line (Data : String);
procedure Put_Trace (Entries : Natural := 16; Go_Back : Natural := 0);
-- Print out the most recent entries in the event trace. The event
-- trace contains a time sequence of various interesting events that
-- occur in the Enp_Driver task. It is useful mainly for debugging.
procedure Scavenge (Status : out Status_Type);
-- Un-wire surplus wired pages. Check for stuck channels.
-- This procedure should be called about once a minute,
-- so long as Status := OK.
package Machine_Time is
subtype Duration is Long_Integer;
function Convert (D : Duration) return Standard.Duration;
pragma Inline (Convert);
function Convert (D : Standard.Duration) return Duration;
pragma Inline (Convert);
function Time_Since_Ipl return Duration;
pragma Inline (Time_Since_Ipl);
type Deadline is private;
function Start (Time_To_Go : Standard.Duration) return Deadline;
function Time_To_Go (Timer : Deadline) return Standard.Duration;
function Expired (Timer : Deadline) return Boolean;
private
type Deadline is new Duration; -- the Time_Since_IPL of expiration
end Machine_Time;
pragma Integrate (Machine_Time);
type Iop_Address is new Long_Integer range 0 .. (2 ** 32) - 1;
-- These are the addresses used by the IOP 680x0 CPU.
type Iop_Quanta is (Bytes, Words, Longs);
-- The IOP can read and write data in any of these quanta.
-- Sometimes (depending on the IOP_Address) it matters.
Quantum_Length : constant array (Iop_Quanta) of Positive := (1, 2, 4);
-- The number of bytes in each quantum.
procedure Read (First : Iop_Address;
Data : out Byte_String;
Count : out Natural;
Quantum : Iop_Quanta := Bytes);
-- Read Data from IOP address space, starting at First.
-- Return Count = the number of bytes actually read.
procedure Write (First : Iop_Address;
Data : Byte_String;
Count : out Natural;
Quantum : Iop_Quanta := Bytes);
-- Write Data into IOP address space, starting at First.
-- Return Count = the number of bytes actually written.
-- If Read or Write fails entirely, return Count = 0.
-- Count may be less than Data'Length if Data'Length is
-- not a multiple of Quantum, or Data cannot fit into an
-- IOP command, or a nonexistent range of IOP_Addresses
-- is referenced.
package Iop_Defs is
package Filler is
subtype Filler is Long_Integer;
subtype Filler_1 is Filler range 0 .. 2 ** 1 - 1;
subtype Filler_2 is Filler range 0 .. 2 ** 2 - 1;
subtype Filler_4 is Filler range 0 .. 2 ** 4 - 1;
subtype Filler_5 is Filler range 0 .. 2 ** 5 - 1;
subtype Filler_7 is Filler range 0 .. 2 ** 7 - 1;
subtype Filler_8 is Filler range 0 .. 2 ** 8 - 1;
subtype Filler_16 is Filler range 0 .. 2 ** 16 - 1;
end Filler;
pragma Integrate (Filler);
type Unit_Number is new Filler.Filler_8;
package Enp_Defs is
type Command_Type is new Filler.Filler_7;
Reset : constant Command_Type := 0;
Write : constant Command_Type := 1;
Read : constant Command_Type := 2;
Configure : constant Command_Type := 3;
Input : constant Command_Type := 4;
Control : constant Command_Type := 5;
Immediate : constant Command_Type := 6;
Transmit : constant Command_Type := 7;
Cancel : constant Command_Type := 8;
type Enp_Command is
record
Unit : Unit_Number;
Hld : Boolean;
Command : Command_Type;
Byte_12 : System.Byte;
Byte_13 : System.Byte;
Byte_14 : System.Byte;
Byte_15 : System.Byte;
end record;
type Enp_Response is
record
Byte_13 : System.Byte;
Byte_14 : System.Byte;
Byte_15 : System.Byte;
end record;
-- Byte fields are numbered from byte 0 at the beginning of
-- the entire Sysbus header (not just the Control_Part).
end Enp_Defs;
pragma Integrate (Enp_Defs);
package Debug_Defs is
type Command is
record
Count : System.Byte;
Command : System.Byte;
Address : Iop_Address;
end record;
type Response is
record
Byte_13 : Filler.Filler_8;
Count : Filler.Filler_16;
end record;
end Debug_Defs;
pragma Integrate (Debug_Defs);
--------------------------------------------------------------
--
-- Control portion of R1000 --> IOP packet
--
---------------------------------------------------------------
type Device_Kind is (Nil, Dh11, Rh11, Ts11, If11, Exos, Enp, Debug);
type Sequence_Number is
new Natural range 0 .. Substrate.Max_Ioa_Buffers - 1;
type Virtual_Buffer_Number is new Natural range 0 .. 57;
Null_Virtual_Buffer_Number : constant Virtual_Buffer_Number := 0;
type Iop_Command (Slop_9_13 : Filler.Filler_4 := 0;
Device : Device_Kind := Nil) is
record
Slop_16_19 : Filler.Filler_4;
Queue_Position : Sequence_Number;
Slop_24_25 : Filler.Filler_2;
Map_Location : Virtual_Buffer_Number;
Slop_32_35 : Filler.Filler_4;
Command_Packet : Substrate.Packet_Id;
Is_Last_Part : Boolean;
Slop_41_44 : Filler.Filler_4;
Resume_Operation : Boolean;
Slop_46_46 : Filler.Filler_1;
Expects_Multi_Part_Response : Boolean;
case Device is
when Enp | Debug =>
Enp : Enp_Defs.Enp_Command;
-- when Debug =>
-- Debug : Debug_Defs.Command;
when others =>
null;
end case;
end record;
-- The UNIT, and device command are guaranteed to be the same
-- in all parts of the same command.
--------------------------------------------------------------
--
-- Control portion of IOP --> R1000 packet
--
---------------------------------------------------------------
type Iop_Response is
record
Slop_0_15 : Filler.Filler_16;
Slop_16_31 : Filler.Filler_16;
Slop_32_39 : Filler.Filler_8;
Is_Last_Part : Boolean;
Slop_41_45 : Filler.Filler_5;
Success : Boolean;
Slop_47 : Filler.Filler_1;
Slop_48_63 : Filler.Filler_16;
Slop_64_71 : Filler.Filler_8;
Enp : Enp_Defs.Enp_Response;
end record;
-- Assume that a request enables the IOP to send packets for parts
-- 0..n-1. The IOP may choose to send fewer than n packets back.
-- The R1000 knows how many packets are coming back because the last
-- one has IS_LAST_PART set. Thus, assuming IS_LAST_PART is set on
-- part i, the R1000 will get packets for 0..i, and no packets for
-- i+1..n-1. Also beware that the actual arrival order of packets is
-- unrelated to their logical ordering.
function To_Control_Part (Cmd : Iop_Command)
return Substrate.Control_Part;
function To_Iop_Response
(Control : Substrate.Control_Part) return Iop_Response;
-- Unchecked conversions.
end Iop_Defs;
pragma Integrate (Iop_Defs);
Bits_Per_Page : constant Natural := Virt_Mem_Defs.Bits_Per_Page;
Bytes_Per_Page : constant Natural := Bits_Per_Page / System.Byte'Size;
subtype Byte_Count is Natural range 0 .. Bytes_Per_Page;
type Trace_Element_Kind is
(Nil, Enp_Command, Enp_Response, Enp_Output_Signal);
type Trace_Element (Kind : Trace_Element_Kind := Nil) is
record
Timestamp : Machine_Time.Duration := 0;
Packet : Substrate.Packet_Id := Substrate.Nil_Packet_Id;
Data_Bytes : Byte_Count := 0;
case Kind is
when Enp_Command =>
Resume : Boolean;
Command : Iop_Defs.Enp_Defs.Enp_Command;
when Enp_Response =>
Dropsy : Boolean;
Success : Boolean;
Response : Iop_Defs.Enp_Defs.Enp_Response;
when Enp_Output_Signal =>
Channel : Iop_Defs.Filler.Filler_16;
-- Data_Bytes is Max_Bytes
when others =>
null;
end case;
end record;
type Trace_String is array (Natural range <>) of Trace_Element;
function Get_Trace (Entries : Natural := 16; Go_Back : Natural := 0)
return Trace_String;
-- Return the first Entries of the most recent (Entries + Go_Back).
-- The returned Trace_String'Length may be less than Entries
-- if fewer than Entries events have occurred since booting, or
-- if the trace buffer is shorter than (Entries).
procedure Put (Channel : Channel_Id;
Status : out Status_Type;
Bfr : out Iop_Address;
Header, Data : Byte_String;
Immediate : Boolean := False;
Max_Wait : Duration := Forever);
-- Store one buffer, containing Header & Data, in ENP RAM, but do NOT
-- pass it to the ENP. Return Bfr := the address where it was stored.
-- Header & Data contain a BCH, space for protocol headers, and a BDB.
-- Data ordinarily contains the BDB, but this is NOT required: Header
-- and Data are catentated before splitting them into their parts.
-- If no buffer space is available, wait as long as Max_Wait for it.
-- Immediate => allocate buffer space from the pool that is used for
-- buffers to be passed to the controller immediately.
-- Use Immediate = True only if the buffer will be returned promptly:
-- an Immediate Put will block if there is another outstanding.
procedure Get (Channel : Channel_Id;
Status : out Status_Type;
Header, Data : out Byte_String;
Header_Length, Data_Length : out Natural;
Preview : Boolean; -- := false
Fragment : Boolean := False;
Max_Wait : Duration := Forever);
-- Return the contents of one buffer received from the ENP.
-- If no buffer is waiting, wait as long as Max_Wait for one.
-- If Preview, do not drop the returned buffer from the queue;
-- a subsequent call to Get will return the same buffer again.
-- If a verbose INPUT response was received then
-- return the BCH to Header/Header_Length, and return the
-- BDB to Data/Data_Length. If the BCH is longer than
-- Header'Length, return Header_Length > Header'Length;
-- the excess bytes (not returned to Header) are lost.
-- If the BDB is longer than Data'Length then
-- return Data_Length > Data'Length.
-- If a terse INPUT response was received then
-- return the first Type_Dependent_Bytes (from Open)
-- of the data pages to Header/Header_Length; and
--- return the remaining bytes to Data/Data_Length.
-- If the number of remaining bytes > Data'Length then
-- return Data_Length > Data'Length.
-- If Data_Length > Data'Length then
-- If Fragment and
-- ((input was terse) or (input b_type = BFRTYPE or TO_BFRTYPE)) then
-- subsequent Get operations will return fragments to
-- Data with Header_Length = 0 and Data_Length = the
-- number of remaining bytes (including Data'Length),
-- until the last fragment is returned with
-- Header_Length = 0 and Data_Length <= Data'Length;
-- else
-- the excess bytes (not returned to Data) are lost.
end Enp_Driver;
nblk1=18
nid=0
hdr6=30
[0x00] rec0=1c rec1=00 rec2=01 rec3=006
[0x01] rec0=14 rec1=00 rec2=02 rec3=014
[0x02] rec0=16 rec1=00 rec2=03 rec3=006
[0x03] rec0=14 rec1=00 rec2=04 rec3=05c
[0x04] rec0=10 rec1=00 rec2=05 rec3=01c
[0x05] rec0=17 rec1=00 rec2=06 rec3=056
[0x06] rec0=12 rec1=00 rec2=07 rec3=054
[0x07] rec0=13 rec1=00 rec2=08 rec3=032
[0x08] rec0=13 rec1=00 rec2=09 rec3=03e
[0x09] rec0=15 rec1=00 rec2=0a rec3=018
[0x0a] rec0=19 rec1=00 rec2=0b rec3=04e
[0x0b] rec0=1c rec1=00 rec2=0c rec3=024
[0x0c] rec0=17 rec1=00 rec2=0d rec3=06e
[0x0d] rec0=18 rec1=00 rec2=0e rec3=01e
[0x0e] rec0=1e rec1=00 rec2=0f rec3=01e
[0x0f] rec0=1c rec1=00 rec2=10 rec3=016
[0x10] rec0=17 rec1=00 rec2=11 rec3=036
[0x11] rec0=18 rec1=00 rec2=12 rec3=084
[0x12] rec0=19 rec1=00 rec2=13 rec3=008
[0x13] rec0=18 rec1=00 rec2=14 rec3=034
[0x14] rec0=11 rec1=00 rec2=15 rec3=03e
[0x15] rec0=12 rec1=00 rec2=16 rec3=00c
[0x16] rec0=11 rec1=00 rec2=17 rec3=018
[0x17] rec0=06 rec1=00 rec2=18 rec3=000
tail 0x20f0012f2000806a63c27 0x42a00088462060003