]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
5d5c5d0d A |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. |
3 | * | |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
2d21ac55 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 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. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
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 | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
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. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b A |
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 | ||
2d21ac55 A |
50 | #include <net/if.h> |
51 | ||
1c79356b A |
52 | #include <netat/sysglue.h> |
53 | #include <netat/appletalk.h> | |
54 | #include <netat/ddp.h> | |
55 | #include <netat/at_pcb.h> | |
2d21ac55 | 56 | #include <netat/at_var.h> |
1c79356b | 57 | #include <netat/atp.h> |
2d21ac55 | 58 | #include <netat/asp.h> |
1c79356b A |
59 | #include <netat/debug.h> |
60 | ||
e2fac8b1 A |
61 | __private_extern__ int atp_resp_seqno2big = 0; |
62 | ||
2d21ac55 | 63 | static void atp_trans_complete(struct atp_trans *); |
91447636 | 64 | void atp_x_done_locked(void *); |
2d21ac55 | 65 | void atp_treq_event(void *); |
1c79356b A |
66 | |
67 | /* | |
68 | * Decide what to do about received messages | |
69 | * Version 1.7 of atp_read.c on 89/02/09 17:53:16 | |
70 | */ | |
71 | ||
55e303ae | 72 | void atp_treq_event(void *arg) |
1c79356b | 73 | { |
55e303ae | 74 | register gref_t *gref = (gref_t *)arg; |
1c79356b A |
75 | register gbuf_t *m; |
76 | register struct atp_state *atp; | |
1c79356b | 77 | |
91447636 | 78 | atalk_lock(); |
1c79356b A |
79 | atp = (struct atp_state *)gref->info; |
80 | if (atp->dflag) | |
81 | atp = (struct atp_state *)atp->atp_msgq; | |
82 | ||
83 | if (atp->dflag) { | |
84 | if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) != NULL) { | |
85 | gbuf_set_type(m, MSG_IOCTL); | |
86 | gbuf_wset(m,sizeof(ioc_t)); | |
87 | ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_GET_POLL; | |
88 | atp_wput(gref, m); | |
89 | } | |
90 | } | |
91 | else if ((m = gbuf_alloc(1, PRI_HI)) != NULL) { | |
92 | *gbuf_rptr(m) = 0; | |
93 | gbuf_wset(m,1); | |
94 | atalk_putnext(gref, m); | |
95 | } | |
96 | ||
97 | if (m == 0) | |
98 | timeout(atp_treq_event, gref, 10); | |
91447636 | 99 | atalk_unlock(); |
1c79356b A |
100 | } |
101 | ||
102 | void atp_rput(gref, m) | |
103 | gref_t *gref; | |
104 | gbuf_t *m; | |
105 | { | |
106 | register at_atp_t *athp; | |
107 | register struct atp_state *atp; | |
1c79356b | 108 | gbuf_t *m_asp = NULL; |
91447636 | 109 | struct timeval timenow; |
0c530ab8 | 110 | u_short temp_net; |
1c79356b A |
111 | |
112 | atp = (struct atp_state *)gref->info; | |
113 | if (atp->dflag) | |
114 | atp = (struct atp_state *)atp->atp_msgq; | |
115 | ||
116 | switch(gbuf_type(m)) { | |
117 | case MSG_DATA: | |
118 | /* | |
119 | * Decode the message, make sure it is an atp | |
120 | * message | |
121 | */ | |
122 | if (((AT_DDP_HDR(m))->type != DDP_ATP) || | |
123 | (atp->atp_flags & ATP_CLOSING)) { | |
124 | gbuf_freem(m); | |
125 | dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), | |
126 | ("atp_rput: dropping MSG, not atp\n")); | |
127 | break; | |
128 | } | |
129 | ||
130 | athp = AT_ATP_HDR(m); | |
131 | dPrintf(D_M_ATP_LOW, D_L_INPUT, | |
132 | ("atp_rput MSG_DATA: %s (%d)\n", | |
133 | (athp->cmd == ATP_CMD_TRESP)? "TRESP": | |
134 | (athp->cmd == ATP_CMD_TREL)? "TREL": | |
135 | (athp->cmd == ATP_CMD_TREQ)? "TREQ": "unknown", | |
136 | athp->cmd)); | |
137 | trace_mbufs(D_M_ATP_LOW, " r", m); | |
138 | ||
139 | switch (athp->cmd) { | |
140 | ||
141 | case ATP_CMD_TRESP: | |
142 | { | |
143 | register struct atp_trans *trp; | |
e2fac8b1 A |
144 | register unsigned int seqno; |
145 | register at_ddp_t *ddp; | |
1c79356b A |
146 | |
147 | /* | |
148 | * we just got a response, find the trans record | |
149 | */ | |
150 | ||
1c79356b | 151 | for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) { |
0c530ab8 | 152 | if (trp->tr_tid == UAS_VALUE_NTOH(athp->tid)) |
1c79356b A |
153 | break; |
154 | } | |
155 | ||
156 | /* | |
157 | * If we can't find one then ignore the message | |
158 | */ | |
159 | seqno = athp->bitmap; | |
e2fac8b1 A |
160 | if (seqno > 7) { |
161 | atp_resp_seqno2big++; | |
162 | ddp = AT_DDP_HDR(m); | |
163 | dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), | |
164 | ("atp_rput: dropping TRESP seqno too big, tid=%d,loc=%d,rem=%d.%d,seqno=%u\n", | |
165 | UAS_VALUE_NTOH(athp->tid), | |
166 | ddp->dst_socket, ddp->src_node, ddp->src_socket, seqno)); | |
167 | gbuf_freem(m); | |
168 | return; | |
169 | } | |
1c79356b | 170 | if (trp == NULL) { |
1c79356b A |
171 | ddp = AT_DDP_HDR(m); |
172 | dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), | |
e2fac8b1 | 173 | ("atp_rput: dropping TRESP, no trp,tid=%d,loc=%d,rem=%d.%d,seqno=%u\n", |
0c530ab8 A |
174 | UAS_VALUE_NTOH(athp->tid), |
175 | ddp->dst_socket, ddp->src_node, ddp->src_socket, seqno)); | |
1c79356b A |
176 | gbuf_freem(m); |
177 | return; | |
178 | } | |
179 | ||
180 | /* | |
181 | * If no longer valid, drop it | |
182 | */ | |
183 | if (trp->tr_state == TRANS_FAILED) { | |
1c79356b A |
184 | ddp = AT_DDP_HDR(m); |
185 | dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), | |
186 | ("atp_rput: dropping TRESP, failed trp,tid=%d,loc=%d,rem=%d.%d\n", | |
0c530ab8 | 187 | UAS_VALUE_NTOH(athp->tid), |
1c79356b A |
188 | ddp->dst_socket, ddp->src_node, ddp->src_socket)); |
189 | gbuf_freem(m); | |
190 | return; | |
191 | } | |
192 | ||
193 | /* | |
194 | * If we have already received it, ignore it | |
195 | */ | |
196 | if (!(trp->tr_bitmap&atp_mask[seqno]) || trp->tr_rcv[seqno]) { | |
1c79356b A |
197 | ddp = AT_DDP_HDR(m); |
198 | dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), | |
e2fac8b1 | 199 | ("atp_rput: dropping TRESP, duplicate,tid=%d,loc=%d,rem=%d.%d,seqno=%u\n", |
0c530ab8 | 200 | UAS_VALUE_NTOH(athp->tid), |
1c79356b A |
201 | ddp->dst_socket, ddp->src_node, ddp->src_socket, seqno)); |
202 | gbuf_freem(m); | |
203 | return; | |
204 | } | |
205 | ||
206 | /* | |
207 | * Update the received packet bitmap | |
208 | */ | |
209 | if (athp->eom) | |
210 | trp->tr_bitmap &= atp_lomask[seqno]; | |
211 | else | |
212 | trp->tr_bitmap &= ~atp_mask[seqno]; | |
213 | ||
214 | /* | |
215 | * Save the message in the trans record | |
216 | */ | |
217 | trp->tr_rcv[seqno] = m; | |
218 | ||
219 | /* | |
220 | * If it isn't the first message then | |
221 | * can the header | |
222 | */ | |
223 | if (seqno) | |
224 | gbuf_rinc(m,DDP_X_HDR_SIZE); | |
225 | ||
226 | /* | |
227 | * If we now have all the responses then return | |
228 | * the message to the user | |
229 | */ | |
230 | if (trp->tr_bitmap == 0) { | |
1c79356b A |
231 | |
232 | /* | |
233 | * Cancel the request timer and any | |
234 | * pending transmits | |
235 | */ | |
236 | atp_untimout(atp_req_timeout, trp); | |
237 | ||
238 | /* | |
239 | * Send the results back to the user | |
240 | */ | |
241 | atp_x_done(trp); | |
242 | return; | |
243 | } | |
244 | if (athp->sts) { | |
245 | /* | |
246 | * If they want treq again, send them | |
247 | */ | |
1c79356b A |
248 | atp_untimout(atp_req_timeout, trp); |
249 | atp_send(trp); | |
250 | return; | |
251 | } | |
1c79356b A |
252 | return; |
253 | } | |
254 | ||
255 | case ATP_CMD_TREL: | |
256 | { register struct atp_rcb *rcbp; | |
257 | register at_ddp_t *ddp; | |
258 | ||
259 | /* | |
260 | * Search for a matching transaction | |
261 | */ | |
262 | ddp = AT_DDP_HDR(m); | |
263 | ||
1c79356b | 264 | for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) { |
0c530ab8 | 265 | if (rcbp->rc_tid == UAS_VALUE_NTOH(athp->tid) && |
1c79356b A |
266 | rcbp->rc_socket.node == ddp->src_node && |
267 | rcbp->rc_socket.net == NET_VALUE(ddp->src_net) && | |
268 | rcbp->rc_socket.socket == ddp->src_socket) { | |
269 | /* | |
270 | * Mark the rcb released | |
271 | */ | |
272 | rcbp->rc_not_sent_bitmap = 0; | |
273 | if (rcbp->rc_state == RCB_SENDING) | |
274 | rcbp->rc_state = RCB_RELEASED; | |
275 | else | |
276 | { | |
277 | ddp = 0; | |
278 | atp_rcb_free(rcbp); | |
1c79356b A |
279 | } |
280 | break; | |
281 | } | |
282 | } | |
283 | ||
1c79356b A |
284 | gbuf_freem(m); |
285 | return; | |
286 | } | |
287 | ||
288 | ||
289 | case ATP_CMD_TREQ: | |
290 | { register struct atp_rcb *rcbp; | |
291 | register at_ddp_t *ddp; | |
292 | gbuf_t *m2; | |
293 | ||
294 | /* | |
295 | * If it is a request message, first | |
296 | * check to see | |
297 | * if matches something in our active | |
298 | * request queue | |
299 | */ | |
300 | ddp = AT_DDP_HDR(m); | |
301 | ||
1c79356b | 302 | for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) { |
0c530ab8 | 303 | if (rcbp->rc_tid == UAS_VALUE_NTOH(athp->tid) && |
1c79356b A |
304 | rcbp->rc_socket.node == ddp->src_node && |
305 | rcbp->rc_socket.net == NET_VALUE(ddp->src_net) && | |
306 | rcbp->rc_socket.socket == ddp->src_socket) | |
307 | break; | |
308 | } | |
309 | /* | |
310 | * If this is a new req then do | |
311 | * something with it | |
312 | */ | |
313 | if (rcbp == NULL) { | |
314 | /* | |
315 | * see if it matches something in the | |
316 | * attached request queue | |
317 | * if it does, just release the message | |
318 | * and go on about our buisness | |
319 | */ | |
320 | /* we just did this, why do again? -jjs 4-10-95 */ | |
321 | for (rcbp = atp->atp_attached.head; rcbp; rcbp = rcbp->rc_list.next) { | |
0c530ab8 | 322 | if (rcbp->rc_tid == UAS_VALUE_NTOH(athp->tid) && |
1c79356b A |
323 | rcbp->rc_socket.node == ddp->src_node && |
324 | rcbp->rc_socket.net == NET_VALUE(ddp->src_net) && | |
325 | rcbp->rc_socket.socket == ddp->src_socket) { | |
1c79356b A |
326 | gbuf_freem(m); |
327 | dPrintf(D_M_ATP_LOW, D_L_INPUT, | |
328 | ("atp_rput: dropping TREQ, matches req queue\n")); | |
329 | return; | |
330 | } | |
331 | } | |
332 | ||
333 | /* | |
334 | * assume someone is interested in | |
335 | * in an asynchronous incoming request | |
336 | */ | |
1c79356b A |
337 | if ((rcbp = atp_rcb_alloc(atp)) == NULL) { |
338 | gbuf_freem(m); | |
339 | return; | |
340 | } | |
341 | rcbp->rc_state = RCB_UNQUEUED; | |
1c79356b A |
342 | |
343 | rcbp->rc_local_node = ddp->dst_node; | |
0c530ab8 A |
344 | temp_net = NET_VALUE(ddp->dst_net); |
345 | NET_ASSIGN_NOSWAP(rcbp->rc_local_net, temp_net); | |
1c79356b A |
346 | rcbp->rc_socket.socket = ddp->src_socket; |
347 | rcbp->rc_socket.node = ddp->src_node; | |
348 | rcbp->rc_socket.net = NET_VALUE(ddp->src_net); | |
0c530ab8 | 349 | rcbp->rc_tid = UAS_VALUE_NTOH(athp->tid); |
1c79356b A |
350 | rcbp->rc_bitmap = athp->bitmap; |
351 | rcbp->rc_not_sent_bitmap = athp->bitmap; | |
352 | rcbp->rc_xo = athp->xo; | |
353 | /* | |
354 | * if async then send it as | |
355 | * data | |
356 | * otherwise, it is a synchronous ioctl so | |
357 | * complete it | |
358 | */ | |
359 | if (atp->dflag) { /* for ASP? */ | |
360 | if ((m2 = gbuf_alloc(sizeof(ioc_t), PRI_HI))) { | |
361 | gbuf_set_type(m2, MSG_DATA); | |
362 | gbuf_wset(m2,sizeof(ioc_t)); | |
363 | ((ioc_t *)gbuf_rptr(m2))->ioc_cmd = AT_ATP_GET_POLL; | |
364 | m_asp = m2; | |
365 | } | |
366 | } else if ((m2 = gbuf_alloc(1, PRI_HI))) { | |
367 | *gbuf_rptr(m2) = 0; | |
368 | gbuf_wset(m2,1); | |
369 | atalk_putnext(gref, m2); | |
370 | } | |
371 | if (m2 == 0) { | |
372 | dPrintf(D_M_ATP,D_L_WARNING, | |
373 | ("atp_rput: out of buffer for TREQ\n")); | |
374 | timeout(atp_treq_event, gref, 10); | |
375 | } | |
376 | rcbp->rc_ioctl = m; | |
377 | ||
378 | /* | |
379 | * move it to the attached list | |
380 | */ | |
381 | dPrintf(D_M_ATP_LOW, D_L_INPUT, | |
382 | ("atp_rput: moving to attached list\n")); | |
383 | rcbp->rc_state = RCB_PENDING; | |
384 | ATP_Q_APPEND(atp->atp_attached, rcbp, rc_list); | |
385 | if (m_asp != NULL) { | |
1c79356b A |
386 | atp_req_ind(atp, m_asp); |
387 | return; | |
388 | } | |
389 | } else { | |
390 | dPrintf(D_M_ATP_LOW, D_L_INPUT, | |
391 | ("atp_rput: found match, state:%d\n", | |
392 | rcbp->rc_state)); | |
393 | ||
394 | /* | |
395 | * Otherwise we have found a matching request | |
396 | * look for what to do | |
397 | */ | |
398 | switch (rcbp->rc_state) { | |
399 | case RCB_RESPONDING: | |
400 | case RCB_RESPONSE_FULL: | |
401 | /* | |
402 | * If it is one we have in progress | |
403 | * (either have all the responses | |
404 | * or are waiting for them) | |
405 | * update the bitmap and resend | |
406 | * the replies | |
407 | */ | |
91447636 | 408 | getmicrouptime(&timenow); |
1c79356b | 409 | if (rcbp->rc_timestamp) { |
91447636 | 410 | rcbp->rc_timestamp = timenow.tv_sec; |
1c79356b A |
411 | if (rcbp->rc_timestamp == 0) |
412 | rcbp->rc_timestamp = 1; | |
413 | } | |
1c79356b A |
414 | rcbp->rc_bitmap = athp->bitmap; |
415 | rcbp->rc_not_sent_bitmap = athp->bitmap; | |
1c79356b A |
416 | gbuf_freem(m); |
417 | atp_reply(rcbp); | |
418 | return; | |
419 | ||
420 | case RCB_RELEASED: | |
421 | default: | |
422 | /* | |
423 | * If we have a release or | |
424 | * we haven't sent any data yet | |
425 | * ignore the request | |
426 | */ | |
1c79356b A |
427 | gbuf_freem(m); |
428 | return; | |
429 | } | |
430 | } | |
1c79356b A |
431 | return; |
432 | } | |
433 | ||
434 | default: | |
435 | gbuf_freem(m); | |
436 | break; | |
437 | } | |
438 | break; | |
439 | ||
440 | case MSG_IOCACK: | |
441 | if (atp->dflag) | |
442 | asp_ack_reply(gref, m); | |
443 | else | |
444 | atalk_putnext(gref, m); | |
445 | break; | |
446 | ||
447 | case MSG_IOCNAK: | |
448 | if (atp->dflag) | |
449 | asp_nak_reply(gref, m); | |
450 | else | |
451 | atalk_putnext(gref, m); | |
452 | break; | |
453 | ||
454 | default: | |
455 | gbuf_freem(m); | |
456 | } | |
457 | } /* atp_rput */ | |
458 | ||
459 | void | |
91447636 | 460 | atp_x_done_locked(trp) |
55e303ae | 461 | void *trp; |
1c79356b | 462 | { |
91447636 | 463 | atalk_lock(); |
55e303ae | 464 | atp_x_done((struct atp_trans *)trp); |
91447636 | 465 | atalk_unlock(); |
1c79356b A |
466 | |
467 | } | |
468 | ||
469 | void | |
470 | atp_x_done(trp) | |
471 | register struct atp_trans *trp; | |
472 | { | |
473 | struct atp_state *atp; | |
474 | gbuf_t *m; | |
475 | ||
476 | ||
477 | if ( !trp->tr_xo) | |
478 | atp_trans_complete(trp); | |
479 | else { | |
480 | /* | |
481 | * If execute once send a release | |
482 | */ | |
483 | if ((m = (gbuf_t *)atp_build_release(trp)) != NULL) { | |
484 | AT_DDP_HDR(m)->src_socket = ((struct atp_state *) | |
485 | trp->tr_queue)->atp_socket_no; | |
486 | DDP_OUTPUT(m); | |
487 | /* | |
488 | * Now send back the transaction reply to the process | |
489 | * or notify the process if required | |
490 | */ | |
491 | atp_trans_complete(trp); | |
492 | } else { | |
493 | ||
494 | atp = trp->tr_queue; | |
495 | trp->tr_state = TRANS_RELEASE; | |
91447636 | 496 | timeout(atp_x_done_locked, trp, 10); |
1c79356b A |
497 | } |
498 | } | |
499 | } | |
500 | ||
501 | static void | |
502 | atp_trans_complete(trp) | |
503 | register struct atp_trans *trp; | |
504 | { register gbuf_t *m; | |
505 | register int type; | |
506 | struct atp_state *atp; | |
507 | ||
508 | /* we could gbuf_freem(trp->tr_xmt) here if were not planning to | |
509 | re-use the mbuf later */ | |
510 | m = trp->tr_xmt; | |
511 | trp->tr_xmt = NULL; | |
512 | trp->tr_state = TRANS_DONE; | |
513 | ||
514 | if (gbuf_cont(m) == NULL) /* issued via the new interface */ | |
515 | type = AT_ATP_ISSUE_REQUEST_NOTE; | |
516 | else { | |
517 | type = ((ioc_t *)(gbuf_rptr(m)))->ioc_cmd; | |
518 | /* | |
519 | * free any data following the ioctl blk | |
520 | */ | |
521 | gbuf_freem(gbuf_cont(m)); | |
522 | gbuf_cont(m) = NULL; | |
523 | } | |
524 | dPrintf(D_M_ATP_LOW, D_L_INPUT, ("atp_trans_comp: trp=0x%x type = %s\n", | |
525 | (u_int) trp, | |
526 | (type==AT_ATP_ISSUE_REQUEST)? "AT_ATP_ISSUE_REQUEST": | |
527 | (type==AT_ATP_ISSUE_REQUEST_NOTE)? "AT_ATP_ISSUE_REQUEST_NOTE" : | |
528 | "unknown")); | |
529 | ||
530 | switch(type) { | |
531 | case AT_ATP_ISSUE_REQUEST: | |
532 | atp = trp->tr_queue; | |
533 | if (atp->dflag) { | |
534 | ((ioc_t *)gbuf_rptr(m))->ioc_count = 0; | |
535 | ((ioc_t *)gbuf_rptr(m))->ioc_error = 0; | |
536 | ((ioc_t *)gbuf_rptr(m))->ioc_rval = trp->tr_tid; | |
537 | ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_REQUEST_COMPLETE; | |
538 | gbuf_set_type(m, MSG_IOCTL); | |
539 | atp_rsp_ind(trp, m); | |
540 | } else { | |
541 | if (trp->tr_bdsp == NULL) { | |
542 | gbuf_freem(m); | |
543 | if (trp->tr_rsp_wait) | |
9bccf70c | 544 | wakeup(&trp->tr_event); |
1c79356b A |
545 | } else { |
546 | gbuf_set_type(m, MSG_IOCACK); | |
547 | ((ioc_t *)gbuf_rptr(m))->ioc_count = 0; | |
548 | ((ioc_t *)gbuf_rptr(m))->ioc_error = 0; | |
549 | ((ioc_t *)gbuf_rptr(m))->ioc_rval = 0; | |
550 | atalk_putnext(trp->tr_queue->atp_gref, m); | |
551 | } | |
552 | } | |
553 | break; | |
554 | ||
555 | case AT_ATP_ISSUE_REQUEST_NOTE: | |
556 | gbuf_wset(m,1); | |
557 | *gbuf_rptr(m) = 1; | |
558 | gbuf_set_type(m, MSG_DATA); | |
559 | atalk_putnext(trp->tr_queue->atp_gref, m); | |
560 | break; | |
561 | } | |
562 | } /* atp_trans_complete */ |