]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/atp_misc.c
xnu-1228.15.4.tar.gz
[apple/xnu.git] / bsd / netat / atp_misc.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1996-1998 Apple Computer, Inc.
30 * All Rights Reserved.
31 */
32
33 /* Modified for MP, 1996 by Tuyen Nguyen
34 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
35 */
36 #include <sys/errno.h>
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <machine/spl.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/proc.h>
43 #include <sys/filedesc.h>
44 #include <sys/fcntl.h>
45 #include <sys/mbuf.h>
46 #include <sys/ioctl.h>
47 #include <sys/malloc.h>
48 #include <sys/socket.h>
49
50 #include <netat/sysglue.h>
51 #include <netat/appletalk.h>
52 #include <netat/ddp.h>
53 #include <netat/at_pcb.h>
54 #include <netat/atp.h>
55 #include <netat/asp.h>
56 #include <netat/debug.h>
57
58 extern struct atp_rcb_qhead atp_need_rel;
59 extern struct atp_trans *trp_tmo_rcb;
60
61 /*
62 * The request timer retries a request, if all retries are used up
63 * it returns a NAK
64 */
65
66 void
67 atp_req_timeout(trp)
68 register struct atp_trans *trp;
69 {
70 register gbuf_t *m;
71 gref_t *gref;
72 struct atp_state *atp;
73 struct atp_trans *ctrp;
74
75 if ((atp = trp->tr_queue) == 0)
76 return;
77 if (atp->atp_flags & ATP_CLOSING)
78 return;
79
80 for (ctrp = atp->atp_trans_wait.head; ctrp; ctrp = ctrp->tr_list.next) {
81 if (ctrp == trp)
82 break;
83 }
84 if (ctrp != trp)
85 return;
86
87 if ((m = gbuf_cont(trp->tr_xmt)) == NULL)
88 m = trp->tr_xmt; /* issued via the new interface */
89
90 if (trp->tr_retry == 0) {
91 trp->tr_state = TRANS_FAILED;
92 if (m == trp->tr_xmt) {
93 trp->tr_xmt = NULL;
94 l_notify:
95 gbuf_wset(m,1);
96 *gbuf_rptr(m) = 99;
97 gbuf_set_type(m, MSG_DATA);
98 gref = trp->tr_queue->atp_gref;
99 atalk_putnext(gref, m);
100
101 return;
102 }
103 dPrintf(D_M_ATP_LOW,D_L_INFO, ("atp_req_timeout: skt=%d\n",
104 trp->tr_local_socket));
105 m = trp->tr_xmt;
106 switch(((ioc_t *)(gbuf_rptr(trp->tr_xmt)))->ioc_cmd) {
107 case AT_ATP_ISSUE_REQUEST:
108 trp->tr_xmt = NULL;
109 if (trp->tr_queue->dflag)
110 ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_REQUEST_COMPLETE;
111 else if (trp->tr_bdsp == NULL) {
112 gbuf_freem(m);
113 if (trp->tr_rsp_wait)
114 wakeup(&trp->tr_event);
115 break;
116 }
117 atp_iocnak(trp->tr_queue, m, ETIMEDOUT);
118 atp_free(trp);
119 return;
120
121 case AT_ATP_ISSUE_REQUEST_NOTE:
122 case AT_ATP_ISSUE_REQUEST_TICKLE:
123 trp->tr_xmt = gbuf_cont(m);
124 gbuf_cont(m) = NULL;
125 goto l_notify;
126 }
127 } else {
128 (AT_ATP_HDR(m))->bitmap = trp->tr_bitmap;
129
130 if (trp->tr_retry != (unsigned int) ATP_INFINITE_RETRIES)
131 trp->tr_retry--;
132 atp_send(trp);
133 }
134 }
135
136
137 /*
138 * atp_free frees up a request, cleaning up the queues and freeing
139 * the request packet
140 * always called at 'lock'
141 */
142
143 void atp_free(trp)
144 register struct atp_trans *trp;
145 {
146 register struct atp_state *atp;
147 register int i;
148
149 dPrintf(D_M_ATP_LOW, D_L_TRACE,
150 ("atp_free: freeing trp 0x%x\n", (u_int) trp));
151
152
153 if (trp->tr_state == TRANS_ABORTING) {
154 ATP_Q_REMOVE(atp_trans_abort, trp, tr_list);
155 trp->tr_state = TRANS_DONE;
156 }
157 else {
158 if (trp->tr_tmo_func)
159 atp_untimout(atp_req_timeout, trp);
160
161 atp = trp->tr_queue;
162 ATP_Q_REMOVE(atp->atp_trans_wait, trp, tr_list);
163
164 if (trp->tr_xmt) {
165 gbuf_freem(trp->tr_xmt);
166 trp->tr_xmt = NULL;
167 }
168 for (i = 0; i < 8; i++) {
169 if (trp->tr_rcv[i]) {
170 gbuf_freem(trp->tr_rcv[i]);
171 trp->tr_rcv[i] = NULL;
172 }
173 }
174 if (trp->tr_bdsp) {
175 gbuf_freem(trp->tr_bdsp);
176 trp->tr_bdsp = NULL;
177 }
178
179 if (trp->tr_rsp_wait) {
180 trp->tr_state = TRANS_ABORTING;
181 ATP_Q_APPEND(atp_trans_abort, trp, tr_list);
182 wakeup(&trp->tr_event);
183 return;
184 }
185 }
186
187 atp_trans_free(trp);
188 } /* atp_free */
189
190
191 /*
192 * atp_send transmits a request packet by queuing it (if it isn't already) and
193 * scheduling the queue
194 */
195
196 void atp_send(trp)
197 register struct atp_trans *trp;
198 {
199 gbuf_t *m;
200 struct atp_state *atp;
201
202 dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ("atp_send: trp=0x%x, loc=%d\n",
203 (u_int) trp->tr_queue, trp->tr_local_socket));
204
205 if ((atp = trp->tr_queue) != 0) {
206 if (trp->tr_state == TRANS_TIMEOUT) {
207 if ((m = gbuf_cont(trp->tr_xmt)) == NULL)
208 m = trp->tr_xmt;
209
210 /*
211 * Now either release the transaction or start the timer
212 */
213 if (!trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo) {
214 m = (gbuf_t *)gbuf_copym(m);
215 atp_x_done(trp);
216 } else {
217 m = (gbuf_t *)gbuf_dupm(m);
218
219 atp_timout(atp_req_timeout, trp, trp->tr_timeout);
220 }
221
222 if (m) {
223 trace_mbufs(D_M_ATP_LOW, " m", m);
224 DDP_OUTPUT(m);
225 }
226 }
227 }
228 }
229
230
231 /*
232 * atp_reply sends all the available messages in the bitmap again
233 * by queueing us to the write service routine
234 */
235
236 void atp_reply(rcbp)
237 register struct atp_rcb *rcbp;
238 {
239 register struct atp_state *atp;
240 register int i;
241
242 if ((atp = rcbp->rc_queue) != 0) {
243 for (i = 0; i < rcbp->rc_pktcnt; i++) {
244 if (rcbp->rc_bitmap&atp_mask[i])
245 rcbp->rc_snd[i] = 1;
246 else
247 rcbp->rc_snd[i] = 0;
248 }
249 if (rcbp->rc_rep_waiting == 0) {
250 rcbp->rc_state = RCB_SENDING;
251 rcbp->rc_rep_waiting = 1;
252 atp_send_replies(atp, rcbp);
253 }
254 }
255 }
256
257
258 /*
259 * The rcb timer just frees the rcb, this happens when we missed a release for XO
260 */
261
262 void atp_rcb_timer(__unused struct atp_trans *junk)
263 {
264 register struct atp_rcb *rcbp;
265 register struct atp_rcb *next_rcbp;
266 struct timeval timenow;
267
268 l_again:
269 getmicrouptime(&timenow);
270 for (rcbp = atp_need_rel.head; rcbp; rcbp = next_rcbp) {
271 next_rcbp = rcbp->rc_tlist.next;
272
273 if ((timenow.tv_sec - rcbp->rc_timestamp) > 30) {
274 atp_rcb_free(rcbp);
275 goto l_again;
276 }
277 }
278 atp_timout(atp_rcb_timer, trp_tmo_rcb, 10 * HZ);
279 }
280
281 void atp_iocack(atp, m)
282 struct atp_state *atp;
283 register gbuf_t *m;
284 {
285 if (gbuf_type(m) == MSG_IOCTL)
286 gbuf_set_type(m, MSG_IOCACK);
287 if (gbuf_cont(m))
288 ((ioc_t *)gbuf_rptr(m))->ioc_count = gbuf_msgsize(gbuf_cont(m));
289 else
290 ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
291
292 if (atp->dflag)
293 asp_ack_reply(atp->atp_gref, m);
294 else
295 atalk_putnext(atp->atp_gref, m);
296 }
297
298 void atp_iocnak(atp, m, err)
299 struct atp_state *atp;
300 register gbuf_t *m;
301 register int err;
302 {
303 if (gbuf_type(m) == MSG_IOCTL)
304 gbuf_set_type(m, MSG_IOCNAK);
305 ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
306 ((ioc_t *)gbuf_rptr(m))->ioc_error = err ? err : ENXIO;
307 ((ioc_t *)gbuf_rptr(m))->ioc_rval = -1;
308 if (gbuf_cont(m)) {
309 gbuf_freem(gbuf_cont(m));
310 gbuf_cont(m) = NULL;
311 }
312
313 if (atp->dflag)
314 asp_nak_reply(atp->atp_gref, m);
315 else
316 atalk_putnext(atp->atp_gref, m);
317 }
318
319 /*
320 * Generate a transaction id for a socket
321 */
322 static int lasttid;
323 int atp_tid(atp)
324 register struct atp_state *atp;
325 {
326 register int i;
327 register struct atp_trans *trp;
328
329 for (i = lasttid;;) {
330 i = (i+1)&0xffff;
331
332 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
333 if (trp->tr_tid == i)
334 break;
335 }
336 if (trp == NULL) {
337 lasttid = i;
338 return(i);
339 }
340 }
341 }