📄 serlink.c
字号:
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Serial link communications core.
*
****************************************************************************/
#include "trpimp.h"
#include "trperr.h"
#include "stddef.h"
#include "string.h"
#include "serial.h"
#include "packet.h"
static int BaudCounter; /* baud rate counter */
static int LastResponse = NAK; /* last response holder */
static int Errors = 0; /* Errors so far */
static int PrevErrors = 0; /* Errors of previous BlockSend() operation */
static unsigned SendBlkNo = 0; /* next block number to send */
static unsigned ReceiveBlkNo = 0; /* next block number to receive */
static unsigned BytesReceived; /* # bytes from last receive */
int MaxBaud;
#define BAUD_ENTRY( x ) #x, sizeof( #x ) - 1, TEST_TIME( x )
baud_entry BaudTable[] = {
BAUD_ENTRY( 115200 ),
BAUD_ENTRY( 57600 ),
BAUD_ENTRY( 38400 ),
BAUD_ENTRY( 19200 ),
BAUD_ENTRY( 9600 ),
BAUD_ENTRY( 4800 ),
BAUD_ENTRY( 2400 ),
BAUD_ENTRY( 1200 ),
"0", 1, 0,
};
extern char *ParsePortSpec( char * * );
extern char *InitSys( void );
extern void ResetSys( void );
extern bool Baud( int );
extern void ClearCom( void );
extern int GetByte( void );
extern void SendByte( int );
extern void DonePort( void );
extern bool CheckPendingError( void );
extern void ClearLastChar( void );
extern void ZeroWaitCount( void );
extern unsigned WaitCount( void );
extern int WaitByte( unsigned );
extern void Wait( unsigned );
extern void StartBlockTrans( void );
extern void StopBlockTrans( void );
#ifdef SERVER
extern void ServMessage( char * );
#endif
void SyncPoint( unsigned tick )
{
Wait( tick - WaitCount() );
}
static int SenderHandshake( void )
{
unsigned wait_time; /* used to test for time-out */
int reply; /* storing data received from other machine */
wait_time = WaitCount() + SYNC_TIME_OUT; /* limit for time out */
if( MaxBaud == MIN_BAUD ) wait_time += SEC(1);
SendByte( SYNC_BYTE ); /* send SYNC_BYTE */
for( ;; ) { /* loop until ACK received or time out */
reply = WaitByte( 1 ); /* get reply */
if( reply == ACK ) break; /* ACK received; go to next operation */
if( reply == HI ) { /* return HI received */
SendByte( HI );
} else if( WaitCount() > wait_time ) { /* time out */
return( FAIL );
} /* not yet time out; loop */
}
SendByte( SYNC_END );
return( SUCCESS );
}
/* This routine is one side of the set baud rate routine -- sender
Result: SUCCESS or FAIL */
static int SetBaudSender( void )
{
int data; /* storing sync string data to other machine */
int i; /* loop index */
int wait_time;
if( !SenderHandshake() ) return( FAIL );
/* sync byte received ... send string */
StartBlockTrans();
for( i = data = 0; i < SYNC_LEN; i++, data = (data + SYNC_INC) & 0xff ) {
SendByte( data ); /* send sync string bytes */
}
StopBlockTrans();
wait_time = WaitCount() + SYNC_TIME_OUT; /* limit for time out */
/* If MaxBaud == MIN_BAUD, we're talking over a modem and it might
have buffered characters that haven't been transmitted yet. */
if( MaxBaud == MIN_BAUD ) wait_time += SEC(2);
for( ;; ) {
if( WaitByte( 1 ) == TAK ) {
SendByte( ACK );
if( WaitByte( SEC(1)/2 ) == TAK ) {
return( SUCCESS );
} else {
return( FAIL );
}
} else if( WaitCount() >= wait_time ) {
/* break not found; other end have not acknowledged string */
return( FAIL );
}
}
}
/*========================================================================*/
/*========================================================================*/
/* This routine determines if speed sync string received ok.
Input: Receive buffer should have sync string
Return: SUCCESS or FAIL */
static int CheckSyncString( void )
{
int syn_c; /* correct sync string bytes value */
int i; /* loop index */
unsigned wait;
if( CheckPendingError() ) return( FAIL );
wait = (MaxBaud == MIN_BAUD) ? SEC(2) : (SEC(1)/4);
for( syn_c = i = 0; i < SYNC_LEN; ++i, syn_c = (syn_c + SYNC_INC) & 0xff ) {
if( WaitByte( wait ) != syn_c ) { /* error -- timeout or incorrect data */
return( FAIL );
}
wait = SEC(1)/4;
}
return( SUCCESS );
}
/*========================================================================*/
/*========================================================================*/
static int ReceiverHandshake( void )
{
int reply; /* storing data received from other machine */
int wait_time;
wait_time = WaitCount() + SYNC_TIME_OUT;
if( MaxBaud == MIN_BAUD ) wait_time += SEC(1);
for( ;; ) { /* loop until SYNC_END received or time out */
reply = WaitByte( 1 ); /* get character */
if( reply == SYNC_END ) break; /* SYNC_END received; continue */
if( reply == SYNC_BYTE ) { /* SYNC_BYTE received; send ACK */
SendByte( ACK );
} else if( reply == HI ) { /* return HI received */
SendByte( HI );
} else if( WaitCount() >= wait_time ) { /* 2 sec time out */
return( FAIL );
} /* not yet time out; loop */
}
return( SUCCESS );
}
/* This routine is one side of the set baud rate routine -- receiver
Result: SUCCESS or FAIL */
static int SetBaudReceiver( void )
{
unsigned wait;
if( !ReceiverHandshake() ) return( FAIL );
/* sync string should have been received; and in receive buffer now
CheckSyncString() checks if sync string is received successfully */
if( CheckSyncString() ) {
SendByte( TAK );
wait = (MaxBaud == MIN_BAUD) ? SEC(2) : SEC(1)/2;
if( WaitByte( wait ) == ACK ) {
SendByte( TAK );
return( SUCCESS );
} else {
return( FAIL );
}
} else {
return( FAIL );
}
}
/*========================================================================*/
/*========================================================================*/
/* This routine tries to establish reliable connection at a specific
baud rate. baud_index contains the baud rate index
Output: SUCCESS or FAIL */
static int SetBaud( int baud_index, int *sync_point_p )
{
int reply; /* storing data received from other machine */
int sync_point;
sync_point = *sync_point_p;
*sync_point_p += MAX_BAUD_SET_TICKS + 3*SYNC_SLOP;
if( !Baud( baud_index ) ) return( FAIL ); /* sets up baud rate */
SyncPoint( sync_point );
ClearCom();
Wait( SYNC_SLOP );
SendByte( HI );
reply = WaitByte( SYNC_SLOP*2 );
if( reply != HI ) {
return( FAIL );
}
/* now go the other way */
*sync_point_p += BaudTable[ baud_index ].full_test_ticks;
#ifdef SERVER
if( !SetBaudReceiver() ) return( FAIL );
if( !SetBaudSender() ) return( FAIL );
#else
if( !SetBaudSender() ) return( FAIL );
if( !SetBaudReceiver() ) return( FAIL );
#endif
return( SUCCESS );
}
/*========================================================================*/
/*========================================================================*/
bool MarchToTheSameDrummer( void )
{
int got;
#ifdef SERVER
SendByte( LOK );
#else
if( ( got = WaitByte( SEC( 2 ) ) ) != LOK ) {
return( FAIL );
}
#endif
#ifndef SERVER
SendByte( ACK );
#else
if( ( got = WaitByte( SEC(1)/2 ) ) != ACK ) {
return( FAIL );
}
#endif
Wait( 1 ); /* don't go till the timer hits exactly on the tick */
ZeroWaitCount();
return( SUCCESS );
}
bool SetSyncTime( void )
{
if( MaxBaud != MIN_BAUD ) {
if( !Baud( LOW_BAUD ) ) return( FAIL );
}
#ifdef SERVER
if( WaitByte( SEC(1)/10 ) != HI ) {
return( FAIL );
}
#else
SendByte( HI );
#endif
return( MarchToTheSameDrummer() );
}
/*========================================================================*/
/*========================================================================*/
/* This routine sets up the highest possible baud rate.
BaudCounter contains the baud rate index
Returns: SUCCESS or FAIL */
static int Speed( void )
{
int sync_point;
if( !MarchToTheSameDrummer() ) return( FAIL );
sync_point = MAX_BAUD_SET_TICKS;
for( ;; ) {
if( SetBaud( BaudCounter, &sync_point ) ) break;
++BaudCounter; /* ... try next slower speed */
if( BaudCounter >= MIN_BAUD ) {
BaudCounter = MIN_BAUD;
return( FAIL );
}
}
return( SUCCESS ); /* link established */
}
/*========================================================================*/
/*========================================================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -