DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T

⟦1ea361679⟧ TextFile

    Length: 45502 (0xb1be)
    Types: TextFile
    Names: »TCPLIB_C«

Derivation

└─⟦afbc8121e⟧ Bits:30000532 8mm tape, Rational 1000, MC68020_OS2000 7_2_2
    └─ ⟦77aa8350c⟧ »DATA« 
        └─⟦f794ecd1d⟧ 
            └─⟦this⟧ 

TextFile

/*****************************************************************************/
/*                                                                           */
/* TCP/IP interface between application and driver.                          */
/*                                                                           */
/* All calls to the TCP/IP driver are made trough routines in this file.     */
/* This file shall be linked with the application programs.                  */
/*                                                                           */
/* If switch ERR_REPORT is active the file TCPERR.C also must be linked with */
/* the application programs.                                                 */
/*                                                                           */
/* Application programs may also have to include MSOCKET.H                   */
/*                                                                           */
/* The function of each routine is described elsewhere in this file.         */
/*                                                                           */
/* Notes:                                                                    */
/*        'Port' in OS9 corresponds to 'Socket' in ADA.C                     */
/*                                                                           */
/* The parameter iocpara.timeout is passed to the driver. It specifies how   */
/* long the program shall wait for an interrupt response from the board.     */
/*                                                                           */
/*---------------------------------------------------------------------------*/
/* Programmer: Lars Engdahl Mikrotell. 87.06.30                              */
/* --------------------------------------------------------------------------*/
/* Entries:                                                                  */
/* --------                                                                  */
/* nopen                                                                     */
/* nsocket                                                                   */
/* nconnect                                                                  */
/* naccept                                                                   */
/* nread                                                                     */
/* nreread                                                                   */
/* nwrite                                                                    */
/* nioctl                                                                    */
/* nsocketaddr                                                               */
/*****************************************************************************/
/*\f

*/

#include "../INCL/msocket.h"               /*  get the structs shown below */

#define ERR_REPORT                         /* to get error report */
#define ERR_PRINT                          /* to get error printout */

int tcp_errno;    /* Error code, returned from libcalls below is placed here */
/*----------------------------------------------------------------------------*/
/* The FUNC_xxxxx defines below are also defined in TCPDRIVER.A  */
/* These codes are used as parameters to TCPDRIVER.A             */
#asm
FUNC_READ    equ  140
FUNC_WRITE   equ  141
FUNC_SOIOCTL equ  142
FUNC_SOCLOSE equ  143
FUNC_CLEANUP equ  160

ERR_DRV      equ  $EE00
#endasm

/*----------------------------------------------------------------------------*/
/*\f

*/
/*----------------------------------------------------------------------------*/
/*  struct sockaddr                              */
/*  {                                            */
/*    short  sin_family                          */
/*    Ushort sin_port                            */
/*    Ulong  sin_addr                            */
/*    char   sin_data[8]                         */
/*  }                                            */
/*----------------------------------------------------------------------------*/
/*  struct sockproto        not used in OS9      */
/*  {                                            */
/*    short sp_family                            */
/*    short sp_protocoll                         */
/*  }                                            */
/*----------------------------------------------------------------------------*/
/*
/* struct ioc_para                */     /* Used to pass parameters to driver */
/* {                      
/*   short              reply ;   */     /* must be first */
/*   int                type;     */     
/*   int                cmd;      */     
/*   int                sock_id ; */     
/*   char               *bufptr ; */     
/*   int                length ;  */     
/*   short              iamroot;  */     
/*   short              isaddr;   */     
/*   int                options;  */     
/*   struct sockaddr    asa;      */     
/*   int                timeout;  */     
/* };                             */
/*-------------------------------------------------------------------------*/

int device_id;

/*-------------------------------------------------------------------------*/

/*\f

*/
/*==========================================================================*/
/* NOPEN    Open device driver.                                             */
/*                                                                          */
/* Call:    dev_id = nopen()                                                */
/*                                                                          */
/* Purpose: Open device driver.                                             */
/*                                                                          */
/* Input:  ---                                                              */
/*                                                                          */
/* Output: dev_id = to be used on following calls to   nsocket, nsockaddr   */
/*                  naccept, nconnect, nread, nioctl, nwrite, nclose.       */
/*                                                                          */
/* Driver : ----                                                            */
/*                                                                          */
/* ERROR:  dev_id -1      errornumber in tcp_errno.                         */
/*--------------------------------------------------------------------------*/
/* Corresponding ADA procedure: none                                        */
/*==========================================================================*/

