/* SerialIO.c */

#include <exec/types.h>
#include <exec/memory.h>
#include <stdio.h>
#include <devices/serial.h>
#include <functions.h>

/* Default starting values */
#define STARTBAUD 300  /* default baud rate */
#define SERFLAGS    (SERF_SHARED | SERF_XDISABLED)
#define CTLCHAR     0x11130501    

int Mode = 0;

/* declarations for the serial stuff */
static struct IOExtSer *Read_Request = NULL;
static UBYTE rs_in[2];
static struct IOExtSer *Write_Request = NULL;
static UBYTE rs_out[2];

/* stack to save Serial Port flags */
#define MAXSTACK 10


/*------------------------------------------------------------*/
/*  GetSerialSigBit: return Read_Request's Signal Bit	      */
/*------------------------------------------------------------*/
/*
int GetSerialSigBit()
{
   return Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit;
}
*/
/*------------------------------------------------------------*/
/*  CheckSerIO : return TRUE if serial port has a character   */
/*------------------------------------------------------------*/

BOOL CheckSerIO()
{
   return (BOOL)( CheckIO( Read_Request ) != NULL);
}

/*------------------------------------------------------------*/
/* 	 FlushSerIO: Flush the receive buffer		      */
/*------------------------------------------------------------*/

void FlushSerIO()
{
register struct IOExtSer *r = Read_Request;

	if(CheckIO( r ) == FALSE) {          /* if IO pending */
		AbortIO( r );                 /* abort it */
		}
	WaitIO( r );

	r->IOSer.io_Command = CMD_FLUSH;
	DoIO( r );                         /* flush all IO requests */
	r->IOSer.io_Command = CMD_CLEAR;
	DoIO( r);                          /* flush receive buffer  */
}

void RestartSerIO()
{
   register struct IOExtSer *r = Read_Request;
   Read_Request->IOSer.io_Command = CMD_READ;
   BeginIO( r );                       /* start receive request */
}

/*------------------------------------------------------------*/
/*  PushSerState: save current io flags                       */
/*------------------------------------------------------------*/
/*
void PushSerState()
{
   register struct IOExtSer *r = Read_Request; 

   if ( stackSize < MAXSTACK )
     {
        /comment* Save the current Mode /
        modeStack[ stackSize ] = Mode;
        
	/comment* Get the current flags /
	AbortIO( r );
	flagStack[ stackSize++ ] = r->io_SerFlags;
	BeginIO( r );
     }
}
*/

/*------------------------------------------------------------*/
/*  PullSerState: restore last saved flag state		      */
/*------------------------------------------------------------*/
/*
void PullSerState()
{
   register struct IOExtSer *r = Read_Request; 

   if ( stackSize > 0 )
     {
	/comment* Reset the Mode /
	Mode = modeStack[ --stackSize ];

	/comment* Set the old flags /
	AbortIO( r );
	r->io_SerFlags = flagStack[ stackSize ];
	r->IOSer.io_Command = SDCMD_SETPARAMS;
	DoIO( r );
	r->IOSer.io_Command = CMD_READ;
	BeginIO( r );
     }
}
*/

/*-------------------------------------------------------------*/
/*           CloseSerialIO: Close the serial port              */
/*-------------------------------------------------------------*/
void CloseSerialIO()
{
   register struct IOExtSer *r = Read_Request;
   register struct IOExtSer *w = Write_Request;

   if ( r != NULL )
     {
	CloseDevice( r );
	DeletePort( r->IOSer.io_Message.mn_ReplyPort );
	FreeMem( r, (long)sizeof( *r ) );
	Read_Request = NULL;
      }

    if ( w != NULL )
      {
	CloseDevice( w );
	DeletePort( w->IOSer.io_Message.mn_ReplyPort );
	FreeMem( w, (long)sizeof( *w ) );
	Write_Request = NULL;
      }
}
/*-------------------------------------------------------------*/
/* InitSerialIO: Open serial IO - return read Port	       */
/*-------------------------------------------------------------*/	
int InitSerialIO(rd, wr)
struct IOExtSer **rd, **wr;
{
   register struct IOExtSer *r, *w;

