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

📄 mnpllvl.c

📁 汇编源代码大全2
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Reset_timers 
*/
ack_tm = fcw_tm = lr_tm = lt_tm  = NULL;

/* Reset send and receive framers 
*/
sf_busy = sf_lt = modem_out_busy = NULL;
rdle_flg = frame_snt = frame_rcvd = frame_dne =NULL;
sf_state = SF_INIT;
rf_state = RF_INIT;

/* Reset transmit and receive buffers 
*/
reset_blst(&rb);
reset_blst(&ftb);
reset_blst(&lkb);
reset_blst(&rlkb);

tbcnt = 0;

p_mnpcb->ld_reason = NULL;

/* Re-enable interrupts.
*/
set_int();

}

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

	lpdu_send - send an LPDU other than an LT

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

SIGN_16 lpdu_send(type,wait)

SIGN_16 type,
	wait;
{

SIGN_16 retcode; 				/* return code */
struct BLST *snd_struct;			/* LPDU structure */

/* Get a buffer for the LPDU, send the LPDU, then release buffer. 
*/
get_b(&lkb,&snd_struct);
retcode = send_pdu(type,wait,snd_struct);
ret_b(&lkb,snd_struct);

/* Exit 
*/
return(retcode);
}

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

	parse_lr - parse an LR LPDU and perform parameter negotiation

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

SIGN_16 parse_lr()

{

register USIGN_8 *p;			/* header pointer */
register USIGN_16 len,
			*pi;

/* Initialize 
*/
lcb.lr_parm = 0;
p = (rlkb.used_lst)->bptr;
len = *p++ - 2;

/* Process fixed fields 
*/
if (*p++ != LR)
	{
	ret_b(&rlkb,rlkb.used_lst);
	return(PROT_ERR);
	}

lcb.prot_level = min(lcb.prot_level,*p);
p++;

/* Process variable part 
*/
while (len > 0)
	{
	if (*p == 1)			/* skip parm 1 - serial no. */
		{
		len -= 8;
		p += 8;
		continue;
		}

	if (*p == 2)			/* take min of service class values */
		{
		len -= 3;
		p += 2;
		lcb.lr_parm |= LR_SRV_CLASS;
		lcb.srv_class = min(LCL_SCLASS, *p);
		p++;
		if (lcb.srv_class == 1)
			SETBIT1(HDUPLEX)
		continue;
		}

	if (*p == 3)			/* take min of window size */
		{
		len -= 3;
		p += 2;
		lcb.lr_parm |= LR_WNDW_SZ;
		lcb.window_sz = min (lcb.window_sz, *p);
		p++;
		continue;
		}

	if (*p == 4)
		{
		len -= 4;
		pi = (SIGN_16 *) (p += 2);
		lcb.lr_parm |= LR_DATA_SZ;
		lcb.max_data_sz = max (lcb.max_data_sz, *pi);
		p += 2;
		continue;
		}

	if (*p > 4)			/* ignore anything else */
		{
		len -= *++p + 2;
		p += *p++;
		break;
		}
	}

/* All done with LR in buffer, return the buffer 
*/
ret_b(&rlkb,rlkb.used_lst);

/* Now check for parms not received and set default values 
*/
if (!(lcb.lr_parm & LR_SRV_CLASS))
	lcb.srv_class = 1;

if (!(lcb.lr_parm & LR_WNDW_SZ))
	lcb.window_sz = 1;

if (!(lcb.lr_parm & LR_DATA_SZ))
	lcb.max_data_sz = BLK_DATA_SZ;

/* There is such a thing as a block-mode MNP link-connection, but
** this implementation will not talk to one (block mode links are
** for use with higher-level MNP protocols). 
*/
if (lcb.max_data_sz == BLK_DATA_SZ)
	return(BAD_LR_PARMS);

/* Adjust the credit for any receive buffers already used.
*/
lcb.lcl_credit = lcb.window_sz - rb.used;

/* Exit 
*/
return(SUCCESS);
}

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

	receive_wait -  wait for an LPDU during link establishment

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

SIGN_16 receive_wait ()
{

/* Wait for an LPDU to be received or 2 seconds to go by, which ever
** occurs first.
*/
clr_int();
return(event_wait(20,FRAME_RCV));

}

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

	retran_lt - handle LT LPDU retransmission

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