int nopen()
{
  int dev_id ;

#ifdef TRACE
    printf("TCPLIB:  nopen()\n");   
#endif


  dev_id = open("/tcpdev",3);

#ifdef ERR_PRINT
    if (dev_id==-1)
          printf("TCPLIB:  nopen()  *** ERROR. Can't open TCP device.\n");
#endif

#ifdef TRACE
  printf("TCPLIB:  nopen() done. dev_id =x%x\n", dev_id); 
#endif

  device_id = dev_id ;  /* used by intercept routine */
  init_intercept();

  return (dev_id) ;
}
/*--------------------------------------------------------------------------*/

/*\f

*/
/*===========================================================================*/
/* NSOCKET  create an end point for communication.                           */
/*                                                                           */
/* If the socket is to be used for acccept the specified portnumber must be  */
/* used by the connecting device. ( in struct asa )                          */
/*                                                                           */
/* Call: socket_id = nsocket(dev_id,type,asp,asa,options)                    */
/*                                                                           */
/* input: dev_id = process-path id. (returned from nopen)                    */
/*        type   = defines sematics for comm. Only SOCK_STREAM is supported. */
/*        *asp   = protocoll family. Must be a NULL  pointer.                */
/*        *asa   = Used to define a specific local port.                     */
/*                 This is the port the Remote will make a connect on.       */
/*                                                                           */
/*                 1. If *asa is a NULL pointer the EXOS board               */
/*                    will pick an available port.                           */
/*                    nsocketaddr() can be used to find out what port        */
/*                    value it picked.                                       */
/*                 2. If a specific port is desired:                         */
/*                    asa.sin_port   := Local_Port_Number;                   */
/*                    asa.sin_family := AF_INET;   (address family)          */
/*                                                                           */
/*      options =  SO_ACCEPTCONN must be used with sockets for accept        */
/*                                                                           */
/* output: socket_id to be used on following accept,connect,open,close requ  */
/*                                                                           */
/* Error:  sock_id = -1.   errornumber in tcp_errno.                         */
/*                                                                           */
/* Driver: xsoioctl in MEXSOCKET                                             */
/*---------------------------------------------------------------------------*/
/* Corresponding ADA procedure:                                              */
/* Procedure Open( Connection: out Transport.Connection_Id;                  */
/*                 Status:     out Transport_Defs.Status_Type;               */
/*                 Network:        Transport_Defs.Network_Name;              */
/*                 Local_Socket:   Transport_Defs.Socket_Id  );              */
/*                                                                           */
/* INPUT:  Network:       = "TCP/IP"                                         */
/*         Local_Socket: If Null then the system will pick one.              */
/* OUTPUT: Connection:   To be used in subsequent procedure calls.           */
/*         Status:       Error message.                                      */
/*===========================================================================*/
/*\f

*/
int nsocket(dev_id,type,asp,asa,options)

int dev_id;                                 /* returned from previuos mopen */
int type;                                   /* must be SOCK_STREAM          */
struct sockproto    *asp;                   /* must be a NULL pointer.      */
struct sockaddr     *asa;                   /*  */
int options;
{
  short  sock_id;
  struct ioc_para iocpara ;                 /* used to pass param to driver */

#ifdef TRACE
  printf("TCPLIB:  nsocket(). dev_id = x%x\n",dev_id);
#endif

      iocpara.cmd     = SOSOCKET;
      iocpara.type    = SOCK_STREAM;   /* ? or input param 'type' */
      iocpara.options = options;
      iocpara.iamroot = 1;             /* always considered privileged */
      iocpara.timeout = 2000 ;         /* timeout in ticks for board response */
 
      if (asa == (struct sockaddr *) 0 ) iocpara.isaddr = 0 ;
      else
      {
         iocpara.isaddr = 1 ;
         iocpara.asa.sin_family = asa->sin_family ;
         iocpara.asa.sin_port   = asa->sin_port ;
         iocpara.asa.sin_addr   = asa->sin_addr ;
      }
      mso_ioctl(dev_id,&iocpara)  ;
      tcp_errno = iocpara.reply ;

#ifdef TRACE
      printf("TCPLIB:  nsocket() done. sock_id =x%x. Reply = x%x \n",
      iocpara.sock_id,iocpara.reply);
#endif

      if (tcp_errno != 0 ) goto error;
      return iocpara.sock_id;

  error:
#ifdef ERR_REPORT
   print_error(tcp_errno,"nsocket().");
#else
#ifdef ERR_PRINT
  printf("TCPLIB:  *** ERROR in routine nsocket(): ErrCode = x%x\n",tcp_errno);
#endif   
#endif   
    
  return -1;
}
/*--------------------------------------------------------------------------*/

