[comp.sys.amiga.tech] Asynchronous I/O, Packet Interface

duncant@mbunix.mitre.org (Thomson) (11/27/90)

I'm looking for some help in how to do asynchronous I/O using the AmigaDOS
packet interface.  I can't get it to work, even for the most simple case,
and I'm sure that I'm not making a programming goof.  I think that my 
problem is that I'm working from an "AmigaDOS Technical Reference Manual"
that applies to AmigaDOS 1.0.  I assumed that later releases were all
backward compatible, so that if I coded in accordance with this manual,
my code would work, but apparantly this is not the case.  Can someone who
owns a more recent version of the documentation, or, even better, someone
who knows from experience how this stuff is supposed to work, give me a
hand here?  I'd really appreciate it, as I'm totally stumped and have no
way to debug any further.  BTW, the Autodocs don't provide any help in
this area, since they only cover function calls, not services obtained
by sending packets to a handler, as is the case here.

What I'm trying to do is send an AmigaDOS packet to a file system handler,
requesting a Read on a file, which has already been opened by calling
Open().  

1) Is the following the correct way to set up the arguments
   of the packet structure?

   std_pkt->sp_Pkt.dp_Type = ACTION_READ;
   std_pkt->sp_Pkt.dp_Arg1 = (LONG) in_hdl;   /* BPTR to file handle */
   std_pkt->sp_Pkt.dp_Arg2 = (LONG) storage;  /* Normal C pointer to storage */
   std_pkt->sp_Pkt.dp_Arg3 = size;				 /* Number of bytes to read */

   Here, std_pkt is a pointer to a StandardPacket structure.

2) The StandardPacket structure contains a Message structure and a DosPacket
   structure.  Is the following the correct way to initialize these
   structures?

   /* Initialize the Message structure within the StandardPacket structure */
   std_pkt->sp_Msg.mn_Node.ln_Name = (char *) &(std_pkt->sp_Pkt);
   std_pkt->sp_Msg.mn_Node.ln_Type = NT_MESSAGE;
   std_pkt->sp_Msg.mn_ReplyPort    = reply_port;
   std_pkt->sp_Msg.mn_Length       = sizeof( struct DosPacket );

   /* Initialize the DosPacket structure within the StandardPacket structure */
   std_pkt->sp_Pkt.dp_Link         = &(std_pkt->sp_Msg);
   std_pkt->sp_Pkt.dp_Port         = reply_port;

   Here, reply_port is a pointer to a MsgPort structure, which has been
   created with a call to CreatePort.

3) If the answer to 1) and 2) is "Yes", then why, oh why, does my program
   bring up Mr. Guru?  The complete code follows.  


Any help that could be offered would REALLY be appreciated.  Perhaps someone
from Commodore that works on AmigaDOS?????  This is something I asked about
on the net many months ago.  Nobody was able to offer any help then, but 
I've since dug the program out and I'd really like to get it working.  

Duncan Thomson 
(duncant@mbunix.mitre.org)




-----------------------------code follows--------------------------------------



/******************************************************************************
*
*  TESTIO.C
*
*	Tests ASYNCHRONOUS I/O using the AmigaDOS packet interface.
*
*	Run the program giving the name of a file.  A single read
*	operation will be attempted on the file.  
*
*  Bugs: Program doesn't work.  I wish I knew why!
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <exec/types.h>
#include <exec/exec.h>
#include <libraries/dosextens.h>
#include <proto/all.h>

main( argc, argv )
int argc;
char *argv[];
{
   BPTR in_hdl;
   struct FileHandle *hptr;
   struct MsgPort *handler_proc;
   struct MsgPort *reply_port;
   struct StandardPacket *std_pkt;
   char *storage; 
   
   /* Check for correct program invocation */
   if( argc!=2 ) {
      printf( "Usage: %s infile_name\n", argv[0] );
      exit( 10 );
   }
   
   /* Open input file */
   in_hdl = Open( argv[1], MODE_OLDFILE );
   if( in_hdl == NULL ) puke_and_die( "Can't open input file" );

   /* Get the handler process ID from the file handle */
   hptr = (struct FileHandle *) BADDR( in_hdl );
   handler_proc = (struct MsgPort *) (hptr->fh_Type);
   printf( "Handler proc id (from file handle) is: 0x%lx\n", handler_proc );
   
   /* Just to check, get the process ID another way */
   handler_proc = DeviceProc( argv[1] );
   printf( "Handler proc id (from DeviceProc) is: 0x%lx\n", handler_proc );

   /* Allocate storage area */
   storage = malloc( 1024 );
   if( storage==NULL ) puke_and_die( "No memory for storage" );
   printf( "Storage ptr is: 0x%lx\n", storage );
   
   /* Create a reply port */   
   reply_port = CreatePort( NULL, 0 );
   if( reply_port==NULL ) puke_and_die( "Can't make a reply port" );

   /* Set up standard packet */
   std_pkt = (struct StandardPacket *) AllocMem( 
                (long) sizeof(struct StandardPacket),
                MEMF_PUBLIC | MEMF_CLEAR
   );
   if( std_pkt==NULL ) puke_and_die( "Can't make a std packet" );
   std_pkt->sp_Msg.mn_Node.ln_Name = (char *) &(std_pkt->sp_Pkt);
   std_pkt->sp_Msg.mn_Node.ln_Type = NT_MESSAGE;
   std_pkt->sp_Msg.mn_ReplyPort = reply_port;
   std_pkt->sp_Msg.mn_Length = sizeof( struct DosPacket );
   std_pkt->sp_Pkt.dp_Link = &(std_pkt->sp_Msg);
   std_pkt->sp_Pkt.dp_Port = reply_port;

   /* Set up packet arguments to read from file into buffer */
   std_pkt->sp_Pkt.dp_Arg1 = (LONG) in_hdl;
   std_pkt->sp_Pkt.dp_Type = ACTION_READ;
   std_pkt->sp_Pkt.dp_Arg2 = (LONG) storage;
   std_pkt->sp_Pkt.dp_Arg3 = 1;

   /* Now send the packet to the message port of the handler */
   PutMsg( handler_proc, &(std_pkt->sp_Msg) );

