/* Packet.c - general, lo-level packet handling routines.
   Copyright (C) 1991, 1992, 1993 Kristian Nielsen.

   This file is part of XFH, the compressing file system handler.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            */

#include "CFS.h"

#include <stdarg.h>

/*
 * Send an already allocate packet, with given arguments, to a handler.
 * retport is the port that the packet should return to. This function will
 * NOT wait for the packet to return. numarg specifies how many arguments
 * follow after it (arguments will be treated as LONG).
 *
 * Use this function for doing async IO with DOS handlers.
 */
 
void putpkt(struct StandardPacket *pkt,struct MsgPort *procid,
           struct MsgPort *retport,LONG type,int numarg,...){
   va_list vl;
   LONG *p;
   
   /* Allow for variable number of parameters in a packet. */
   va_start(vl,numarg);
   
   /* Set up fields for packet handling. */
   pkt->sp_Msg.mn_Node.ln_Succ=pkt->sp_Msg.mn_Node.ln_Pred=NULL;
   pkt->sp_Msg.mn_Node.ln_Name=(char *)&pkt->sp_Pkt;
   pkt->sp_Msg.mn_Node.ln_Type=NT_MESSAGE;
   pkt->sp_Msg.mn_Node.ln_Pri=0;
   pkt->sp_Msg.mn_ReplyPort=NULL;
   pkt->sp_Msg.mn_Length=sizeof(*pkt);
   pkt->sp_Pkt.dp_Port=retport;
   pkt->sp_Pkt.dp_Link=&pkt->sp_Msg;

   /* Set up packet args. First the packet request type. */
   pkt->sp_Pkt.dp_Type=type;
   
   /* Handle each of the arguments in turn. */
   p=&pkt->sp_Pkt.dp_Arg1;
   while(numarg--){
      *p++=va_arg(vl,LONG);
   }
   
   /* And finally, set the packet off on its way to the handler. */
   PutMsg(procid,&pkt->sp_Msg);
   
   va_end(vl);
}


/*
 * Send an already allocated packet to an AmigaDOS handler using
 * supplied arguments, wait for the reply and return dp_Res1 & dp_Res2.
 *
 * Use this for doing syncronous IO just like dos.library, but using
 * a private message port.
 */

LONG dopkt(struct StandardPacket *pkt,struct MsgPort *procid,
           struct MsgPort *retport,LONG *res2,LONG type,int numarg,...){
   va_list vl;
   LONG *p;
   struct Message *msg;
   
   /* Set up fields for packet handling. */
   pkt->sp_Msg.mn_Node.ln_Succ=pkt->sp_Msg.mn_Node.ln_Pred=NULL;
   pkt->sp_Msg.mn_Node.ln_Name=(char *)&pkt->sp_Pkt;
   pkt->sp_Msg.mn_Node.ln_Type=NT_MESSAGE;
   pkt->sp_Msg.mn_Node.ln_Pri=0;
   pkt->sp_Msg.mn_ReplyPort=NULL;
   pkt->sp_Msg.mn_Length=sizeof(*pkt);
   pkt->sp_Pkt.dp_Port=retport;
   pkt->sp_Pkt.dp_Link=&pkt->sp_Msg;

   /* Set up packet args. First the packet request type. */
   pkt->sp_Pkt.dp_Type=type;
   
   /* Handle each of the arguments in turn. */
   /* Allow for variable number of parameters in a packet. */
   va_start(vl,numarg);   
   p=&pkt->sp_Pkt.dp_Arg1;
   while(numarg--){
      *p++=va_arg(vl,LONG);
   }
   va_end(vl);
   
   /* And finally, set the packet off on its way to the handler. */
   PutMsg(procid,&pkt->sp_Msg);
   
   /*
    * Wait for the reply. NOTE: Make SURE no other messages arrive first
    * at this port!
    */
   while(!(msg=GetMsg(retport))) WaitPort(retport);
   
   if(res2)  /* Allow for NULL 'don't care' pointer. */
      *res2=pkt->sp_Pkt.dp_Res2;
   return pkt->sp_Pkt.dp_Res1;
}