/*\f

*/
/*===========================================================================*/
/* NSOCKADDR get own address and port.                                       */
/*                                                                           */
/* If the socket is to be used for acccept the specified portnumber must be  */
/* known by the connecting device.                                           */
/*                                                                           */
/* Call: status = nsockaddr(dev_id,sock_id,asa)                              */
/*                                                                           */
/* input: dev_id = process-path id. (returned from nopen)                    */
/*        *asa   = ...Used to define a specific local port.                  */
/*                 This is the port the Remote will make a connect on.       */
/*                                                                           */
/* output: The result is the same result that a remote host would get from   */
/*         an naccept call if you connected to him.                          */ 
/*         asa.sin_port = Local port                                         */
/*         asa.sin_addr = Local Host address <<< addr does not work >>>      */
/*                                                                           */
/* Error:  sock_id = -1.   errornumber in tcp_errno.                         */
/*                                                                           */
/* Driver: xsoioctl in MEXSOCKET                                             */
/*---------------------------------------------------------------------------*/
/* Corresponding ADA procedures: Local_Host(...) , Local_Socket(....)        */
/*===========================================================================*/
/*\f

*/
int nsockaddr(dev_id,sock_id,asa)

int dev_id;                                 /* returned from previuos mopen */
int sock_id;
struct sockaddr     *asa;                   /*  */
{
  struct ioc_para iocpara ;                 /* used to pass param to driver */

#ifdef TRACE 
  printf("TCPLIB:  nsockaddr().\n");  
#endif

      iocpara.cmd     = SOSOCKETADDR;
      iocpara.sock_id = sock_id;
      iocpara.type    = SOCK_STREAM;   /* ? or input param 'type' */
      iocpara.timeout = 2000 ;         /* timeout in ticks for board response */
      iocpara.isaddr  = 1 ;         

      mso_ioctl(dev_id,&iocpara)  ;
      tcp_errno = iocpara.reply ;
      if (tcp_errno != 0 ) goto error;

      asa->sin_port = iocpara.asa.sin_port ;  /* driver placed Local port here*/
      asa->sin_addr = iocpara.asa.sin_addr ;  /* driver placed Local addr here*/

#ifdef TRACE
      printf("TCPLIB:  nsockaddr() done. addr =x%x. Port = x%x \n",
                                          asa->sin_addr,asa->sin_port);
#endif

      return 0;

  error:
#ifdef ERR_REPORT
   print_error(tcp_errno,"nsockaddr().");
#else
#ifdef ERR_PRINT   
  printf("TCPLIB:  *** ERROR in routine nsockaddr(): ErrCode= x%x\n",tcp_errno);
#endif  
#endif  
  return -1;
}
/*--------------------------------------------------------------------------*/
/*\f

*/
/*===========================================================================*/
/* NCONNECT  initiates a connection request.                                 */
/*                                                                           */
/* Call: status = nconnect(dev_id,sock_id,asa)                               */
/*                                                                           */
/* input: dev_id:  device id, returned from previus mopen()                  */
/*        sock_id: socket_id returned by previus socket() call.              */
/*        asa:     pointer to struct with Remote Host's address and port.    */
/*                 (address the remote is making an accept at()              */
/*                                                                           */
/*             asa.sin-family    = AF_INET                               */
/*             asa.sin-port      = Remote_Port_Number                    */
/*             asa.sin_addr      = Remote_Host_addr                      */
/*                                                                           */
/* output: 0 is returned when the conection is established.                  */
/*        -1 is returned if error.                                           */
/*                                                                           */
/* output:  rval = -1  -- error. (error number is placed in tcp_errno)       */
/*                                                                           */
/* Driver: xsoioctl in MEXSOCKET                                             */
/*---------------------------------------------------------------------------*/
/* Corresponding ADA procedure:                                              */
/*                                                                           */
/* Procedure Connect                         -- active connect               */
/*   (                                                                       */
/*     Connection   :     Transport.connection_Id;     -- returned from open */
/*     Status       : out Transport_Defs.Status_Type;                        */
/*     Remote_Host  :     Transport_Defs.Host_Id;      -- remote Host id.    */
/*     Remote_Socket:     Transport_Defs.Socket_Id;    -- remote socket id.  */
/*     Max_Wait     :     Duration := Duration'last;                         */
/*   );                                                                      */
/*                                                                           */
/*===========================================================================*/
/*\f

*/
nconnect(dev_id,sock_id,asa)

  int     dev_id;                           /* returned from previuos mopen */
  short  sock_id;
  struct sockaddr  *asa;
{
  struct ioc_para iocpara ;                 /* used to pass param to driver */

#ifdef TRACE
  printf("TCPLIB:  nconnect()\n");  
#endif

  iocpara.cmd        = SOCONNECT ;
  iocpara.timeout    = 4000 ;         /* timeout in ticks for board response */
  iocpara.type       = SOCK_STREAM;                 
  iocpara.sock_id    = sock_id ;
  iocpara.isaddr     = 1 ;                          

