⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mnpllvl.c

📁 汇编源代码大全2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*=============================================================================

			         The Microcom MNP Library
					(Microsoft C Version)

-------------------------------------------------------------------------------

		         MNPLLVL - MNP Link Level Routines

-------------------------------------------------------------------------------

     Modification History

	3/25/87 - Compuserve V1.0

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

/* Header files 
*/
#include <dos.h>
#include <mnpdat.h>
#include <llvl.h>

/* External references
*/
extern USIGN_16 sb_cnt;

/* Global buffers 
*/
struct link_ctl_blk lcb;

struct BUFFER rb, ftb, lkb, rlkb;

struct BLST lkblst[2],
	    rlkblst[2],
	    iatblst[8];

USIGN_8 lkbuff[MAX_LPDU_SZ * 2];
USIGN_8 rlkbuff[MAX_LPDU_SZ * 2];
USIGN_8 iatbuff[(64+5)*8];

USIGN_16 tbcnt;

USIGN_16 g_tm,
	ack_tm,
	fcw_tm,
	lr_tm,
	lt_tm,
	ln_tm;

USIGN_16 port_add,
	chan_no,
	iir_add;

USIGN_8 linestat;

/* Function declarations
*/
void as_disconnect();
SIGN_16 acking();
SIGN_16 credit_chk();
SIGN_16 lpdu_send();
SIGN_16 parse_lr();
SIGN_16 receive_wait();
SIGN_16 retran_lt();
SIGN_16 send_la();
SIGN_16 send_pdu();
SIGN_16 send_wait();

/*GLOBAL********************************************************************

	as_connect - establish an MNP link-connection

***************************************************************************/

SIGN_16 as_connect (mnpcb,mode)

struct MNP_CB *mnpcb;
USIGN_16 mode;
{

SIGN_16 lr_cnt,
    la_cnt,
    retcode,
    link_state;

/* Initialize
*/
lcb.lpdu_type = 0;
link_state = IDLE;

for (;;)
	{

	switch (link_state)
		{

		case IDLE:
			link_init(mnpcb);
			link_reset();
			if (L_ACCEPTOR)
				{
				SETBIT1(MODE)
				link_state = LR_WAIT;
				}
			else
				{
				suspend(5);
				if (retcode = lpdu_send(LR,WAIT))
					link_state = LNK_ERROR;
				else
					link_state = LR_RESP_WAIT;
				}
			break;

		case LR_RESP_WAIT:
			lr_cnt = LR_RETRAN_CNT;
			retcode = SUCCESS;
			while ((retcode = receive_wait()) || !lcb.lpdu_type)
				{
				if (retcode == NO_PHYSICAL)
					{
					link_state = LNK_ERROR;
					break;
					}
				if (lr_cnt--)
					{
					if (retcode = lpdu_send(LR,WAIT))
						{
						link_state = LNK_ERROR;
						break;
						}
					}
				else
					{
					retcode = TIME_OUT;
					link_state = LNK_ERROR;
					break;
					}
				}

			if (retcode == SUCCESS) 
				link_state = PARMS_NEGO;
			break;

		case PARMS_NEGO:
			if (retcode = parse_lr())
				{
				as_disconnect(retcode,NULL);
				return(retcode + LR_CODE);
				}

			if (retcode = lpdu_send(LA,WAIT))
				link_state = LNK_ERROR;
			else
				link_state = LNK_CONNECTED;
			break;

		case LR_WAIT:
			lr_cnt = 2;
			while ((retcode = receive_wait()) || !lcb.lpdu_type)
				{
				if (retcode == NO_PHYSICAL)
					{
					link_state = LNK_ERROR;
					break;
					}
				if (!(--lr_cnt))
					{
					retcode = TIME_OUT;
					link_state = LNK_ERROR;
					break;
					}
				}

			if (link_state != LR_WAIT)
				break;

			if (retcode = parse_lr())
				{
				as_disconnect(retcode,NULL);
				return(retcode + LR_CODE);
				}

			lr_cnt = LR_TRAN_CNT;
			link_state = CONNECT_REQ_WAIT;
			break;

		case CONNECT_REQ_WAIT:
			if (lr_cnt == NULL)
				{
				retcode = FAILURE;
				link_state = LNK_ERROR;
				break;
				}

			if (retcode = lpdu_send(LR,WAIT))
				link_state = LNK_ERROR;
			else
				{
				lr_cnt--;
				la_cnt = LA_WAIT_CNT;
				link_state = LA_WAIT;
				}
			break;

		case LA_WAIT:
			while ((retcode = receive_wait()) || !lcb.lpdu_type)
				{
				if (retcode == NO_PHYSICAL)
					{
					link_state = LNK_ERROR;
					break;
					}
		    		if (--la_cnt)
					{
					if (retcode = lpdu_send(LR,WAIT))
						{
						link_state = LNK_ERROR;
						break;
						}
					}
				else
					{
					retcode = TIME_OUT;
					link_state = LNK_ERROR;
					break;
					}
				}

			if (link_state != LA_WAIT)
				break;

			switch (lcb.lpdu_type)
				{
				case LA:
					lcb.lt_rsn = NULL;

				case LT:
					link_state = LNK_CONNECTED;
					break;

				case LR:
					ret_b (&rlkb,rlkb.used_lst);
					link_state = CONNECT_REQ_WAIT;
					break;
	
				default:
					retcode = FAILURE;
					link_state = LNK_ERROR;
				}

			break;

		case LNK_ERROR:
			as_disconnect(NULL,NULL);
			return(retcode);

		case LNK_CONNECTED:
			dphase_init();
			SETBIT1(LINK_EST)
			return(SUCCESS);
		}
	}
}

