/* Comm serial I/O handlers */ extern struct IOExtSer *AllocMem(); extern struct MenuItem BaudItems[]; extern UBYTE doinit[], doexit[]; static int bits, length, parity; static int xbits, xlength, xparity; #define SERIALIO 1 #include "globals.h" init_serial() { Read_Request = AllocMem((long)sizeof(*Read_Request), MEMF_PUBLIC | MEMF_CLEAR); Read_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED; Read_Request->IOSer.io_Message.mn_ReplyPort = CreatePort("Read_RS",0L); if(OpenDevice(SERIALNAME,0L,Read_Request,0L)) return FALSE; Read_Request->IOSer.io_Command = CMD_READ; Read_Request->IOSer.io_Length = 1; Read_Request->IOSer.io_Data = (APTR) &rs_in[0]; Write_Request = AllocMem((long)sizeof(*Write_Request), MEMF_PUBLIC | MEMF_CLEAR); Write_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED; Write_Request->IOSer.io_Message.mn_ReplyPort = CreatePort("Write_RS",0L); if(OpenDevice(SERIALNAME,0L,Write_Request,0L)) return FALSE; Echo_Request = AllocMem((long)sizeof(*Echo_Request), MEMF_PUBLIC | MEMF_CLEAR); Echo_Request->io_SerFlags = SERF_XDISABLED | SERF_SHARED | IOF_QUICK; Echo_Request->IOSer.io_Message.mn_ReplyPort = CreatePort("Echo_RS",0L); if(OpenDevice(SERIALNAME,0L,Echo_Request,0L)) return FALSE; Write_Request->IOSer.io_Command = CMD_WRITE; Write_Request->IOSer.io_Length = 1; Write_Request->IOSer.io_Data = (APTR) &rs_out[0]; 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; Read_Request->IOSer.io_Length = 1; Read_Request->IOSer.io_Data = (APTR) &rs_in[0]; Read_Request->io_Baud = baud; Read_Request->io_ReadLen = 8; Read_Request->io_WriteLen = 8; Read_Request->io_CtlChar = 0x11130000L; Read_Request->io_RBufLen = 1024; Read_Request->IOSer.io_Command = SDCMD_SETPARAMS; DoIO(Read_Request); Read_Request->IOSer.io_Command = CMD_READ; return TRUE; } /**************************************************************/ /* send char and read char functions for the xmodem function */ /************************************************************/ sendchar(ch) int ch; { rs_out[0] = ch & 0xFF; DoIO(Write_Request); } /************************/ /* echo char to sender */ /************************/ echochar(ch) int ch; { rs_echo[0] = ch & 0xFF; DoIO(Echo_Request); if(ch == '\r') echochar('\n'); } /************************************* readchar() waits for a character timeout built in. Timeout condition causes error return 'seconds' controls duration of wait. 'doabort' TRUE indicates that CAN recvd will set cancel flag **************************************/ readchar( seconds, doabort ) unsigned int doabort, seconds; { extern void emits_rx(); extern long CheckIO(); UBYTE ch; timeout = FALSE; StartTimer((unsigned long)seconds,0L); /* start timeout */ /* wait for a TX window event, the timer to timeout or for a receive character */ wait: Wait( 1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit | 1L << TimerMsgPort.mp_SigBit | 1L << tx_window->UserPort->mp_SigBit ); if(CheckIO(Read_Request)) /* if IO request has completed */ { AbortIO(&TimerIO); Wait( 1L << TimerMsgPort.mp_SigBit); WaitIO(Read_Request); /* remove the message from the queue */ ch = rs_in[0]; /* get character */ BeginIO(Read_Request); /* start a new request */ if( ch == CAN && doabort) /* if this is a CAN char and doabort TRUE */ cancel = TRUE; /* set cancel flag */ return (int)(ch); } /* see if the timer timed out */ if(CheckIO(&TimerIO)) /* was timeout */ { emits_rx(" Timeout\n"); timeout = TRUE; return TIMEOUT; } /* otherwise it was a tx_window input */ Process_window_event(); if(abort) { AbortIO(&TimerIO); Wait( 1L << TimerMsgPort.mp_SigBit); return TIMEOUT; } goto wait; /* wait for Timeout or character */ } /*********************************** Flush receive buffer. Removes pending rx characters to help maintain line syncronization ************************************/ void purge_line() { purge_port(); BeginIO(Read_Request); } purge_port() { AbortIO(Read_Request); /* abort any reads */ WaitIO(Read_Request); /* wait for abort to complete */ Read_Request->IOSer.io_Command = CMD_FLUSH; DoIO(Read_Request); /* flush all IO requests */ Read_Request->IOSer.io_Command = CMD_CLEAR; DoIO(Read_Request); /* flush receive buffer */ Read_Request->IOSer.io_Command = CMD_READ; } /* enable/disable XON/XOFF checking in the serial driver */ Xon(val) int val; { AbortIO(Read_Request); WaitIO(Read_Request); if(val) /* if TRUE, turn on XON/XOFF handling */ Read_Request->io_SerFlags &= ~SERF_XDISABLED; else /* disable XON/XOFF */ Read_Request->io_SerFlags |= SERF_XDISABLED; Read_Request->IOSer.io_Command = SDCMD_SETPARAMS; DoIO(Read_Request); Read_Request->IOSer.io_Command = CMD_READ; BeginIO(Read_Request); } /* Close the serial device */ Close_Serial() { if( Read_Request ) /* if open, close it */ { CloseDevice( Read_Request ); DeletePort( Read_Request->IOSer.io_Message.mn_ReplyPort ); FreeMem( Read_Request, (long)sizeof(*Read_Request) ); } if( Write_Request ) /* ditto */ { CloseDevice( Write_Request ); DeletePort( Write_Request->IOSer.io_Message.mn_ReplyPort ); FreeMem( Write_Request, (long)sizeof(*Write_Request) ); } if( Echo_Request ) /* ditto */ { CloseDevice( Echo_Request ); DeletePort( Echo_Request->IOSer.io_Message.mn_ReplyPort ); FreeMem( Echo_Request, (long)sizeof(*Echo_Request) ); } } /*********************************** Start line. Restart line if stopped with XOFF ************************************/ void Start_line() { sendchar(XON); /* use Echo_Request because it's not busy at the time this is called */ Echo_Request->IOSer.io_Command = CMD_START; DoIO(Echo_Request); /* Restart line request */ } /*********************************** Set baud rate ***********************************/ void set_baud( num ) int num; { USHORT i,itemnum; switch( num ) { case 300: itemnum = 0; break; case 1200: itemnum = 1; break; case 2400: itemnum = 2; break; case 4800: itemnum = 3; break; case 9600: itemnum = 4; break; case 19200:itemnum = 5; break; default: return; } baud = num; purge_port(); Read_Request->io_Baud = (long)num; /* set new baud rate */ Setparams(); for(i = 0; i < RSMAX; i++) BaudItems[ i ].Flags &= ~CHECKED; /* reset Checkmark */ BaudItems[ itemnum ].Flags |= CHECKED; /* Check real baud rate */ } /* see if any characters are in the receive buffer */ /* return FALSE if IO pending, TRUE if not */ check_line() { return(CheckIO(Read_Request)); } /* Read the characters buffered in the RX buffer. First satisfy the 1 character read we started. Then do an I/O query to see how many more characters are ready. Then issue a Read request for these characters. */ USHORT Read_RS() { USHORT len; WaitIO(Read_Request); /* read the 1st rx character */ Echo_Request->IOSer.io_Command = SDCMD_QUERY; DoIO(Echo_Request); dcd = Echo_Request->io_Status & 0x28; len = Echo_Request->IOSer.io_Actual; /* how many bytes in RX buffer */ if(len != 0) { if(len > RSBUFSIZ-1) /* lets not overflow our buffer */ len = RSBUFSIZ-1; Read_Request->IOSer.io_Length = len; Read_Request->IOSer.io_Data = (APTR) &rs_in[1]; DoIO(Read_Request); /* go get em */ Read_Request->IOSer.io_Length = 1; Read_Request->IOSer.io_Data = (APTR) &rs_in[0]; } return (len + 1); } SendBreak() { /* use Echo_Request because it's not busy at the time this is called */ Echo_Request->IOSer.io_Command = SDCMD_BREAK; Echo_Request->io_SerFlags |= SERF_QUEUEDBRK; DoIO(Echo_Request); /* Restart line request */ Echo_Request->io_SerFlags &= ~SERF_QUEUEDBRK; } Setparity(parnum) int parnum; { WaitRequest(); switch( parnum ) { case 0: /* no parity */ Read_Request->io_SerFlags &= ~SERF_PARTY_ON; break; case 1: /* odd parity */ Read_Request->io_SerFlags |= SERF_PARTY_ODD | SERF_PARTY_ON; break; case 2: /* even parity */ Read_Request->io_SerFlags |= SERF_PARTY_ON; Read_Request->io_SerFlags &= ~SERF_PARTY_ODD; break; } parity = parnum; Setparams(); } Setlength( len ) int len; { WaitRequest(); switch( len ) { case 0: /* 8 bits */ Read_Request->io_ReadLen = Read_Request->io_WriteLen = 8; break; case 1: /* 7 bits */ Read_Request->io_ReadLen = Read_Request->io_WriteLen = 7; break; } length = len; Setparams(); } Setstopbits( num ) int num; { if( (Read_Request->io_ReadLen == 8) & ( num == 1 ) ) { emits_rx("SERIAL DEVICE ERROR: can't have 2 stop bits with 8 bit word\n"); return; } WaitRequest(); switch( num ) { case 0: /* 1 stop bit */ Read_Request->io_StopBits = 1; break; case 1: /* 2 stop bits */ Read_Request->io_StopBits = 2; break; } bits = num; Setparams(); } Setparams() { Read_Request->IOSer.io_Command = SDCMD_SETPARAMS; DoIO(Read_Request); Read_Request->IOSer.io_Command = CMD_READ; BeginIO(Read_Request); } WaitRequest() { AbortIO(Read_Request); /* abort it */ WaitIO(Read_Request); /* wait for abort to finish */ } Xconfig( state ) int state; { if(state == FALSE) /* restore state */ { Setstopbits( xbits ); Setparity( xparity ); Setlength( xlength ); Xon(xonflg); } else { xbits = bits; xparity = parity ; xlength = length; Setstopbits( 0 ); /* 1 stop bit */ Setparity( 0 ); /* no parity */ Setlength( 0 ); /* 8 bits */ Xon( FALSE ); } } Modem_init() { sendout(doinit); } Modem_exit() { sendout(doexit); }