  iocpara.isaddr     = 1 ;
  iocpara.asa.sin_family = asa->sin_family ;
  iocpara.asa.sin_port   = asa->sin_port   ;
  iocpara.asa.sin_addr   = asa->sin_addr   ;

  mso_ioctl(dev_id,&iocpara) ;
  tcp_errno = iocpara.reply ;

#ifdef TRACE
   printf("TCPLIB:  nconnect() done. Reply =  x%x\n",iocpara.reply);
#endif

  if (tcp_errno != 0 ) goto error;
  return 0;

error:

#ifdef ERR_REPORT
   print_error(tcp_errno,"nconnect().");
#else
#ifdef ERR_PRINT   
  printf("TCPLIB:  *** ERROR in routine nconnect(): ErrCode = x%x\n",tcp_errno);
#endif
#endif

  return -1;
}
/*--------------------------------------------------------------------------*/
/*\f

*/
/*===========================================================================*/
/* NACCEPT provides the "listen end" of the protocoll handshake.             */
/*                                                                           */
/* Call: status = naccept(dev_id,sock_id,asa)                                */
/*                                                                           */
/* input: dev_id:  device id, returned from previus mopen()                  */
/*        sock_id: socket_id returned by previus socket() call.              */
/*        asa:     pointer to struct where connecting process' address and   */
/*                 portnumber is returned.                                   */
/*                                                                           */
/* output: if accept is successful: connecting process' address and portno   */
/*             asa.sin-port      = Remote_Port_Number                    */
/*             asa.sin_addr      = Remote_Host_addr                      */
/*                                                                           */
/*         0 is returned when the connection is established.                 */
/*        -1 error. (error number is placed in tcp_errno)?                   */
/*                                                                           */
/* Driver: xsoioctl in MEXSOCKET                                             */
/*---------------------------------------------------------------------------*/
/* Corresponding ADA procedure:  Procedure Connect(....)  -- passive connect */
/*===========================================================================*/
/*\f

*/
naccept(dev_id,sock_id,asa)

  int    dev_id;                          /* returned from previuos mopen */
  short  sock_id;
  struct sockaddr  *asa;
{
  struct ioc_para iocpara ;               /* used to pass param to driver */

#ifdef TRACE
    printf("TCPLIB:  naccept()\n");
#endif

  iocpara.cmd      = SOACCEPT ;
  iocpara.timeout  = 0000 ;            /* no timeout */
  iocpara.type     = SOCK_STREAM;      /* do I need this ???      */
  iocpara.isaddr   = 1 ;               /* do I need this ???      */
  iocpara.sock_id  = sock_id ;

  mso_ioctl(dev_id,&iocpara) ;
  tcp_errno = iocpara.reply;

  if (tcp_errno != 0 ) goto error;

  asa->sin_port = iocpara.asa.sin_port ;  /* driver placed Remote port here */
  asa->sin_addr = iocpara.asa.sin_addr ;  /* driver placed Remote addr here */

#ifdef TRACE
  printf("TCPLIB:  naccept() done. addr =x%x. Port = x%x \n",
                                          asa->sin_addr,asa->sin_port);
#endif

  return 0;

error:

#ifdef ERR_REPORT
   print_error(tcp_errno,"naccept().");
#else
#ifdef ERR_PRINT
  printf("TCPLIB:  *** ERROR in routine naccept(). ErrCode = x%x\n",tcp_errno);
#endif                                                              
#endif                                                              
  return -1;
}
/*--------------------------------------------------------------------------*/

/*\f

*/
/*===========================================================================*/
/* NIOCTL.                                                                   */
/*                                                                           */
/* Call:status = nioctl(dev_id,sock_id,func,para)                            */
/*                                                                           */
/* input: dev_id:   device id, returned from previus mopen()                 */
/*        sock_id:  socket_id returned by previus socket() call.             */
/*        ioctlcmd: Code for function to perform:                            */
/*        para:     pointer to in/out parameter.                             */
/*                                                                           */
/* output:  Depends on ioctlcmd: see below                                   */
/* ------------------------------------------------------------------------  */
/* FIONREAD: Returns a byte count (in parameter 'para') of data in the       */
/*           socket's receive buffer.                                        */
/*           The user can use this before a nread() to avoid waiting for data.*/
/* ------------------------------------------------------------------------  */
/* FIONBIO:  Enable/disable nonblocking IO                                   */
/*           input: *para = 1 - enable  nonblocking IO                       */
/*           input  *para = 0 - disable nonblocking IO                       */
/*           no output in *para.                                             */
/* ------------------------------------------------------------------------  */
/* other functions may work, (if they are made 'not comments').              */
/* belived to be supported in driver ?? but are not tested (yet).            */
/* ------------------------------------------------------------------------  */
/*                                                                           */
/* output = -1 = error. (error number is placed in tcp_errno)                */
/*                                                                           */
/* Driver: xsoioctl - xsocontrol in MEXSOCKET                                */
/*---------------------------------------------------------------------------*/
/* Corresponding ADA procedure:  ?????                                       */
/*===========================================================================*/
/*\f

*/