/*GLOBAL***********************************************************************

	as_disconnect - terminate a link-connection

******************************************************************************/

void as_disconnect(lreason,ureason)

SIGN_16 lreason,
	ureason;
{

/* If the link is still up, send an LD LPDU to the other side.  If the
** caller has supplied a reason code (in ureason) then save this code
** in the lcb so that it will be sent in the LD.  Wait for the LD to 
** actually be sent (to the very last byte...). 
*/
if (BIT1SET(LINK_EST))
	{
	if ((lcb.l_disc_code = lreason) == 255)
		lcb.u_disc_code = ureason;
	lpdu_send(LD,NOWAIT);
	while (!lne_stat() && modem_out_busy)
		;
	CLRBIT1(LINK_EST);
	}

/* In any case, wait a bit.
*/
suspend(10);

/* Now remove interrupt handlers - link driver and timers. 
*/
drvr_rem();
timerrem();

}

/*GLOBAL********************************************************************

	as_link - maintain a link-connection

***************************************************************************/

SIGN_16 as_link()
{

SIGN_16 retcode;

/* If the link-connection has failed, return reporting link down. 
*/
if (!BIT1SET(LINK_EST))
	return (LNK_DOWN);

/* If the physical connection has been lost, return reporting p-conn down. 
*/
if (lne_stat())
	return (NO_PHYSICAL);

/* If we support attention service, go see if we have any to process. 
*/
if (lcb.prot_level == 2)
	{
	if (retcode = attn_process())
		return(retcode);
	}

/* Go see if it's time to send an ack. 
*/
if (retcode = acking())
	return(retcode);

/* Try to free up any transmit buffers which have been acked. 
*/
tb_free();

/* Go see if we have to retransmit. 
*/
if (retcode = retran_lt())
	return(retcode);

/* Make sure link is still up one more time 
*/
if (!BIT1SET(LINK_EST))
	return(LNK_DOWN);

/* Exit 
*/
return(SUCCESS);
}

/*LOCAL------------------------------------------------------------------------

	acking - send an LA LPDU if an ack condition is present

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

SIGN_16 acking()
{

SIGN_16 retcode,				/* return code */
    lt_unacked; 				/* number of unacked LTs */

/* If the force ack flag is set, send an LA right away.
*/
clr_int();					/* protect flag access */
if (BIT2SET(FORCE_ACK))			/* reset flag if set */
	{
	CLRBIT2(FORCE_ACK)
	set_int();
	return(send_la());			/* send LA and return */
	}
set_int();

/* If the window timer is enabled and has expired, send an LA. 
*/
if (BIT2SET(WNDW_TIMER) && (fcw_tm == 0))
	return(send_la());

/* If there are unacknowledged LT's, it may be time to send an LA. 
*/
if (lt_unacked = lcb.lt_rsn - lcb.ltrsn_acked)
	{

/* If there is no user data to send (i.e. no reason to put it off)
** send an LA.
*/
	if (sb_cnt == 0)
		return(send_la());

/* If the acknowledgment threshold has been reached, send an LA.
*/
	if (lt_unacked >= lcb.ack_threshold)
		return(send_la());

/* If the ack timer has elapsed, send an LA.  Otherwise, set the timer.
*/
	if (BIT1SET(ACK_TIMER))
		{
		if (ack_tm)
			return(SUCCESS);
		else
			return(send_la());
		}
	else
		{
		SETBIT1(ACK_TIMER)
		ack_tm = lcb.ack_timer;
		return(SUCCESS);
		}
	}

/* If there are no unacknowledged LT's, handle the 'zero window
** opening' case.
*/
else
	{
	if (BIT2SET(ZERO_WNDW) && credit_chk())
		{
		CLRBIT2(ZERO_WNDW)
		return(send_la());
		}
	}

/* Exit 
*/
return(SUCCESS);
}

/*LOCAL------------------------------------------------------------------------

	attn_process - handle break signalling

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

attn_process()
{

SIGN_16 retcode;

/* If the LN timer is set and has expired, it is time to retransmit the
** last LN LPDU sent.  However, if the retransmission limit has been
** reached, then the link is unusable.  Terminate the link and return
** with a function value=retran limit reached.
*/
if (BIT3SET(LN_TIMER) && (ln_tm == 0))
	{
	if (lcb.ln_ret_cnt == RET_LIMIT)
		{
		as_disconnect(RETRAN_TMR_EXP,NULL);
		return(-67);
		}
	if (retcode = lpdu_send(LN,NOWAIT))
		return(retcode);
	++lcb.ln_ret_cnt;
	SETBIT3(LN_SENT)

	clr_int();
	SETBIT3(LN_TIMER)
	ln_tm=lcb.lt_tmr;
	set_int();
	}

