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