SIGN_16 retran_lt()
{

SIGN_16 i,
	retcode,
	not_done;
register USIGN_16 lts_unacked;
register struct BLST *snd_struct;

not_done = 1;
while (not_done)
	{

/* If there are no buffers in use, there is nothing to retransmit. 
*/
	if (ftb.used == 0)
		{
		CLRBIT2(FORCE_RET)			/* reset force flag */
		return(SUCCESS);			/* and just exit */
		}

/* Check for forced retransmission.  If so, clear flag and go right at
** it.  Otherwise, retransmit only when retran timer set and expired.
*/
	clr_int();
	if (BIT2SET(FORCE_RET))
		{
		CLRBIT2(FORCE_RET)
		set_int();
		}
	else
		{
		set_int();
		if (!BIT1SET(RET_TIMER))
	    		return(SUCCESS);
	if (lt_tm)
		return (SUCCESS);
	}

/* It's time to retransmit. But if we have retransmitted to the limit
** count, terminate the link.
*/
	if (lcb.lt_ret_cnt == RET_LIMIT)
		{
		as_disconnect(RETRAN_TMR_EXP,NULL);
		return(FAILURE);
		}

/* It's OK to still retransmit if there is remote credit (no need to
** check when window is only 1).
*/
	if (lcb.window_sz == 1)
		lcb.rem_credit = 0;
	else
		if (lcb.rem_credit == 0)
			return(SUCCESS);

/* Retransmit ALL unacknowledged LT's.
*/
	snd_struct = ftb.used_lst;
	not_done--;

	if (lcb.lt_ssn >= lcb.ltssn_acked)
		lts_unacked = lcb.lt_ssn - lcb.ltssn_acked;
	else
		lts_unacked = (256 - lcb.ltssn_acked) + lcb.lt_ssn;

	while (lts_unacked)
		{
		lts_unacked--;
		if (retcode = send_pdu(LT,NOWAIT,snd_struct))
			return(retcode);

		if (lcb.window_sz == 1) 
			event_wait(100,FRAME_SND);

		if (retcode = acking())
			return(retcode);
		if (lcb.prot_level == 2)
			{
	    		if (retcode = attn_process())
				return(retcode);
			}

		snd_struct = snd_struct->next_b;

/* If forced retransmission, i.e., LA received, we may have received
** another LA acknowledging frames that we would retransmit next.  If
** this happened, free up acked transmit buffer(s), then go back to
** beginning.  note: if there are buffers in use, say 3 & 4, & if after
** 3 & 4 are retransmitted, we receive an LA for 3, then this logic will
** retransmit 4 again. The last 4 will be ignored by receiver as an 
** immediate duplicate.
*/
		if (BIT2SET(FORCE_RET) || BIT1SET(LA_RECEIVED))
			{
			i = ftb.used;
			tb_free();
			if (i != ftb.used)
				{
/* Something has been freed.  If all buffers were freed, then we're
** all done.  If not, reset flags and do it over again.
*/
		    		if (ftb.used)
					{
					SETBIT2(FORCE_RET)
					not_done++;
					break;
					}
		    		}
			}
		}

	if (!not_done)
		{
		lcb.lt_ret_cnt++;
		lt_tm = lcb.lt_tmr;
		}
	}
	return(SUCCESS);
}

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

	send_la - send an LA LPDU

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

SIGN_16 send_la()
{

SIGN_16 retcode;

/* Check for a zero window.  We want to remember sending a zero credit.
** We don't send zero credit, however, when the window is one. 
*/
if (!credit_chk())
	{
	SETBIT2(ZERO_WNDW)
	if (lcb.window_sz == 1)
		return(SUCCESS);
	}

/* Send an LA LPDU.  Return if link-connection is lost. 
*/
if (retcode = lpdu_send(LA,NOWAIT))
	return(retcode);

/* Reset ack and flow control timers. 
*/
clr_int();
CLRBIT1(ACK_TIMER)
ack_tm = NULL;
fcw_tm = lcb.window_tmr;
set_int();

/* Exit 
*/
return(SUCCESS);
}

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

	send_pdu - send an LPDU

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

SIGN_16 send_pdu(type,wait,snd_struct)

SIGN_16 type,					/* LPDU type */
    wait;						/* wait for send to complete */
