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