nioctl(dev_id,sock_id,func,para)

  int    dev_id;                         /* returned from previuos mopen */
  short  sock_id;
  short func;                            /* function code */ 
  int   *para;

{
  struct ioc_para iocpara ;              /* used to pass param to driver */

#ifdef TRACE
   printf("TCPLIB:  nioctl()\n");
#endif

  iocpara.cmd      = func     ;   /* = FIONREAD or FIONBIO ... ? */
  iocpara.timeout  = 2000 ;       /* timeout in ticks for board response */
  iocpara.sock_id  = sock_id  ;

  /* check if a valid (implemented) function request */ 

  switch(func)
  {                   
    case FIONREAD :               /* ret no of bytes in rec buffer */
/*  case SIOCGKEEP:   */
/*  case SIOCGLINGER: */
/*  case SIOCRCVOOB:  */
/*  case SIOCATMARK:  */
/*  case SIOCGPGRP:   */ 
                         break;   /* no input parameter tu functions above */

/*  case SIOCSENDOOB: */

    case FIONBIO:                 /* enable disable nonblocking IO*/
/*  case SIOCDONE:    */
/*  case SIOCSKEEP:   */
/*  case SIOCSLINGER: */
/*  case SIOCSPGRP:   */ 
                         iocpara.options  = *para ; break;

    default: tcp_errno = 0x5500 ; goto error;   /* err code to be def later???*/
  }

  mso_ioctl(dev_id,&iocpara) ;
  tcp_errno = iocpara.reply ;
  
#ifdef TRACE
   printf("TCPLIB:  nioctl() done. reply = x%x *para = %x\n",
                                               iocpara.reply,iocpara.options );
#endif

  if (tcp_errno != 0 ) goto error;

  /* ---- put result (if any) in *para ---- */

  switch(func)
  {                 
    case FIONREAD :                        /* ret no of bytes (int) in rec buf*/

/*  case SIOCGKEEP:   */ /* these returns a short */
/*  case SIOCGLINGER: */
/*  case SIOCATMARK:  */
/*  case SIOCGPGRP:   */ 

/*  case SIOCRCVOOB:  */ /* this returns a char */

                     *para = iocpara.options ;
                     break;
  }
  return 0;

error:

#ifdef ERR_REPORT
   print_error(tcp_errno,"nioctl().");
#else
#ifdef ERR_PRINT
  printf("TCPLIB:  *** ERROR in routine nioctl(). ErrCode = x%x\n",tcp_errno);
#endif                                                              
#endif                                                              

  return -1;
}
/*-------------------------------------------------------------------------*/


/*\f

*/
/*===========================================================================*/
/* interface for driver call from nsocket,nsockaddr, naccept, nconnect,nioctl*/
/* return 0 if OK, -1 if error. return data in struct ioc_para.              */
/*===========================================================================*/
#asm
mso_ioctl:
    MOVEM.L D1/A0,-(A7)
    MOVE.L  D1,A0                /* A0 = pntr to ioc_para structure    */
    MOVE.W  #FUNC_SOIOCTL,D1     /* D1 = funtion code passed to driver */
                                     /* D0 = parameter path to OS-9 call   */
    OS9 I$GetStt
    BCS.S   err_mso              /* error if carry set */
    MOVEM.L (A7)+,D1/A0
    RTS
*
err_mso MOVE.W  #ERR_DRV,(A0)        /* return error code in parptr-reply */
    MOVEM.L (A7)+,D1/A0
    RTS
#endasm
/*---------------------------------------------------------------------------*/
/*\f

*/
/*==========================================================================*/
/* NREAD                                                                    */
/*                                                                          */
/* Call:  no_of_bytes = nread(id,s_id,bufptr,buflen)                        */
/*        no_of_bytes = nreread(id,s_id,bufptr,buflen) << no timeout >>     */
/*                                                                          */
/* If the connection is still open but no message is in the queue, nread    */
/* wait for the message.                                                    */
/* If the remote host is disconnected, nread will return zero.              */
/* wait for the message.                                                    */
/* If bufflen < the maximum packet size (1024) and the message is > than    */
/* buflen, buflen bytes will be read and the rest of the packet will be lost.*/
/* Therefore allways use a readbuffer with size >= 1024.                    */
/*                                                                          */
/* Input:  dev_id   = device id. (returned from previus nopen)              */
/*         sock_id  = socket id. (returned from previus nsocket)            */
/*         r_length = max no of bytes.                                      */
/*         r_buff   = pointer to read buffer.                               */
/*                                                                          */
/* output:  no_of_bytes = -1  -- error. (errornumber is placed in tcp_errno)*/
/*          no_of_bytes  number of bytes read.                              */
/*                                                                          */
/* Driver: xsoread in MEXSOCKET                                             */
/*--------------------------------------------------------------------------*/
/* Corresponding ADA procedure:                                             */
/*                                                                          */
/* Procedure Receive                                                        */
/*   (                                                                      */
/*     Connection :     Transport.connection_Id;                            */
/*     Status     : out Transport_Defs.Status_Code;                         */
/*     Data       : out Byte_Defs.Byte_String;                              */
/*     Count      : out Natural;                                            */
/*     Max_Wait   :     Duration := Duration'last;                          */
/*   );                                                                     */
/*===========================================================================*/
/*\f

*/
int nread(dev_id,sock_id,r_buff,r_length)

