[comp.lang.ada] Ada, VADS 5.5h and Sun3 Frame Buffers

lewin@savax.UUCP (Stuart Lewin) (05/18/88)

Well, what started out as a simple programming project while fooling around
with Ada has become extremely frustrating and so I'm appealing for help to
all you Ada gurus out there in net-land. We have a program here called "dark"
which is used to clear a Sun workstation screen when you logoff. I want to
rewrite "dark" in Ada. It works by opening the framebuffer and then writing
directly to it in order to turn all the pixels off. My system configuration
consists of a monochrome frame buffer that is currently attached to a Sun3
running SunOS 3.5. The system is using the colorboard as the system console
(/dev/fb(?)). I'm using VADS 5.5h as my Ada environment.

Although dark obviously works, I also wrote another simple C program that
simply opens the frame buffer (/dev/bwtwo0), does a "valloc" in order to
get a matching array of unsigned chars and then does a mmap. I can then
write to the array directly and have it appear on the screen. So I'm fairly
confident that I can do what I want to do.

What follows is the Ada program that attempts to do the same, and the
C routine to open the device and mmap it. If I run it, however, mmap fails
with error EINVAL (appearing to fail since I get buffer addresses from the
Ada code that aren't aligned on a page boundary as required). I can print
out elements of the array from within the C code, so I would assume this
means that the right address is being passed. What appears to be failing is
the record representation spec for the frame buffer, in that the "at mod 8192"
is not placing it correctly.
I've tried all the record and (record) access types permutations that I can
think of and can't get this to work. From reading the VADS documentation, I
can't see anything that says this wouldn't work. Can anyone help me out with
this - am I trying to do something completely foreign to Ada or just making
a stupid mistake somewhere. Please reply to me directly...

Thanks In Advance,
Stu
...!decvax!savax!lewin

Disclaimer: My opinions are my own, and in no way reflect those of my
supervisor, or my supervisor's supervisor, ..., or anyone else at either
Sanders or Lockheed -- Whew, all that just to ask a question!

-------------------------------------------------------------------------------
--------------------
-----File: fb_test.a
--------------------
-------------------------------------------------------------------------------
with System;
with Text_IO;               use Text_IO;

procedure FB_Test is

  type MY_UNSIGNED_CHAR_TYPE is range 0 .. (2 ** 8) - 1;
  for  MY_UNSIGNED_CHAR_TYPE'SIZE use 8 * 1;

  type MY_INT_TYPE is range -(2 ** 32)/2 .. (2 ** 32)/2 - 1;
  for  MY_INT_TYPE'SIZE use 32 * 1;

  System_Page_Size  : constant MY_INT_TYPE 
                    := (8192 * 8) / System.Storage_Unit;
  Frame_Buffer_Size : constant MY_INT_TYPE 
                    := (131072 * 8) / System.Storage_Unit;

  type Frame_Buffer_Type is array(MY_INT_TYPE range <>) of MY_UNSIGNED_CHAR_TYPE;

  type Frame_Buffer_Record_Type is
    record
      Image : Frame_Buffer_Type(1 .. Frame_Buffer_Size);
  end record;

  for Frame_Buffer_Record_Type use
    record at mod System_Page_Size;
    Image at 0 range 0 .. (Frame_Buffer_Size*System.Storage_Unit - 1);
  end record;
  for Frame_Buffer_Record_Type'SIZE use Frame_Buffer_Size * 8;

  Frame_Buffer : Frame_Buffer_Record_Type;

  package My_Integer_IO is new Integer_IO(MY_INT_TYPE);
  use My_Integer_IO;

  ---------------------------------
  -- Unix/C Procedure Specification
  ---------------------------------
  procedure Unix_Frame_Buffer_Init(FB   : in System.Address;
                                   Size : in MY_INT_TYPE);

  pragma Interface(C, Unix_Frame_Buffer_Init, "_unix_frame_buffer_init");

begin

  -- store some values for debugging on the c side
  Frame_Buffer.Image(1) := 3;
  Frame_Buffer.Image(2) := 17;
  Frame_Buffer.Image(3) := 60;
  Frame_Buffer.Image(4) := 0;
  Frame_Buffer.Image(5) := 10;
  Frame_Buffer.Image(131067) := 5;
  Frame_Buffer.Image(131068) := 6;
  Frame_Buffer.Image(131069) := 7;
  Frame_Buffer.Image(131070) := 8;
  Frame_Buffer.Image(131071) := 9;
  Frame_Buffer.Image(131072) := 10;


  Put("Pagesize is "); Put(System_Page_Size); New_Line;
  Put("FrameBuffer size is "); Put(Frame_Buffer_Size); New_Line;
  Put("Record size is "); Put(Frame_Buffer.Image'SIZE / System.Storage_Unit);
    New_Line;

  -- open frame buffer and map it to physical device
  Unix_Frame_Buffer_Init(Frame_Buffer.Image'ADDRESS, Frame_Buffer_Size);

  -- now write to frame buffer and erase screen (on a sun 1 = OFF)
  for Index in Frame_Buffer.Image'FIRST .. Frame_Buffer.Image'LAST
  loop
    Frame_Buffer.Image(Index) := 16#ff#;
  end loop;

end FB_Test;

-------------------------------------------------------------------------------
-----------------------------------
-----File: unix_frame_buffer_init.c
-----------------------------------
-------------------------------------------------------------------------------
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/types.h>

#define DEBUG 1

extern int errno;

unix_frame_buffer_init(logical_address, length)
  char    *logical_address;
  int     length;
{
  int   prot;
  int   share;
  int   fd;
  off_t off;

  char      *pBuff;
  int       i;

#ifdef DEBUG
  printf("\nunix_frame_buffer_init:\n");
  printf("logical_address: %d\n", logical_address);
  printf("length         : %d\n", length);

  /*
   * print out the values at beginning & end to make sure address passed
   * correctly
  */
  for(i=0, pBuff=logical_address; i<5; i++, pBuff++)
    printf("%d(th) array element is: %d\n",i,*pBuff);
  for(i=length, pBuff=logical_address+length; i>length-5; i--)
    printf("%d(th) array element is: %d\n",i,*(--pBuff));
#endif

  /* open monochrome framebuffer */
  if((fd = open("/dev/bwtwo0", O_RDWR)) < 0) {
    printf("Error opening device; errno = %d\n", errno);
  }
  else {
    /* map it to user space */
    if (mmap(logical_address, length, PROT_READ | PROT_WRITE,
        MAP_SHARED, fd, 0) < 0) {
      printf("Error mapping device; errno = %d\n", errno);
    }
  }

}

----The End!!!