register struct BLST *snd_struct;
{

register USIGN_8 *p;
USIGN_8 *pli;
USIGN_16 *pi;
SIGN_16 i;

/* Just return if there is no physical connection. 
*/
if (lne_stat())
	return(NO_PHYSICAL);

/* If the lpdu is an LD, then we want to expedite it.  If an lpdu is being
** sent, wait a bit then truncate it.  This wait is necessary so that an
** empty frame (which is illegal) is not sent. 
*/
if (type == LD && sf_busy)
	{
	switch (lcb.baud_rate)
		{	
		case B_1200:
			i = 10;
			break;

		case B_300:
			i = 20;
			break;

		case B_110:
			i = 30;
			break;

		default:
			i = 5;
		}

	suspend(i);
	sf_len = 0;
    
	while (sf_busy)
		;
	}

/* Wait for the send framer to finish if a frame is in progress.  
*/
clr_int();
while (sf_busy)
	if (send_wait())
		return(TIME_OUT);

/* Now prepare the requested LPDU.
*/
p = snd_struct->bptr;

switch (type)
	{
	case LT:
		break;

	case LA:
		*p++ = LA_LEN;
		*p++ = LA;
		*p++ = 1;
		*p++ = 1;
		clr_int();
		*p++ = lcb.ltrsn_acked = lcb.lt_rsn;
		*p++ = 2;
		*p++ = 1;
		*p  = (USIGN_8) credit_chk();
		set_int();
		break;

	case LN:
		*p++ = LN_LEN;
		*p++ = LN;
		*p++ = 1;
		*p++ = 1;
		*p++ = lcb.ln_ssn;
		*p++ = 2;
		*p++ = 1;
		*p = lcb.ln_stype;
		break;

	case LNA:
		*p++ = LNA_LEN;
		*p++ = LNA;
		*p++ = 1;
		*p++ = 1;
		*p = lcb.ln_rsn;
		break;

	case LR:
		pli = p++;
		*p++ = LR;
		*p++ = lcb.prot_level;
		*p++ = 1;
		*p++ = 6;
		*p++ = 1;
		*p++ = 0;
		*p++ = 0;
		*p++ = 0;
		*p++ = 0;
		*p++ = 255;
		if (BIT1SET(MODE))
			{
	    		*pli = LR_ALEN;
			if (lcb.lr_parm & LR_SRV_CLASS)
				{
				*p++ = 2;
				*p++ = 1;
				*p++ = lcb.srv_class;
				*pli += 3;
				
				if (lcb.lr_parm & LR_WNDW_SZ)
					{
		    			*p++ = 3;
		    			*p++ = 1;
		    			*p++ = lcb.window_sz;
		    			*pli += 3;
		    
					if (lcb.lr_parm & LR_DATA_SZ)
						{
						*p++ = 4;
						*p++ = 2;
						pi = (USIGN_16 *) p;
						*pi = lcb.max_data_sz;
						*pli += 4;
						}
		    			}
				}
	    		}
		else
			{
			*pli = LR_ILEN;
			*p++ = 2;
			*p++ = 1;
			*p++ = LCL_SCLASS;
			*p++ = 3;
			*p++ = 1;
			*p++ = lcb.window_sz;
			*p++ = 4;
			*p++ = 2;
			pi = (USIGN_16 *) p;
			*pi = lcb.max_data_sz;
			}
		break;

	case LD:
		*p++ = LD_LEN;
		*p++ = LD;
		*p++ = 1;
		*p++ = 1;
		if ((*p = lcb.l_disc_code) == 255)
			{
			p++;
	    		*p++ = 2;
	    		*p++ = 1;
	    		*p = lcb.u_disc_code;
	    		*(snd_struct->bptr) += 3;
	    		}
		break;
	}

/* Pause a bit if this is a class 1 connection (hardly likely...)
*/
if (BIT1SET(HDUPLEX))
	suspend (20);

/* Set up the interrupt-driven send framer to send the lpdu.
*/
clr_int();
if (type == LT)
	sf_len = snd_struct->len;
else
	sf_len = *(snd_struct->bptr) + 1;

sf_ptr = snd_struct->bptr;
sf_busy = 1;
trigger_sf();
set_int();

/* Wait for the lpdu to get out, if that was what the caller wanted.
*/
if (wait)
	if (send_wait()) 
		return(TIME_OUT);

/* Exit
*/
return(SUCCESS);
}

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

	send_wait - wait for transmission of an LPDU or timeout

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

SIGN_16 send_wait()
{

/* Wait 55 seconds (arbitrary number which is larger than the time
** needed to send a long LPDU), or until the LPDU is sent. If the time
** expires and frame send has not completed, return time out.  This
** means, effectively, that the hardware is broken.
*/
clr_int();
return(event_wait(550,FRAME_SND));

}

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

	tb_free - process acknowledged LT LPDUs

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

tb_free()
{

register struct BLST *bp;
register USIGN_16 acked_lts;	    /* to hold value between 0 and 65535 */
register USIGN_16 head_ssn;

/* If there are no LT LPDUs unacknowledged, just clear force retransmission
** flag and return. 
*/
if (!tbcnt)
	{
	CLRBIT2(FORCE_RET)
	return;
	}

/* Some LT LPDU's have been sent.  However, only try to free up transmit
** buffers if an LA has been received. 
*/
clr_int();
if (BIT1SET(LA_RECEIVED))	
	{
	CLRBIT1(LA_RECEIVED)
	set_int();

/* Start freeing at the head of the list of buffers in use.  Free until
** the buffer just freed contains the LT with the same seq number as
** that of the last LT positively acked 
*/
	bp = ftb.used_lst;

	head_ssn = (USIGN_8)*(bp->bptr + LT_SEQ);

	if (head_ssn <= lcb.ltssn_acked)
		acked_lts = lcb.ltssn_acked - head_ssn +1;
	else
		acked_lts = (256 - head_ssn) + lcb.ltssn_acked + 1;

	while (acked_lts)
		{
		ret_b(&ftb,bp);
		bp = bp->next_b;
		acked_lts--;
		tbcnt--;
		}
	if (tbcnt < 0)
		tbcnt=0;

/* Clear force retransmission flag 
*/
	CLRBIT2(FORCE_RET)

/* If any LTs remain outstanding, reset the retransmission timer for them.
** Otherwise, be sure that the timer is cancelled. Since something has been
** acknowledged, the retransmission count can also be reset to 0. 
*/
	if (tbcnt)
		{
		SETBIT1(RET_TIMER)
		lt_tm = lcb.lt_tmr;
		ftb.used_lst = bp;
		}
	else
		{
		CLRBIT1(RET_TIMER)
		lt_tm = 0;
		}
	lcb.lt_ret_cnt = 0;
	}
else
	{
	set_int();
    	}
}


⌨️ 快捷键说明

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