xref: /csrg-svn/sys/netccitt/pk_output.c (revision 41709)
1*41709Ssklower /*
2*41709Ssklower  * Copyright (c) University of British Columbia, 1984
3*41709Ssklower  * Copyright (c) 1990 The Regents of the University of California.
4*41709Ssklower  * All rights reserved.
5*41709Ssklower  *
6*41709Ssklower  * This code is derived from software contributed to Berkeley by
7*41709Ssklower  * the Laboratory for Computation Vision and the Computer Science Department
8*41709Ssklower  * of the University of British Columbia.
9*41709Ssklower  *
10*41709Ssklower  * %sccs.include.redist.c%
11*41709Ssklower  *
12*41709Ssklower  *	@(#)pk_output.c	7.2 (Berkeley) 05/11/90
13*41709Ssklower  */
1441592Ssklower 
1541592Ssklower #include "../h/param.h"
1641592Ssklower #include "../h/systm.h"
1741592Ssklower #include "../h/mbuf.h"
1841592Ssklower #include "../h/socket.h"
1941592Ssklower #include "../h/socketvar.h"
2041592Ssklower #include "../h/protosw.h"
2141592Ssklower #include "../h/errno.h"
2241592Ssklower 
2341592Ssklower #include "../net/if.h"
2441592Ssklower 
2541592Ssklower #include "../netccitt/pk.h"
2641592Ssklower #include "../netccitt/pk_var.h"
2741592Ssklower #include "../netccitt/x25.h"
2841592Ssklower 
2941592Ssklower struct	mbuf *nextpk ();
3041592Ssklower 
3141592Ssklower pk_output (lcp)
3241592Ssklower register struct pklcd *lcp;
3341592Ssklower {
3441592Ssklower 	register struct x25_packet *xp;
3541592Ssklower 	register struct mbuf *m;
3641592Ssklower 	register struct pkcb *pkp = lcp -> lcd_pkp;
3741592Ssklower 
3841592Ssklower 	if (lcp == 0 || pkp == 0) {
3941592Ssklower 		printf ("pk_output: zero arg\n");
4041592Ssklower 		return;
4141592Ssklower 	}
4241592Ssklower 
4341592Ssklower 	while ((m = nextpk (lcp)) != NULL) {
4441592Ssklower 		xp = mtod (m, struct x25_packet *);
4541592Ssklower 
4641592Ssklower 		switch (pk_decode (xp) + lcp -> lcd_state) {
4741592Ssklower 		/*
4841592Ssklower 		 *  All the work is already done - just set the state and
4941592Ssklower 		 *  pass to peer.
5041592Ssklower 		 */
5141592Ssklower 		case CALL + READY:
5241592Ssklower 			lcp -> lcd_state = SENT_CALL;
5341592Ssklower 			lcp -> lcd_timer = pk_t21;
5441592Ssklower 			break;
5541592Ssklower 
5641592Ssklower 		/*
5741592Ssklower 		 *  Just set the state to allow packet to flow and send the
5841592Ssklower 		 *  confirmation.
5941592Ssklower 		 */
6041592Ssklower 		case CALL_ACCEPTED + RECEIVED_CALL:
6141592Ssklower 			lcp -> lcd_state = DATA_TRANSFER;
6241592Ssklower 			break;
6341592Ssklower 
6441592Ssklower 		/*
6541592Ssklower 		 *  Just set the state. Keep the LCD around till the clear
6641592Ssklower 		 *  confirmation is returned.
6741592Ssklower 		 */
6841592Ssklower 		case CLEAR + RECEIVED_CALL:
6941592Ssklower 		case CLEAR + SENT_CALL:
7041592Ssklower 		case CLEAR + DATA_TRANSFER:
7141592Ssklower 			lcp -> lcd_state = SENT_CLEAR;
7241592Ssklower 			lcp -> lcd_retry = 0;
7341592Ssklower 			/* fall through */
7441592Ssklower 
7541592Ssklower 		case CLEAR + SENT_CLEAR:
7641592Ssklower 			lcp -> lcd_timer = pk_t23;
7741592Ssklower 			lcp -> lcd_retry++;
7841592Ssklower 			break;
7941592Ssklower 
8041592Ssklower 		case CLEAR_CONF + RECEIVED_CLEAR:
8141592Ssklower 		case CLEAR_CONF + SENT_CLEAR:
8241592Ssklower 		case CLEAR_CONF + READY:
8341592Ssklower 			lcp -> lcd_state = READY;
8441592Ssklower 			break;
8541592Ssklower 
8641592Ssklower 		case DATA + DATA_TRANSFER:
8741592Ssklower 			PS(xp) = lcp -> lcd_ssn;
8841592Ssklower 			PR(xp) = lcp -> lcd_input_window;
8941592Ssklower 			lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window;
9041592Ssklower 			lcp -> lcd_ssn = (lcp -> lcd_ssn + 1) % MODULUS;
9141592Ssklower 			if (lcp -> lcd_ssn == ((lcp -> lcd_output_window + pkp->pk_xcp->xc_pwsize) % MODULUS))
9241592Ssklower 				lcp -> lcd_window_condition = TRUE;
9341592Ssklower 			break;
9441592Ssklower 
9541592Ssklower 		case INTERRUPT + DATA_TRANSFER:
9641592Ssklower 			xp -> packet_data = 0;
9741592Ssklower 			lcp -> lcd_intrconf_pending = TRUE;
9841592Ssklower 			break;
9941592Ssklower 
10041592Ssklower 		case INTERRUPT_CONF + DATA_TRANSFER:
10141592Ssklower 			break;
10241592Ssklower 
10341592Ssklower 		case RR + DATA_TRANSFER:
10441592Ssklower 			lcp -> lcd_input_window = (lcp -> lcd_input_window + 1) % MODULUS;
10541592Ssklower 			PR(xp) = lcp -> lcd_input_window;
10641592Ssklower 			lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window;
10741592Ssklower 			break;
10841592Ssklower 
10941592Ssklower 		case RNR + DATA_TRANSFER:
11041592Ssklower 			PR(xp) = lcp -> lcd_input_window;
11141592Ssklower 			lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window;
11241592Ssklower 			break;
11341592Ssklower 
11441592Ssklower 		case RESET + DATA_TRANSFER:
11541592Ssklower 			lcp -> lcd_reset_condition = TRUE;
11641592Ssklower 			break;
11741592Ssklower 
11841592Ssklower 		case RESET_CONF + DATA_TRANSFER:
11941592Ssklower 			lcp -> lcd_reset_condition = FALSE;
12041592Ssklower 			break;
12141592Ssklower 
12241592Ssklower 		/*
12341592Ssklower 		 *  A restart should be only generated internally. Therefore
12441592Ssklower 		 *  all logic for restart is in the pk_restart routine.
12541592Ssklower 		 */
12641592Ssklower 		case RESTART + READY:
12741592Ssklower 			lcp -> lcd_timer = pk_t20;
12841592Ssklower 			break;
12941592Ssklower 
13041592Ssklower 		/*
13141592Ssklower 		 *  Restarts are all  handled internally.  Therefore all the
13241592Ssklower 		 *  logic for the incoming restart packet is handled in  the
13341592Ssklower 		 *  pk_input routine.
13441592Ssklower 		 */
13541592Ssklower 		case RESTART_CONF + READY:
13641592Ssklower 			break;
13741592Ssklower 
13841592Ssklower 		default:
13941592Ssklower 			m_freem (m);
14041592Ssklower 			return;
14141592Ssklower 		}
14241592Ssklower 
14341592Ssklower 		/* Trace the packet. */
14441592Ssklower 		pk_trace (pkp -> pk_xcp, xp, "P-Out");
14541592Ssklower 
14641592Ssklower 		/* Pass the packet on down to the link layer */
14741592Ssklower 		(*pkp -> pk_output) (m, pkp -> pk_xcp);
14841592Ssklower 	}
14941592Ssklower }
15041592Ssklower 
15141592Ssklower /*
15241592Ssklower  *  This procedure returns the next packet to send or null. A
15341592Ssklower  *  packet is composed of one or more mbufs.
15441592Ssklower  */
15541592Ssklower 
15641592Ssklower struct mbuf *
15741592Ssklower nextpk (lcp)
15841592Ssklower struct pklcd *lcp;
15941592Ssklower {
16041592Ssklower 	register struct socket *so = lcp -> lcd_so;
16141592Ssklower 	register struct mbuf *m = 0, *n;
16241592Ssklower 
16341592Ssklower 	if (lcp -> lcd_template) {
16441592Ssklower 		m = dtom (lcp -> lcd_template);
16541592Ssklower 		lcp -> lcd_template = NULL;
16641592Ssklower 	} else {
16741592Ssklower 		if (lcp -> lcd_rnr_condition || lcp -> lcd_window_condition ||
16841592Ssklower 				lcp -> lcd_reset_condition)
16941592Ssklower 			return (NULL);
17041592Ssklower 
17141592Ssklower 		if (so == 0)
17241592Ssklower 			return (NULL);
17341592Ssklower 
17441592Ssklower 		if ((m = so -> so_snd.sb_mb) == 0)
17541592Ssklower 			return (NULL);
17641592Ssklower 
17741592Ssklower 		n = m;
17841592Ssklower 		while (n) {
17941592Ssklower 			sbfree (&so -> so_snd, n);
18041592Ssklower #ifndef BSD4_3
18141592Ssklower 			if ((int) n -> m_act == 1)
18241592Ssklower 				break;
18341592Ssklower #endif
18441592Ssklower 			n = n -> m_next;
18541592Ssklower 		}
18641592Ssklower 
18741592Ssklower #ifdef BSD4_3
18841592Ssklower  		so->so_snd.sb_mb = m->m_act;
18941592Ssklower  		m->m_act = 0;
19041592Ssklower #else
19141592Ssklower 		if (n) {
19241592Ssklower 			so -> so_snd.sb_mb = n -> m_next;
19341592Ssklower 			n -> m_next = 0;
19441592Ssklower 		}
19541592Ssklower #endif
19641592Ssklower 	}
19741592Ssklower 
19841592Ssklower 	return (m);
19941592Ssklower }
200