/* If an LN has been received, check its type for a destructive break
** signal.  Reset the link on receipt of a destructive break.
*/
clr_int();
if (BIT3SET(LN_RECEIVED))
	{
	CLRBIT3(LN_RECEIVED)			
	if (lcb.ln_rtype == 1)
		{
		link_reset();
		dphase_init();
		}
	set_int();
	if (retcode = lpdu_send(LNA,NOWAIT))
		return(retcode);
	}
set_int();

/* Check for need to send an LNA
*/
if (BIT3SET(FORCE_LNA))
	{
	CLRBIT3(FORCE_LNA)
	if (retcode = lpdu_send(LNA,NOWAIT))
		return(retcode);
	}

/* Exit 
*/
return(SUCCESS);
}

/*LOCAL------------------------------------------------------------------------

	credit_chk - determine local ability to receive

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

SIGN_16 credit_chk()
{

extern USIGN_16 rb_cnt;

/* Compute the number of LT LPDUs which can be received.  This is
** the number of max sized LT's which will fit into the receive
** ring buffer.  This number can not be larger than maximum window
** (8 for this implementation).
*/
lcb.lcl_credit = (RBUF_LEN - rb_cnt) / lcb.max_data_sz;
if (lcb.lcl_credit > lcb.window_sz)
	lcb.lcl_credit = lcb.window_sz;

/* Exit.  Function value is receive credit. 
*/
return(lcb.lcl_credit);
}

/*LOCAL------------------------------------------------------------------------

	dphase_init - perform data phase initialization

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

dphase_init()
{

SIGN_16 i;

/* Set initial credits equal to negotiated maximum credit. 
*/
lcb.lcl_credit = lcb.rem_credit = lcb.window_sz;

/* Compute ack threshold 
*/
lcb.ack_threshold = (i = lcb.window_sz / 2) ? i : 1;

/* Be sure that ack conditions are reset. 
*/
CLRBIT1(LA_RECEIVED)
CLRBIT2(FORCE_ACK)

/* If window == 1, lt retran timer is specified to be 8 seconds
*/
if (lcb.window_sz == 1)
	lcb.lt_tmr = 8;
else
	{
	SETBIT2(WNDW_TIMER)
	fcw_tm = lcb.window_tmr;
	}
}

/*LOCAL------------------------------------------------------------------------

	link_init - perform one-time link initialization

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

link_init(mnpcb)

register struct MNP_CB *mnpcb;
{

/* Initialize link control block values 
*/
lcb.status_1 = lcb.status_2 = lcb.status_3 = NULL;

ftb.num = lcb.window_sz = STRM_WNDW_SZ;
lcb.max_data_sz = STRM_DATA_SZ;

lcb.prot_level = 2;
lcb.srv_class = LCL_SCLASS;

lcb.ln_rsn = lcb.ln_ssn = lcb.ln_ret_cnt = ln_tm = NULL;

switch (lcb.baud_rate = baudrate)
	{
	case B_1200:
		lcb.lt_tmr = LTTMR_12;
		lcb.window_tmr = W_TMR_12;
		break;

	case B_300:
		lcb.lt_tmr = LTTMR_3;
		lcb.window_tmr = W_TMR_3;
		break;

	case B_110:
		lcb.lt_tmr = LTTMR_110;
		lcb.window_tmr = W_TMR_110;
		break;

	case B_2400:
	default:
		lcb.lt_tmr = LTTMR_24;
		lcb.window_tmr = W_TMR_24;
		break;
	}

lcb.ack_timer = (lcb.lt_tmr/2)+1;

/* Initialize receive and transmit buffers 
*/
rlkb.list = rlkblst;
rlkb.num = 2;
lkb.list = lkblst;
lkb.num = 2;

init_blst(mnpcb->rlkb = &rlkb, MAX_LPDU_SZ, rlkbuff);
init_blst(mnpcb->lkb = &lkb, MAX_LPDU_SZ, lkbuff);

ftb.list = iatblst;
init_blst(mnpcb->ftb = &ftb,64+5, iatbuff);

/* Initialize async driver variables, too 
*/
p_mnpcb = mnpcb;
timerins();
drvr_ins();

}

/*LOCAL------------------------------------------------------------------------

	link_reset - 

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

link_reset()
{

/* Disable interrupts while reseting the link.
*/
clr_int();

/* Reset lcb values - note that attention sequence numbers are not
** reintialized.
*/
lcb.lt_rsn = lcb.lt_ssn = lcb.ltrsn_acked = lcb.ltssn_acked = NULL;
lcb.lt_ret_cnt = lcb.lpdu_type = NULL;

lcb.status_1 &= ~(DATA_READY | ACK_TIMER | RET_TIMER);
lcb.status_2 &= ~(FORCE_ACK | FORCE_RET | ZERO_WNDW | WNDW_TIMER);
lcb.status_3 &= ~(DUP_IGNORED);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -