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