   r = (struct IOExtSer *) AllocMem( (long)sizeof( *r),
     (long)MEMF_PUBLIC|MEMF_CLEAR);
   if (r == NULL)
	return NULL;

   Read_Request = r;
   r->io_SerFlags = SERFLAGS;
   r->io_CtlChar  = CTLCHAR;
   r->IOSer.io_Message.mn_ReplyPort = CreatePort(NULL,NULL);
   if(OpenDevice(SERIALNAME,NULL,r,NULL))
      {
	 puts("Can't open Read device\n");
	goto q4;
      }

   r->io_Baud = STARTBAUD;
   r->io_ReadLen = 8;
   r->io_WriteLen = 8;
   r->IOSer.io_Command = SDCMD_SETPARAMS;
   DoIO(r);
   r->IOSer.io_Command = CMD_READ;
   r->IOSer.io_Length = 1;
   r->IOSer.io_Data = (APTR)&rs_in[0];


   w = (struct IOExtSer *)AllocMem( (long)sizeof( *w),
      (long)MEMF_PUBLIC|MEMF_CLEAR);
   if (w == NULL) goto q3;

   Write_Request = w;
   w->io_SerFlags = SERFLAGS;
   w->io_CtlChar  = CTLCHAR;
   w->IOSer.io_Message.mn_ReplyPort = CreatePort(NULL,NULL);
   if(OpenDevice(SERIALNAME,NULL,w,NULL))
      {
	puts("Can't open Write device\n");
	goto q1;
      }
   w->io_Baud = STARTBAUD;
   w->io_ReadLen = 8;
   w->io_WriteLen = 8;
   w->IOSer.io_Command = SDCMD_SETPARAMS;
   DoIO(w);

   w->IOSer.io_Command = CMD_WRITE;
   w->IOSer.io_Length = 1;
   w->IOSer.io_Data = (APTR)&rs_out[0];

   BeginIO( r );
	*rd = r;
	*wr = w;
   return 1;

q1:   DeletePort( w->IOSer.io_Message.mn_ReplyPort );
q2:   FreeMem( w, (long)sizeof( *w) );
q3:   CloseDevice( r );
q4:   DeletePort( r->IOSer.io_Message.mn_ReplyPort );
q5:   FreeMem( r, (long)sizeof( *r) );

   return NULL;
}

/*----------------------------------------------------------*/
/*         SetXonMode: set Xon On or Off                    */
/*----------------------------------------------------------*/

void SetXonMode( status )
BOOL status;
{

   register UBYTE flags;
   register struct IOExtSer *r = Read_Request; 

   /* Get the current flags */
   AbortIO( r );
   flags = r->io_SerFlags;

   if ( status )
      flags &= ~(SERF_XDISABLED);
   else
      flags |= SERF_XDISABLED; 
   r->io_SerFlags = flags;
   r->IOSer.io_Command = SDCMD_SETPARAMS;
   DoIO( r );
   r->IOSer.io_Command = CMD_READ;
   BeginIO( r );
}

/*----------------------------------------------------------*/
/*         SetSerBaud: set Serial Baud Rate                 */
/*----------------------------------------------------------*/

void SetSerBaud( baud )
int baud;
{
   register struct IOExtSer *r = Read_Request; 

   /* Get the current flags */
   AbortIO( r );
   r->io_Baud = baud;
   r->IOSer.io_Command = SDCMD_SETPARAMS;
   DoIO( r );
   r->IOSer.io_Command = CMD_READ;
   BeginIO( r );
}

/*----------------------------------------------------------*/
/*         SerIOPut: put a byte out the serial port	    */
/*----------------------------------------------------------*/

void SerIOPut( c )
register UBYTE c;
{

   *rs_out = c;
   DoIO( Write_Request );

}

/*----------------------------------------------------------*/
/*         SerIOGet: get a byte from the serial port	    */
/*----------------------------------------------------------*/

UBYTE SerIOGet()
{
   register struct IOExtSer *r = Read_Request;
   register UBYTE c;

   WaitIO( r );
   c = *rs_in;
   BeginIO( r );

   if ( Mode )	/* if MODEECHO */
      {
         *rs_out = c;
         DoIO( Write_Request );
      }
   return c;
}