printf( "Sent the message.  Hit CR..." ); getchar();

   /******** PROGRAM DIES ABOUT HERE ****************/
  
   /* Wait for the reply and tae reply port */
   WaitPort( reply_port );
   GetMsg( reply_port );
   
   printf( "Got the reply.  Hit CR..." ); getchar();

   /* Clean up */
   free( std_pkt );
   DeletePort( reply_port );
   free( storage );
   Close( in_hdl );
   
} /* end main */

/* ------------- */
puke_and_die( str )
char *str;
{
   printf( "YEUCH GLEARCH URRRGH: %s\n", str );
   printf( "You better reboot - I didn't clean up my mess!\n" );
   exit( 10 );
}
/* ---------- end of file ---------- */

--
(Please excuse the typos and garbage caused by line noise.)

jesup@cbmvax.commodore.com (Randell Jesup) (12/19/90)

In article <126865@linus.mitre.org> duncant@mbunix.mitre.org (Thomson) writes:
>1) Is the following the correct way to set up the arguments
>   of the packet structure?
>
>   std_pkt->sp_Pkt.dp_Type = ACTION_READ;
>   std_pkt->sp_Pkt.dp_Arg1 = (LONG) in_hdl;   /* BPTR to file handle */
>   std_pkt->sp_Pkt.dp_Arg2 = (LONG) storage;  /* Normal C pointer to storage */
>   std_pkt->sp_Pkt.dp_Arg3 = size;		/* Number of bytes to read */

	Whoops!  dp_Arg1 for read should be fh->fh_Arg1, not fh!

>2) The StandardPacket structure contains a Message structure and a DosPacket
>   structure.  Is the following the correct way to initialize these
>   structures?
>
>   /* Initialize the Message structure within the StandardPacket structure */
>   std_pkt->sp_Msg.mn_Node.ln_Name = (char *) &(std_pkt->sp_Pkt);
>   std_pkt->sp_Msg.mn_Node.ln_Type = NT_MESSAGE;
>   std_pkt->sp_Msg.mn_ReplyPort    = reply_port;
>   std_pkt->sp_Msg.mn_Length       = sizeof( struct DosPacket );

	OK.  Strictly speaking, the NT_MESSAGE and sizeof(struct DosPacket)
aren't needed (actually replyport isn't either).

>   /* Initialize the DosPacket structure within the StandardPacket structure */
>   std_pkt->sp_Pkt.dp_Link         = &(std_pkt->sp_Msg);
>   std_pkt->sp_Pkt.dp_Port         = reply_port;

	Fine.

>Any help that could be offered would REALLY be appreciated.  Perhaps someone
>from Commodore that works on AmigaDOS?????  This is something I asked about
>on the net many months ago.  Nobody was able to offer any help then, but 
>I've since dug the program out and I'd really like to get it working.  

	Sorry this reply took so long, I get way behind on the nets at times.
Information overload.

>   /* Wait for the reply and tae reply port */
>   WaitPort( reply_port );
>   GetMsg( reply_port );

	You should really make sure you got a message back...

-- 
Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com  BIX: rjesup  
The compiler runs
Like a swift-flowing river
I wait in silence.  (From "The Zen of Programming")  ;-)

glmwc@marlin.jcu.edu.au (Matt Crowd) (12/19/90)

In article <16649@cbmvax.commodore.com> jesup@cbmvax.commodore.com (Randell Jesup) writes:
>In article <126865@linus.mitre.org> duncant@mbunix.mitre.org (Thomson) writes:
>>   /* Initialize the Message structure within the StandardPacket structure */
>>   std_pkt->sp_Msg.mn_Node.ln_Name = (char *) &(std_pkt->sp_Pkt);
>>   std_pkt->sp_Msg.mn_Node.ln_Type = NT_MESSAGE;
>>   std_pkt->sp_Msg.mn_ReplyPort    = reply_port;
>>   std_pkt->sp_Msg.mn_Length       = sizeof( struct DosPacket );
>
>	OK.  Strictly speaking, the NT_MESSAGE and sizeof(struct DosPacket)
                                                   ^^^^^^^^^^^^^^^^^^^^^^
>aren't needed (actually replyport isn't either).

Does this imply we are never going to get memory protection!
I think so.  Please guys, don't give up yet.  There is still time
to convince people to say how long their messages are, and not to
use pointers in them!  

>Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
[nice .sig deleted]

nb.  I have never done any message port programming between tasks, so
I'm no real expert, just read the book once.


-- 
Matt Crowd       Amiga Man
Email Address    glmwc@marlin.jcu.edu.au