int   dev_id;
int   sock_id;
int   r_length;
char *r_buff;

{
  struct ioc_para iocpara;
  int count;

#ifdef TRACE
  printf("TCPLIB:  nread()\n");
#endif

  iocpara.timeout   = 0000 ;         /* no timeout for board response */
  iocpara.sock_id   = sock_id ;
  iocpara.bufptr    = r_buff ;
  iocpara.length    = r_length ;

  read_call(dev_id,&iocpara) ;

  tcp_errno = iocpara.reply;
  
  if (tcp_errno != 0 ) goto error;

#ifdef TRACE
  printf("TCPLIB:  nread() done. reply = x%x count = %x\n",
                                               iocpara.reply,iocpara.length );
#endif

  return (iocpara.length) ;

error:

#ifdef ERR_REPORT
   print_error(tcp_errno,"nread().");
#else
#ifdef ERR_PRINT
  printf("TCPLIB:  *** ERROR in routine nread(). ErrCode = x%x\n",tcp_errno);
#endif
#endif                                                              

  return -1;
}
/*==========================================================================*/
/* <<<<< not tested >>>>>>                                                  */
/*--------------------------------------------------------------------------*/
int nreread(dev_id,sock_id,r_buff,r_length)
int   dev_id,sock_id,r_length;
char *r_buff;
{
  struct ioc_para iocpara;
  int count;

#ifdef TRACE
   printf("TCPLIB:  nreread()\n");
#endif

  iocpara.timeout  = 0000 ;         /* no timeout for board response */
  iocpara.sock_id  = sock_id ;
  iocpara.bufptr   = r_buff ;
  iocpara.length   = r_length ;

  read_call(dev_id,&iocpara) ;
  tcp_errno = iocpara.reply;
  
  if (tcp_errno != 0 ) goto error;

#ifdef TRACE
   printf("TCPLIB:  nreread() done. reply = x%x count = %x\n",
                                               iocpara.reply,iocpara.length );
#endif

  return (iocpara.length) ;

error:


#ifdef ERR_REPORT
   print_error(tcp_errno,"nreread().");
#else
#ifdef ERR_PRINT
  printf("TCPLIB:  *** ERROR in routine nreread(). ErrCode = x%x\n",tcp_errno);
#endif                                                              
#endif                                                              
  return -1;
}
/*--------------------------------------------------------------------------*/
/* interface for driver call from nread, nreread                            */
/* return 0 if OK, -1 if error. return data in struct ioc_para.             */
/*--------------------------------------------------------------------------*/
#asm
read_call:
    MOVEM.L D1/A0,-(A7)
    MOVE.L  D1,A0                /* A0 = pntr ioc_para structure */
    MOVE.W  #FUNC_READ,D1        /* D1 = funtion code passed to driver */
                                     /* D0 = parameter path to OS-9 call */
    OS9 I$GetStt
    BCS.S   err_rea              /* error if carry set */
    MOVEM.L (A7)+,D1/A0
    RTS

err_rea MOVE.W  #ERR_DRV,(A0)        /* return error code in parptr-reply */
    MOVEM.L (A7)+,D1/A0
    RTS
#endasm
/*---------------------------------------------------------------------------*/

/*\f

*/
/*==========================================================================*/
/* NWRITE                                                                   */
/*                                                                          */
/* input: id:       returned from previus mopen()                           */
/*        s_id:     socket_id returned by previus socket() call.            */
/*        s_buff:   pointer to the message.                                 */
/*        s_length: length of the message.                                  */
/*                                                                          */
/* output: 0 number of written bytes.                                       */
/*        -1  -- error. (errornumber is placed in tcp_errno)                */
/*                                                                          */
/* Driver: xsowrite in MEX_SOCKET                                           */
/*--------------------------------------------------------------------------*/
/* Corresponding ADA procedure:                                             */
/*                                                                          */
/* Procedure Transmit                                                       */
/*   (                                                                      */
/*     Connection   :     Transport.connection_Id;                          */
/*     Status       : out Transport_Defs.Status_Type;                       */
/*     Data         : out Byte_Defs.Byte_String;                            */
/*     Count        : out Natural;                                          */
/*     Max_Wait     :     Duration := Duration'last;                        */
/*     More         :     Boolean := False                                  */
/*   );                                                                     */
/*===========================================================================*/
/*\f

*/
int nwrite(dev_id,sock_id,s_buff,s_length)

