From: mfb@mbunix.mitre.org (Michael F Brenner)
Subject: Re: DOS interrupts with GNAT 3.04
Date: 1996/12/24
Date: 1996-12-24T00:00:00+00:00 [thread overview]
Message-ID: <59p725$ff4@top.mitre.org> (raw)
In-Reply-To: 1996Dec23.124409.5432@news
Dos interrupts are done a little differently on several different compilers.
On Janus and Meridian they are provided. On Alsys only the interrupts which
did not pass an address were provided, otherwise you need access to assembly
code. On gnat the following code seems to work, and is subject to the Ada
modification to the Gnu GPPL which permits commercial companies to use it
but not change its free stataus:
with unsign;
package memory is
use unsign;
-- Memory:
--
-- Purpose:
-- Provide physical memory access
--
-- Architecture:
-- ADO (Abstract Data Object)
-- SDS (Semantically Dependent Specification)
--
-- History
-- 1986-09-17 added pragma inline (put) which cut the drawing time for
-- 1986-09-17 the SV PCX 2%, from 36 down to 35 seconds.
-- 1986-02-25 created
type addresses is new unsigned_32;
type byte_arrays is array (addresses range <>) of unsigned_8;
procedure put (address: addresses; data: in unsigned_8);
procedure put (address: addresses; data: in unsigned_16);
procedure put (address: addresses; data: in unsigned_32);
procedure put (address: addresses; data: in byte_arrays);
procedure put (address: addresses; data: in string);
procedure get (address: addresses; data: out unsigned_8);
procedure get (address: addresses; data: out unsigned_16);
procedure get (address: addresses; data: out unsigned_32);
procedure get (address: addresses; length: addresses; data: out byte_arrays);
function get (address: addresses) return unsigned_8;
function get (address: addresses) return unsigned_16;
function get (address: addresses) return unsigned_32;
function get (address: addresses; length: addresses)
return byte_arrays;
function get (address: addresses; length: addresses)
return string;
pragma inline (put);
end memory;
with unsign;
package dos16bit is
-- These objects and methods are common to all 16-bit and and 32-bit DOSs.
-- They comprise all DOS calls that do not pass addresses or 32-bit lengths.
-- DOS16bit is complemented by dos_utils which differs for each compiler.
--
-- Warning: DOS and Unix are not thread-safe for memory allocation, I/O, etc.
-- Warning: DOS blocks on all I/O, Unix blocks on most I/O.
-- Warning: DOS is not even re-entrant, as some Unixen are
procedure init; -- not to be used by Alsys to avoid random reboots
-- DOS SYSTEM CALLS
DOS_interrupt: constant := 16#21#;
type interrupts is range 0..255;
for interrupts'size use 8;
subtype register_data is unsign.unsigned_16;
type registers_16 is record
-- Half of the 16-bit and 32-bit DOS calls (those that do not pass
-- addresses or 32-bit lengths) can use the simplified registers
-- (registers_16) to do their work. These DOS calls are identical
-- across 16- and 32-bit systems.
ax, bx, cx, dx, flags: register_data := 0;
end record;
procedure interrupt_16 (interrupt: interrupts;
register: in out registers_16);
-- flags is used in many DOS calls as an error indicator:
-- flags bit 0: carry
-- flags bit 2: parity
-- flags bit 6: zero
-- flags bit 7: sign
type dos_error_numbers is range -2**15..2**15-1;
function command_line return string; -- not to be used by Alsys
function error return dos_error_numbers;
function error_interpretation return string;
end dos16bit;
with dos_utils;
with memory;
package body dos16bit is
-- compiler_this_package_is_dependent_on: constant string := "any DOS";
-- GLOBAL VARIABLES
cmd_line: string (1..255);
cmd_line_length: integer := 0;
initialized: boolean:=False;
x: constant string (1..2):=ascii.nul & '$';
interrupt_62_failed: exception;
why_are_you_calling_dos16bit_Instead_Of_os_command_Line: exception;
function odd (number: register_data) return boolean is
use unsign;
begin
return (number and 1) = 1;
end odd;
-- INTERRUPTS
procedure get_original_command_line is
-- WARNING: not to be called by Alsys
-- WARNING: not to be called twice
use memory;
use unsign;
DOS_get_psp: constant := 16#6200#;
sixteen: constant := 16#10#;
offset_to_length: constant := 16#80#;
reg: dos16bit.registers_16;
psp: memory.addresses;
length: unsigned_8;
byte: unsigned_8;
char: character;
j: natural := 1;
begin
if initialized then
raise interrupt_62_failed;
end if;
reg.ax := DOS_get_PSP;
dos16bit.interrupt_16 (16#21#, reg);
if (reg.flags and 1)=1 then
raise interrupt_62_failed;
end if;
psp := addresses (reg.bx) * sixteen;
length := memory.get (psp + offset_to_length);
cmd_line_length := natural(length);
for i in 1 .. cmd_line_length loop
byte := memory.get (psp+offset_to_length+addresses(i));
char := character'val (byte);
cmd_line (i) := char;
end loop;
loop
exit when j > cmd_line_length;
exit when cmd_line(j) /= ' ';
j:=j+1;
end loop;
if j>1 then
for i in j..cmd_line_length loop
cmd_line (i+1-j) := cmd_line (i);
end loop;
cmd_line_length := cmd_line_length+1-j;
end if;
end get_original_command_line;
function command_line return string is
begin
if not initialized then
raise why_are_you_calling_dos16bit_Instead_Of_os_command_Line;
end if;
return cmd_line (1..cmd_line_length);
end command_line;
function error return dos_error_numbers is
reg: registers_16;
dos_get_error: constant := 16#5900#;
begin
reg.ax := dos_get_error;
reg.bx := 0;
interrupt_16 (interrupt => DOS_interrupt, register => reg);
return dos_error_numbers (reg.ax);
end error;
function error_interpretation return string is
bh, bl, ch: register_data;
reg: registers_16;
type classes is (non_recognized_error,
non_available_resource, busy_network,
wrong_password, dos_failure,
hardware_failure, bad_dos_system_file,
programmer_inserted_bug, missing_object,
wrong_control_block, locked_item,
bad_spot_on_media, duplicate_file,
surprize);
type locuses is (plenum,
computer_somewhere, block_device_driver,
network, character_device_driver,
memory, new_dos_feature);
type errors is (no_error,
bad_function, file_not_found, path_not_found,
file_too_many, denied_access, bad_handle,
memory_overwrite, lack_of_memory, bad_address,
bad_environment, bad_format, datum_bad,
bad_drive, delete_current_dir, dissimilar_device,
file_no_more, write_protect, unit_unknown,
drive_not_ready, command_unknown, data_CRC_error,
bad_length, seek_error, medium_unknown,
sector_not_found, printer_outa_paper, write_fault,
read_fault, general_failure, sharing_violation,
lock_violation, sudden_disk_change,
hard_to_describe_file_error);
type actions is (take_no_action,
retry_now, retry_after_a_delay,
fix_the_incorrect_name, terminate_after_cleanup,
abort_without_cleanup, ignore_and_investigate_later,
make_it_available_now, call_a_hacker);
dos_get_error: constant := 16#5900#;
begin
reg.ax := dos_get_error;
reg.bx := 0;
interrupt_16 (interrupt => DOS_interrupt, register => reg);
if natural (reg.ax)=0 then
return ""; --No error to interpret
end if;
if natural (reg.ax) > errors'pos(errors'last) then
reg.ax := errors'pos(errors'last);
end if;
bh := register_data (natural (reg.bx) / 256);
if natural (bh) > natural (classes'pos(classes'last)) then
bh := classes'pos(classes'last);
end if;
bl := register_data (natural (reg.bx) mod 256);
if natural (bl) > actions'pos(actions'last) then
bl := actions'pos(actions'last);
end if;
ch := register_data (natural (reg.cx) / 256);
if natural (ch)>locuses'pos(locuses'last) then
ch := locuses'pos(locuses'last);
end if;
return ascii.cr & ascii.lf &
"Error " &
register_data'image(reg.ax) &
" occurred because a " &
classes'image(classes'val(bh)) &
" in the " &
locuses'image (locuses'val (ch)) &
ascii.cr & ascii.lf &
" had a " &
errors'image (errors'val (reg.ax)) &
". Your best hope is to " &
actions'image (actions'val (bl)) &
ascii.cr & ascii.lf;
end error_interpretation;
procedure interrupt_16 (interrupt: interrupts;
register: in out registers_16) is
begin
dos_utils.interrupt_16 (interrupt, register);
end interrupt_16;
-- SYSTEM CALLS
procedure init is
begin
if not initialized then
get_original_command_line;
end if;
initialized:=True;
end init;
end dos16bit;
with dos16bit;
with system;
package DOS_utils is
-- DOS_utils: Gnat Version
--
-- Purpose:
-- Provide interface to 80x86 software interrupts
--
-- Architecture:
-- ADO (Abstract Data Object)
-- SIS (Semantically Dependent Specification)
subtype interrupts is dos16bit.interrupts;
procedure interrupt_16 (interrupt: interrupts;
register: in out dos16bit.registers_16);
type register_data is mod 2**32;
type short_register_data is mod 2**16;
type flag_data is mod 2**8;
type registers is record
di, si, bp, cflag, bx, dx, cx, ax: register_data := 0;
flags: flag_data := 0;
end record; -- This register order is for gnat3.05 (djgpp 2.0)
procedure interrupt (interrupt: interrupts; register: in out registers);
end DOS_utils;
with System.Storage_Elements;
package body DOS_utils is
-- compiler_this_package_is_dependent_on: constant string := "gnat3";
procedure os_interrupt (interrupt: interrupts;
register: system.address;
results: system.address);
pragma Import (C, os_interrupt, "int86");
procedure interrupt_16 (interrupt: interrupts;
register: in out dos16bit.registers_16) is
reg: registers;
begin
reg.ax := register_data (register.ax);
reg.bx := register_data (register.bx);
reg.cx := register_data (register.cx);
reg.dx := register_data (register.dx);
os_interrupt (interrupt, reg'address, reg'address);
register.ax := dos16bit.register_data (reg.ax);
register.bx := dos16bit.register_data (reg.bx);
register.cx := dos16bit.register_data (reg.cx);
register.dx := dos16bit.register_data (reg.dx);
register.flags := dos16bit.register_data (reg.flags);
end interrupt_16;
procedure interrupt (interrupt: interrupts; register: in out registers) is
begin
os_interrupt (interrupt, register'address, register'address);
end interrupt;
end DOS_utils;
next prev parent reply other threads:[~1996-12-24 0:00 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
1996-12-21 0:00 DOS interrupts with GNAT 3.04 Rich Maggio
1996-12-23 0:00 ` Gautier
1996-12-24 0:00 ` Robert Dewar
1996-12-25 0:00 ` Jerry van Dijk
1996-12-25 0:00 ` Robert Dewar
1996-12-25 0:00 ` Robert Dewar
1996-12-24 0:00 ` Michael F Brenner [this message]
1996-12-25 0:00 ` Jerry van Dijk
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox