]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netccitt/hd_output.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) University of British Columbia, 1984
24 * Copyright (c) 1990, 1993
25 * The Regents of the University of California. All rights reserved.
27 * This code is derived from software contributed to Berkeley by
28 * the Laboratory for Computation Vision and the Computer Science Department
29 * of the University of British Columbia.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * @(#)hd_output.c 8.1 (Berkeley) 6/10/93
62 #include <sys/param.h>
63 #include <sys/systm.h>
65 #include <sys/domain.h>
66 #include <sys/socket.h>
67 #include <sys/syslog.h>
68 #include <sys/protosw.h>
69 #include <sys/errno.h>
71 #include <sys/kernel.h>
75 #include <netccitt/hdlc.h>
76 #include <netccitt/hd_var.h>
77 #include <netccitt/x25.h>
80 * HDLC OUTPUT INTERFACE
82 * This routine is called when the X.25 packet layer output routine
83 * has a information frame (iframe) to write. It is also called
84 * by the input and control routines of the HDLC layer.
88 register struct hdcb
*hdp
;
91 struct x25config
*xcp
;
92 register struct mbuf
*m
= m0
;
97 if ((m
->m_flags
& M_PKTHDR
) == 0)
98 panic ("hd_output 2");
100 if (hdp
->hd_state
!= ABM
) {
106 * Make room for the hdlc header either by prepending
107 * another mbuf, or by adjusting the offset and length
108 * of the first mbuf in the mbuf chain.
111 M_PREPEND(m
, HDHEADERLN
, M_DONTWAIT
);
114 for (len
= 0; m
; m
= m
->m_next
)
117 m
->m_pkthdr
.len
= len
;
119 hd_append (&hdp
->hd_txq
, m
);
124 register struct hdcb
*hdp
;
126 register struct mbuf
*m
;
129 * The iframe is only transmitted if all these conditions are FALSE.
130 * The iframe remains queued (hdp->hd_txq) however and will be
131 * transmitted as soon as these conditions are cleared.
134 while (!(hdp
->hd_condition
& (TIMER_RECOVERY_CONDITION
| REMOTE_RNR_CONDITION
| REJ_CONDITION
))) {
135 if (hdp
->hd_vs
== (hdp
->hd_lastrxnr
+ hdp
->hd_xcp
->xc_lwsize
) % MODULUS
) {
137 /* We have now exceeded the maximum number of
138 outstanding iframes. Therefore, we must wait
139 until at least one is acknowledged if this
140 condition is not turned off before we are
141 requested to write another iframe. */
142 hdp
->hd_window_condition
++;
146 /* hd_remove top iframe from transmit queue. */
147 if ((m
= hd_remove (&hdp
->hd_txq
)) == NULL
)
150 hd_send_iframe (hdp
, m
, POLLOFF
);
155 * This procedure is passed a buffer descriptor for an iframe. It builds
156 * the rest of the control part of the frame and then writes it out. It
157 * also starts the acknowledgement timer and keeps the iframe in the
158 * Retransmit queue (Retxq) just in case we have to do this again.
160 * Note: This routine is also called from hd_input.c when retransmission
161 * of old frames is required.
164 hd_send_iframe (hdp
, buf
, poll_bit
)
165 register struct hdcb
*hdp
;
166 register struct mbuf
*buf
;
169 register struct Hdlc_iframe
*iframe
;
175 printf ("hd_send_iframe: zero arg\n");
180 hdp
->hd_vs
= (hdp
->hd_vs
+ 7) % MODULUS
;
183 iframe
= mtod (buf
, struct Hdlc_iframe
*);
185 iframe
-> hdlc_0
= 0;
186 iframe
-> nr
= hdp
->hd_vr
;
187 iframe
-> pf
= poll_bit
;
188 iframe
-> ns
= hdp
->hd_vs
;
189 iframe
-> address
= ADDRESS_B
;
190 hdp
->hd_lasttxnr
= hdp
->hd_vr
;
193 if (hdp
->hd_vs
== hdp
->hd_retxqi
) {
194 /* Check for retransmissions. */
195 /* Put iframe only once in the Retransmission queue. */
196 hdp
->hd_retxq
[hdp
->hd_retxqi
] = buf
;
197 hdp
->hd_retxqi
= (hdp
->hd_retxqi
+ 1) % MODULUS
;
198 hdp
->hd_iframes_out
++;
201 hdp
->hd_vs
= (hdp
->hd_vs
+ 1) % MODULUS
;
203 hd_trace (hdp
, TX
, (struct Hdlc_frame
*)iframe
);
205 /* Write buffer on device. */
206 m
= hdp
->hd_dontcopy
? buf
: m_copy(buf
, 0, (int)M_COPYALL
);
208 printf("hdlc: out of mbufs\n");
211 (*hdp
->hd_output
)(hdp
, m
);
216 register struct mbuf
*m
;
217 register struct hdcb
*hdp
;
220 * Queue message on interface, and start output if interface
223 register struct ifnet
*ifp
= hdp
->hd_ifp
;
226 if (IF_QFULL(&ifp
->if_snd
)) {
227 IF_DROP(&ifp
->if_snd
);
228 /* printf("%s%d: HDLC says OK to send but queue full, may hang\n",
229 ifp->if_name, ifp->if_unit);*/
232 IF_ENQUEUE(&ifp
->if_snd
, m
);
233 if ((ifp
->if_flags
& IFF_OACTIVE
) == 0)
234 (*ifp
->if_start
)(ifp
);
241 * This routine gets control when the timer expires because we have not
242 * received an acknowledgement for a iframe.
245 hd_resend_iframe (hdp
)
246 register struct hdcb
*hdp
;
249 if (hdp
->hd_retxcnt
++ < hd_n2
) {
250 if (!(hdp
->hd_condition
& TIMER_RECOVERY_CONDITION
)) {
251 hdp
->hd_xx
= hdp
->hd_vs
;
252 hdp
->hd_condition
|= TIMER_RECOVERY_CONDITION
;
255 hdp
->hd_vs
= hdp
->hd_lastrxnr
;
256 hd_send_iframe (hdp
, hdp
->hd_retxq
[hdp
->hd_vs
], POLLON
);
258 /* At this point we have not received a RR even after N2
259 retries - attempt to reset link. */
262 hd_writeinternal (hdp
, SABM
, POLLOFF
);
263 hdp
->hd_state
= WAIT_UA
;
265 hd_message (hdp
, "Timer recovery failed: link down");
266 (void) pk_ctlinput (PRC_LINKDOWN
, hdp
->hd_pkp
);