#include <stdio.h>
#include <exec/types.h>
#include <exec/io.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <hardware/cia.h>
#include <devices/serial.h>

struct	IOExtSer *Read_Request;
struct	MsgPort *ReadPort;
extern char read_in[];
struct	IOExtSer *Write_Request;
struct	MsgPort *WritePort;
char	rs_out[2];
struct	IOExtSer *Echo_Request;
struct	MsgPort *EchoPort;
char	rs_echo[2];

int		Ser_Stat;

int ComOpen(
char	*device,
int		unit,
long	baudrate,
int		bits,
int		parity,
int		stopbits,
int		WIRE7)
{
	if(ReadPort = (struct MsgPort*)CreatePort(0,0))
	{
		if(Read_Request = (struct IOExtSer*)
			CreateExtIO(ReadPort,sizeof(struct IOExtSer)))
		{
			Read_Request->IOSer.io_Message.mn_ReplyPort = ReadPort;
			Read_Request->io_SerFlags = SERF_SHARED|SERF_XDISABLED;
			if(WIRE7)
				Read_Request->io_SerFlags |= SERF_7WIRE;
			if((OpenDevice(device,unit,Read_Request,0)) == 0)
			{
				Read_Request->IOSer.io_Command = CMD_READ;
				Read_Request->IOSer.io_Length = 1;
				Read_Request->IOSer.io_Data = (APTR)&read_in[0];
				if(WritePort = (struct MsgPort*)CreatePort(0,0))
				{
					if(Write_Request = (struct IOExtSer*)
						CreateExtIO(ReadPort,sizeof(struct IOExtSer)))
					{
						Write_Request->IOSer.io_Message.mn_ReplyPort = WritePort;
						Write_Request->io_SerFlags = SERF_SHARED|SERF_XDISABLED;
						if(WIRE7)
							Write_Request->io_SerFlags |= SERF_7WIRE;
						if((OpenDevice(device,unit,Write_Request,0)) == 0)
						{
							Write_Request->IOSer.io_Command = SDCMD_QUERY;
							DoIO(Write_Request);
							Write_Request->IOSer.io_Command	= CMD_WRITE;
							Write_Request->IOSer.io_Length	= 1;
							Write_Request->IOSer.io_Data	= (APTR)&rs_out[0];
							if(EchoPort = (struct MsgPort*)CreatePort(0,0))
							{
								if(Echo_Request = (struct IOExtSer*)
									CreateExtIO(EchoPort,sizeof(struct IOExtSer)))
								{
									Echo_Request->IOSer.io_Message.mn_ReplyPort = EchoPort;
									Echo_Request->io_SerFlags = SERF_SHARED|SERF_XDISABLED;
									if(WIRE7)
										Echo_Request->io_SerFlags |= SERF_7WIRE;
									if((OpenDevice(device,unit,Echo_Request,0)) == 0)
									{
										Echo_Request->IOSer.io_Command = SDCMD_QUERY;
										DoIO(Echo_Request);
										Echo_Request->IOSer.io_Command	= CMD_WRITE;
										Echo_Request->IOSer.io_Length	= 1;
										Echo_Request->IOSer.io_Data		= (APTR)&rs_echo[0];

										Read_Request->io_SerFlags 		= SERF_SHARED | SERF_XDISABLED;
										if(WIRE7)
										Read_Request->io_SerFlags |= SERF_7WIRE;
										Read_Request->IOSer.io_Length	= 1;
										Read_Request->IOSer.io_Data		= (APTR)&read_in[0];
										Read_Request->io_Baud     		= baudrate;
										Read_Request->io_StopBits 		= stopbits;
										Read_Request->io_ReadLen  		= bits;
										Read_Request->io_WriteLen 		= bits;
										Read_Request->io_CtlChar  		= 1L;
										Read_Request->io_RBufLen  		= 2048;
										Read_Request->IOSer.io_Command	= SDCMD_SETPARAMS;
										DoIO(Read_Request);
										Read_Request->IOSer.io_Command	= CMD_READ;
										return(TRUE);
									}
									DeleteExtIO(Echo_Request);
								}
								DeletePort(EchoPort);
							}
							CloseDevice(Write_Request);
						}
						DeleteExtIO(Write_Request);
					}
					DeletePort(WritePort);
				}
				CloseDevice(Read_Request);
			}
			DeleteExtIO(Read_Request);
		}
		DeletePort(ReadPort);
	}
return(FALSE);
}