int   dev_id,sock_id,s_length;
char  *s_buff;
{
  struct ioc_para iocpara;

#ifdef TRACE
  printf("TCPLIB:  nwrite()\n");
#endif

  iocpara.timeout   = 8000 ;         /* timeout in ticks for board response */
  iocpara.sock_id   = sock_id ;
  iocpara.bufptr    = s_buff ;
  iocpara.length    = s_length ;

  write_call(dev_id,&iocpara) ;

  tcp_errno = iocpara.reply;
  
  if (tcp_errno != 0 ) goto error;

#ifdef TRACE
  printf("TCPLIB:  nwrite() done. reply = x%x count = %x\n",
                                               iocpara.reply,iocpara.length );
#endif

  return (iocpara.length) ;

error:

#ifdef ERR_REPORT
   print_error(tcp_errno,"nwrite().");
#else
#ifdef ERR_PRINT
  printf("TCPLIB:  *** ERROR in routine nwrite(). ErrCode = x%x\n",tcp_errno);
#endif                                                              
#endif                                                              

  return -1;
}
/*--------------------------------------------------------------------------*/
/* interface for driver call from write                                     */
/* return 0 if OK, -1 if error. return data in struct ioc_para.             */
/*--------------------------------------------------------------------------*/

#asm
write_call:
    MOVEM.L D1/A0,-(A7)
    MOVE.L  D1,A0                /* A0 = pntr ioc_para structure */
    MOVE.W  #FUNC_WRITE,D1       /* D1 = funtion code passed to driver */
                                     /* D0 = parameter path to OS-9 call */
    OS9 I$GetStt
    BCS.S   err_wri              /* error if carry set */
    MOVEM.L (A7)+,D1/A0
    RTS

err_wri MOVE.W  #ERR_DRV,(A0)        /* return error code in parptr-reply */
    MOVEM.L (A7)+,D1/A0
    RTS
#endasm
/*---------------------------------------------------------------------------*/

/*\f

*/
/*==========================================================================*/
/* MSOCLOSE                                                                 */
/* dont close driver only socket.                                           */
/* input: dev_id:      returned from previus mopen()                        */
/*        sock_id:    socket_id returned by previus nsocket() call.         */
/*                                                                          */
/* output: 0  OK                                                            */
/*        -1  -- error. (errornumber is placed in tcp_errno)                */
/*                                                                          */
/* Driver: xsoclose in MEXSOCKET                                            */
/*--------------------------------------------------------------------------*/
/* Corresponding ADA procedure:                                             */
/* Procedure Disconnect ( Connection: Connection: Transport.Connection_Id );*/
/*===========================================================================*/
/*\f

*/
int nsoclose(dev_id,sock_id)
int dev_id,sock_id;
{
  struct ioc_para iocpara;

#ifdef TRACE
   printf("TCPLIB:  nsoclose()\n");
#endif

  iocpara.timeout   = 2000 ;         /* timeout in ticks for board response */
  iocpara.sock_id   = sock_id ;
  soclose_call(dev_id,&iocpara) ;

  tcp_errno = iocpara.reply;
  if (tcp_errno != 0 ) goto error;

#ifdef TRACE
  printf("TCPLIB:  nsoclose() done. status = x%x\n",iocpara.reply);
#endif

  return 0 ;

error:


#ifdef ERR_REPORT
   print_error(tcp_errno,"nsoclose().");
#else
#ifdef ERR_PRINT
  printf("TCPLIB:  *** ERROR in routine nsoclose(). ErrCode = x%x\n",tcp_errno);
#endif                                                              
#endif                                                              
  return(-1);
}
/*---------------------------------------------------------------------------*/
/* interface for driver call from soclose                                    */
/* return 0 if OK, -1 if error. return data in struct ioc_para.              */
/*---------------------------------------------------------------------------*/
#asm
soclose_call:
    MOVEM.L D1/A0,-(A7)
    MOVE.L  D1,A0                /* A0 = pntr ioc_para structure */
    MOVE.W  #FUNC_SOCLOSE,D1     /* D1 = funtion code passed to driver */
                                     /* D0 = parameter path to OS-9 call */
    OS9 I$GetStt
    BCS.S   err_scl              /* error if carry set */
    MOVEM.L (A7)+,D1/A0
    RTS