void ComClose()
{
	AbortIO(Read_Request);
	WaitIO(Read_Request);
	CloseDevice(Read_Request);
	DeleteExtIO(Read_Request);
	DeletePort(ReadPort);
	CloseDevice(Write_Request);
	DeleteExtIO(Write_Request);
	DeletePort(WritePort);
	CloseDevice(Echo_Request);
	DeleteExtIO(Echo_Request);
	DeletePort(EchoPort);
}

int ComCarrier()
{
	int status;

	Echo_Request->IOSer.io_Command = SDCMD_QUERY;
	DoIO(Echo_Request);
	status = Echo_Request->io_Status & CIAF_COMCD;
	return(status?FALSE:TRUE);
}

void ComSetBaud(baudrate)
long baudrate;
{
	if(!(CheckIO(Read_Request)))
	{
		AbortIO(Read_Request);
		WaitIO(Read_Request);
	}
	Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
	Read_Request->io_Baud = baudrate;
	DoIO(Read_Request);

	Read_Request->IOSer.io_Command = CMD_READ;	/* start reading again */
	Read_Request->IOSer.io_Length = 1;
	Read_Request->IOSer.io_Data = (APTR) &read_in[0];
}

int ComSetFlow(flow)
int flow;
{
	if(!(CheckIO(Read_Request)))
	{
		AbortIO(Read_Request);
		WaitIO(Read_Request);
	}
	Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
	if(flow)
		Read_Request->io_SerFlags |= SERF_7WIRE;
	else
		Read_Request->io_SerFlags &= ~SERF_7WIRE;
	DoIO(Read_Request);

	Read_Request->IOSer.io_Command = CMD_READ;	/* start reading again */
	Read_Request->IOSer.io_Length = 1;
	Read_Request->IOSer.io_Data = (APTR) &read_in[0];
	return(0);
}

void ComPutc(ch)
unsigned char ch;
{
	if(!(CheckIO(Write_Request)))
		WaitIO(Write_Request);
	rs_out[0] = ch & 0xFF;
	Write_Request->IOSer.io_Command = CMD_WRITE;
	Write_Request->IOSer.io_Length = 1;
	Write_Request->IOSer.io_Data = (APTR)&rs_out[0];
	SendIO(Write_Request);
}

int ComRead(buffer,amount)
unsigned char *buffer;
int amount;
{
	int serlen;

	if(!(CheckIO(Read_Request)))
	{
		AbortIO(Read_Request);
		WaitIO(Read_Request);
	}

	Echo_Request->IOSer.io_Command = SDCMD_QUERY;
	DoIO(Echo_Request);

	serlen = Echo_Request->IOSer.io_Actual;	/* How many bytes in RX buffer */

	if(serlen == 0)
		return(0);
	if(serlen > amount) serlen = amount;
	Read_Request->IOSer.io_Length = serlen;
	Read_Request->IOSer.io_Data = (APTR)buffer;
	DoIO(Read_Request);
	Read_Request->IOSer.io_Length = 1;
	Read_Request->IOSer.io_Data = (APTR) &read_in[0];

	return(serlen);
}

void ComWrite(buffer,amount)
unsigned char *buffer;
int amount;
{
	if(!(CheckIO(Write_Request)))
		WaitIO(Write_Request);
	Write_Request->IOSer.io_Command = CMD_WRITE;
	Write_Request->IOSer.io_Length = amount;
	Write_Request->IOSer.io_Data = (APTR)buffer;
	DoIO(Write_Request);
}