err_scl MOVE.W  #ERR_DRV,(A0)        /* return error code in parptr-reply */
    MOVEM.L (A7)+,D1/A0
    RTS
#endasm
/*---------------------------------------------------------------------------*/
/*\f

*/
/*==========================================================================*/
/*                                                                          */
/* rval = nclose(id,s_id)      perform an OS-9 close.                       */
/*                             if s_id >0 then also the socket is closed.   */
/*                                                        (see nsoclose)    */
/* Call:   rval = nclose(dev_id,sock_id)                                    */
/*                                                                          */
/* input: dev_id:  returned from previus mopen()                            */
/*        sock_id: socket_id returned by previus socket() call.             */
/*                 if =0 nsoclose is not called.                            */
/*                 if >0 a nsoclose is first performed.                     */
/* output: >=0 OK .                                                         */
/*         -1   if error                                                    */
/*                                                                          */
/* Driver:                                                                  */
/*--------------------------------------------------------------------------*/
/* Corresponding ADA procedure:                                             */
/* Procedure Close ( Connection: Transport.Connection_Id );                 */
/*===========================================================================*/

int nclose(dev_id,sock_id)
int dev_id;
short sock_id;
{
  int status ;

#ifdef TRACE
  printf("TCPLIB:  nclose()\n");
#endif
 
  if (sock_id >0 ) nsoclose(dev_id,sock_id);  /* no error handling ???? */
  status = close(dev_id);

#ifdef TRACE
  printf("TCPLIB:  nclose() done. status = x%x\n",status);
#endif

  return (status);
}
/*==========================================================================*/
/*\f

*/
/*===========================================================================*/
/* Whenever the process receives a signal this routine is executed.          */
/* (an exception is the S$Wake signal sent by the interrrupt routine).       */
/* control C -> signal code = 3                                              */
/* control E -> signal code = 2                                              */
/*===========================================================================*/

/* assembler routine t set up the intercept routine                          */

#asm
init_intercept:
    MOVEM.L A0,-(sp)
    LEA call_intercept(pc),A0
    OS9 F$Icpt
    MOVEM.L (sp)+,A0
    RTS

call_intercept:
    BSR tcp_intercept    /* entry intercept routine sigcode in D1.W */
    OS9 F$RTE
#endasm

/*===========================================================================*/

tcp_intercept(dummy,signalcode)

int dummy,signalcode;

{
    switch(signalcode & 0xffff)
    {
      case 2:  /* control E was pressed. Abort process. (after cleaning)*/
               /* first perform some cleaning up, then exit process.   */
#ifdef ERR_PRINT
               printf
      (">>>>>>>> Control E was pressed. Abort process. (after cleaning up.)\n");
#endif
               tcp_cleanup( getpid() );
               exit();

      case 3:  /* control C was pressed.                              */
               /* just return. If the driver was waiting for a board  */
               /* interrupt. Error code ERR_ABORT will be returned to */
               /* the caller which must do his own error handling.    */
#ifdef ERR_PRINT
               printf(">>>>>>>> Control C was pressed. Process interrupted.\n");
#endif
               break;

      default:
#ifdef ERR_PRINT
               printf("TCPLIB: tcp_intercept() signalcode = %x.\n",signalcode);
#endif
               exit();
    }
}
/*===========================================================================*/
/* This function will free resoures on the EXOS bord owned by the process    */
/* specified by the input parameter pid.                                     */
/*===========================================================================*/
tcp_cleanup(pid)
int pid ;
{
struct ioc_para iocpara;

iocpara.type = pid;

#ifdef ERR_PRINT
    printf("TCPLIB: tcp_cleanup() calling driver. Process id = x%x\n",pid);
#endif
    cleanup_call(device_id,&iocpara) ;

}
/*===========================================================================*/
/* interface for driver call from tcp_cleanup to xsocleanup in MEXSOCKET.C   */
/* return 0 if OK, -1 if error. return data in struct ioc_para.              */
/*===========================================================================*/
#asm
cleanup_call:
    MOVEM.L D1/A0,-(A7)
    MOVE.L  D1,A0                /* A0 = pntr to ioc_para structure    */
    MOVE.W  #FUNC_CLEANUP,D1     /* D1 = funtion code passed to driver */
                                     /* D0 = parameter path to OS-9 call   */
    OS9 I$GetStt
    BCS.S   err_cln              /* error if carry set */
    MOVEM.L (A7)+,D1/A0
    RTS
*
err_cln MOVE.W  #ERR_DRV,(A0)        /* return error code in parptr-reply */
    MOVEM.L (A7)+,D1/A0
    RTS
#endasm
/*===========================================================================*/