]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/atp_write.c
1eebbd18259113f04e0c609acebfb6e731fb9079
[apple/xnu.git] / bsd / netat / atp_write.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Copyright (c) 1996-1998 Apple Computer, Inc.
27 * All Rights Reserved.
28 */
29
30 /* Modified for MP, 1996 by Tuyen Nguyen
31 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
32 */
33 #define RESOLVE_DBG
34
35 #include <sys/errno.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <machine/spl.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/proc.h>
42 #include <sys/filedesc.h>
43 #include <sys/fcntl.h>
44 #include <sys/mbuf.h>
45 #include <sys/ioctl.h>
46 #include <sys/malloc.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49
50 #include <net/if.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/at_var.h>
58 #include <netat/asp.h>
59 #include <netat/at_pat.h>
60 #include <netat/debug.h>
61
62 static int loop_cnt; /* for debugging loops */
63 #define CHK_LOOP(str) { \
64 if (loop_cnt++ > 100) { \
65 kprintf("%s", str); \
66 break; \
67 } \
68 }
69
70 static void atp_pack_bdsp(struct atp_trans *, struct atpBDS *);
71 static int atp_unpack_bdsp(struct atp_state *, gbuf_t *, struct atp_rcb *,
72 int, int);
73 void atp_retry_req(), atp_trp_clock(), asp_clock(), asp_clock_funnel(), atp_trp_clock_funnel();;
74
75 extern struct atp_rcb_qhead atp_need_rel;
76 extern int atp_inited;
77 extern struct atp_state *atp_used_list;
78 extern asp_scb_t *scb_free_list;
79 extern atlock_t atpgen_lock;
80 extern atlock_t atpall_lock;
81 extern atlock_t atptmo_lock;
82
83 extern gbuf_t *scb_resource_m;
84 extern gbuf_t *atp_resource_m;
85 extern gref_t *atp_inputQ[];
86 extern int atp_pidM[];
87 extern at_ifaddr_t *ifID_home;
88
89 static struct atp_trans *trp_tmo_list;
90 struct atp_trans *trp_tmo_rcb;
91
92 /* first bds entry gives number of bds entries in total (hack) */
93 #define get_bds_entries(m) \
94 ((gbuf_len(m) > TOTAL_ATP_HDR_SIZE)? \
95 (UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz)): 0)
96
97 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
98
99 void atp_link()
100 {
101 trp_tmo_list = 0;
102 trp_tmo_rcb = atp_trans_alloc(0);
103 atp_timout(atp_rcb_timer, trp_tmo_rcb, 10 * HZ);
104 atp_trp_clock((void *)&atp_inited);
105 asp_clock((void *)&atp_inited);
106 }
107
108 void atp_unlink()
109 {
110 untimeout(asp_clock_funnel, (void *)&atp_inited);
111 untimeout(atp_trp_clock_funnel, (void *)&atp_inited);
112 atp_untimout(atp_rcb_timer, trp_tmo_rcb);
113 trp_tmo_list = 0;
114
115 #ifdef BAD_IDEA
116 /* allocated in asp_scb_alloc(), which is called
117 by asp_open() */
118 if (scb_resource_m) {
119 gbuf_freem(scb_resource_m);
120 scb_resource_m = 0;
121 scb_free_list = 0;
122 }
123 /* allocated in atp_trans_alloc() */
124 if (atp_resource_m) {
125 gbuf_freem(atp_resource_m);
126 atp_resource_m = 0;
127 atp_trans_free_list = 0;
128 }
129 #endif
130 }
131
132 /*
133 * write queue put routine .... filter out other than IOCTLs
134 * Version 1.8 of atp_write.c on 89/02/09 17:53:26
135 */
136
137 void
138 atp_wput(gref, m)
139 register gref_t *gref;
140 register gbuf_t *m;
141 {
142 register ioc_t *iocbp;
143 int i, xcnt, s;
144 struct atp_state *atp;
145 struct atp_trans *trp;
146 struct atp_rcb *rcbp;
147 at_socket skt;
148
149 atp = (struct atp_state *)gref->info;
150 if (atp->dflag)
151 atp = (struct atp_state *)atp->atp_msgq;
152
153 switch(gbuf_type(m)) {
154 case MSG_DATA:
155 if (atp->atp_msgq) {
156 gbuf_freem(m);
157 dPrintf(D_M_ATP, D_L_WARNING,
158 ("atp_wput: atp_msgq discarded\n"));
159 } else
160 atp->atp_msgq = m;
161 break;
162
163 case MSG_IOCTL:
164 /* Need to ensure that all copyin/copyout calls are made at
165 * put routine time which should be in the user context. (true when
166 * we are the stream head). The service routine can be called on an
167 * unpredictable context and copyin/copyout calls will get wrong results
168 * or even panic the kernel.
169 */
170 iocbp = (ioc_t *)gbuf_rptr(m);
171
172 switch (iocbp->ioc_cmd) {
173 case AT_ATP_BIND_REQ:
174 if (gbuf_cont(m) == NULL) {
175 iocbp->ioc_rval = -1;
176 atp_iocnak(atp, m, EINVAL);
177 return;
178 }
179 skt = *(at_socket *)gbuf_rptr(gbuf_cont(m));
180 if ((skt = (at_socket)atp_bind(gref, (unsigned int)skt, 0)) == 0)
181 atp_iocnak(atp, m, EINVAL);
182 else {
183 *(at_socket *)gbuf_rptr(gbuf_cont(m)) = skt;
184 iocbp->ioc_rval = 0;
185 atp_iocack(atp, m);
186 atp_dequeue_atp(atp);
187 }
188 return;
189
190 case AT_ATP_GET_CHANID:
191 if (gbuf_cont(m) == NULL) {
192 iocbp->ioc_rval = -1;
193 atp_iocnak(atp, m, EINVAL);
194 return;
195 }
196 *(gref_t **)gbuf_rptr(gbuf_cont(m)) = gref;
197 atp_iocack(atp, m);
198 return;
199
200 /* not the close and not the tickle(?) */
201 case AT_ATP_ISSUE_REQUEST_DEF:
202 case AT_ATP_ISSUE_REQUEST_DEF_NOTE: {
203 gbuf_t *bds, *tmp, *m2;
204 struct atp_rcb *rcbp;
205 at_ddp_t *ddp;
206 at_atp_t *athp;
207
208 if ((tmp = gbuf_cont(m)) != 0) {
209 if ((bds = gbuf_dupb(tmp)) == NULL) {
210 atp_iocnak(atp, m, ENOBUFS);
211 return;
212 }
213 gbuf_rinc(tmp,atpBDSsize);
214 gbuf_wset(bds,atpBDSsize);
215 iocbp->ioc_count -= atpBDSsize;
216 gbuf_cont(tmp) = bds;
217 }
218
219 /*
220 * send a response to a transaction
221 * first check it out
222 */
223 if (iocbp->ioc_count < TOTAL_ATP_HDR_SIZE) {
224 atp_iocnak(atp, m, EINVAL);
225 break;
226 }
227
228 /*
229 * remove the response from the message
230 */
231 m2 = gbuf_cont(m);
232 gbuf_cont(m) = NULL;
233 iocbp->ioc_count = 0;
234 ddp = AT_DDP_HDR(m2);
235 athp = AT_ATP_HDR(m2);
236 if (atp->atp_msgq) {
237 gbuf_cont(m2) = atp->atp_msgq;
238 atp->atp_msgq = 0;
239 }
240
241 ATDISABLE(s, atp->atp_lock);
242 /*
243 * search for the corresponding rcb
244 */
245 for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
246 if (rcbp->rc_tid == UAS_VALUE(athp->tid) &&
247 rcbp->rc_socket.node == ddp->dst_node &&
248 rcbp->rc_socket.net == NET_VALUE(ddp->dst_net) &&
249 rcbp->rc_socket.socket == ddp->dst_socket)
250 break;
251 }
252 ATENABLE(s, atp->atp_lock);
253
254 /*
255 * If it has already been sent then return an error
256 */
257 if ((rcbp && rcbp->rc_state != RCB_NOTIFIED) ||
258 (rcbp == NULL && athp->xo)) {
259 atp_iocnak(atp, m, ENOENT);
260 gbuf_freem(m2);
261 return;
262 }
263 if (rcbp == NULL) { /* a response for an ALO transaction */
264 if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
265 atp_iocnak(atp, m, ENOBUFS);
266 gbuf_freem(m2);
267 return;
268 }
269 rcbp->rc_ioctl = 0;
270 rcbp->rc_socket.socket = ddp->dst_socket;
271 rcbp->rc_socket.node = ddp->dst_node;
272 rcbp->rc_socket.net = NET_VALUE(ddp->dst_net);
273 rcbp->rc_tid = UAS_VALUE(athp->tid);
274 rcbp->rc_bitmap = 0xff;
275 rcbp->rc_xo = 0;
276 ATDISABLE(s, atp->atp_lock);
277 rcbp->rc_state = RCB_SENDING;
278 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
279 ATENABLE(s, atp->atp_lock);
280 }
281 xcnt = get_bds_entries(m2);
282 if ((i = atp_unpack_bdsp(atp, m2, rcbp, xcnt, FALSE))) {
283 if ( !rcbp->rc_xo)
284 atp_rcb_free(rcbp);
285 atp_iocnak(atp, m, i);
286 return;
287 }
288 atp_send_replies(atp, rcbp);
289
290 /*
291 * send the ack back to the responder
292 */
293 atp_iocack(atp, m);
294 return;
295 }
296
297 case AT_ATP_GET_POLL: {
298 if (gbuf_cont(m)) {
299 gbuf_freem(gbuf_cont(m));
300 gbuf_cont(m) = NULL;
301 iocbp->ioc_count = 0;
302 }
303
304 /*
305 * search for a waiting request
306 */
307 ATDISABLE(s, atp->atp_lock);
308 if ((rcbp = atp->atp_attached.head)) {
309 /*
310 * Got one, move it to the active response Q
311 */
312 gbuf_cont(m) = rcbp->rc_ioctl;
313 rcbp->rc_ioctl = NULL;
314 if (rcbp->rc_xo) {
315 ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
316 rcbp->rc_state = RCB_NOTIFIED;
317 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
318 } else {
319 /* detach rcbp from attached queue,
320 * and free any outstanding resources
321 */
322 atp_rcb_free(rcbp);
323 }
324 ATENABLE(s, atp->atp_lock);
325 atp_iocack(atp, m);
326 } else {
327 /*
328 * None available - can out
329 */
330 ATENABLE(s, atp->atp_lock);
331 atp_iocnak(atp, m, EAGAIN);
332 }
333 break;
334 }
335
336 case AT_ATP_CANCEL_REQUEST: {
337 /*
338 * Cancel a pending request
339 */
340 if (iocbp->ioc_count != sizeof(int)) {
341 atp_iocnak(atp, m, EINVAL);
342 break;
343 }
344 i = *(int *)gbuf_rptr(gbuf_cont(m));
345 gbuf_freem(gbuf_cont(m));
346 gbuf_cont(m) = NULL;
347 ATDISABLE(s, atp->atp_lock);
348 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
349 if (trp->tr_tid == i)
350 break;
351 }
352 if (trp == NULL) {
353 ATENABLE(s, atp->atp_lock);
354 atp_iocnak(atp, m, ENOENT);
355 } else {
356 ATENABLE(s, atp->atp_lock);
357 atp_free(trp);
358 atp_iocack(atp, m);
359 }
360 break;
361 }
362
363 case AT_ATP_PEEK: {
364 unsigned char event;
365 if (atalk_peek(gref, &event) == -1)
366 atp_iocnak(atp, m, EAGAIN);
367 else {
368 *gbuf_rptr(gbuf_cont(m)) = event;
369 atp_iocack(atp, m);
370 }
371 break;
372 }
373
374 case DDP_IOC_GET_CFG:
375 #ifdef APPLETALK_DEBUG
376 kprintf("atp_wput: DDP_IOC_GET_CFG\n");
377 #endif
378 if (gbuf_cont(m) == 0) {
379 atp_iocnak(atp, m, EINVAL);
380 break;
381 }
382 {
383 /* *** was ddp_get_cfg() *** */
384 ddp_addr_t *cfgp =
385 (ddp_addr_t *)gbuf_rptr(gbuf_cont(m));
386 cfgp->inet.net = ifID_home->ifThisNode.s_net;
387 cfgp->inet.node = ifID_home->ifThisNode.s_node;
388 cfgp->inet.socket = atp->atp_socket_no;
389 cfgp->ddptype = DDP_ATP;
390 #ifdef NOT_YET
391 cfgp->inet.net = atp->atp_gref->laddr.s_net;
392 cfgp->inet.node = atp->atp_gref->laddr.s_node;
393 cfgp->inet.socket = atp->atp_gref->lport;
394 cfgp->ddptype = atp->atp_gref->ddptype;
395 #endif
396 }
397 gbuf_wset(gbuf_cont(m), sizeof(ddp_addr_t));
398 atp_iocack(atp, m);
399 break;
400
401 default:
402 /*
403 * Otherwise pass it on, if possible
404 */
405 iocbp->ioc_private = (void *)gref;
406 DDP_OUTPUT(m);
407 break;
408 }
409 break;
410
411 default:
412 gbuf_freem(m);
413 break;
414 }
415 } /* atp_wput */
416
417 gbuf_t *atp_build_release(trp)
418 register struct atp_trans *trp;
419 {
420 register gbuf_t *m;
421 register at_ddp_t *ddp;
422 register at_atp_t *athp;
423
424 /*
425 * Now try and allocate enough space to send the message
426 * if none is available the caller will schedule
427 * a timeout so we can retry for more space soon
428 */
429 if ((m = (gbuf_t *)gbuf_alloc(AT_WR_OFFSET+ATP_HDR_SIZE, PRI_HI)) != NULL) {
430 gbuf_rinc(m,AT_WR_OFFSET);
431 gbuf_wset(m,TOTAL_ATP_HDR_SIZE);
432 ddp = AT_DDP_HDR(m);
433 ddp->type = DDP_ATP;
434 UAS_ASSIGN(ddp->checksum, 0);
435 ddp->dst_socket = trp->tr_socket.socket;
436 ddp->dst_node = trp->tr_socket.node;
437 NET_ASSIGN(ddp->dst_net, trp->tr_socket.net);
438 ddp->src_node = trp->tr_local_node;
439 NET_NET(ddp->src_net, trp->tr_local_net);
440
441 /*
442 * clear the cmd/xo/eom/sts/unused fields
443 */
444 athp = AT_ATP_HDR(m);
445 ATP_CLEAR_CONTROL(athp);
446 athp->cmd = ATP_CMD_TREL;
447 UAS_ASSIGN(athp->tid, trp->tr_tid);
448 }
449
450 return (m);
451 }
452
453 void atp_send_replies(atp, rcbp)
454 register struct atp_state *atp;
455 register struct atp_rcb *rcbp;
456 { register gbuf_t *m;
457 register int i, len;
458 int s_gen, s, cnt;
459 unsigned char *m0_rptr = NULL, *m0_wptr = NULL;
460 register at_atp_t *athp;
461 register struct atpBDS *bdsp;
462 register gbuf_t *m2, *m1, *m0, *m3;
463 caddr_t lastPage;
464 gbuf_t *mprev, *mlist = 0;
465 at_socket src_socket = (at_socket)atp->atp_socket_no;
466 gbuf_t *rc_xmt[ATP_TRESP_MAX];
467 struct ddp_atp {
468 char ddp_atp_hdr[TOTAL_ATP_HDR_SIZE];
469 };
470
471 ATDISABLE(s, atp->atp_lock);
472 if (rcbp->rc_queue != atp) {
473 ATENABLE(s, atp->atp_lock);
474 return;
475 }
476 if (rcbp->rc_not_sent_bitmap == 0)
477 goto nothing_to_send;
478
479 dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ("atp_send_replies\n"));
480 /*
481 * Do this for each message that hasn't been sent
482 */
483 cnt = rcbp->rc_pktcnt;
484 for (i = 0; i < cnt; i++) {
485 rc_xmt[i] = 0;
486 if (rcbp->rc_snd[i]) {
487 if ((rc_xmt[i] =
488 gbuf_alloc(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,PRI_MED))
489 == NULL) {
490 for (cnt = 0; cnt < i; cnt++)
491 if (rc_xmt[cnt])
492 gbuf_freeb(rc_xmt[cnt]);
493 goto nothing_to_send;
494 }
495 }
496 }
497
498 m = rcbp->rc_xmt;
499 m0 = gbuf_cont(m);
500 if (m0) {
501 m0_rptr = gbuf_rptr(m0);
502 m0_wptr = gbuf_wptr(m0);
503 }
504 if (gbuf_len(m) > TOTAL_ATP_HDR_SIZE)
505 bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
506 else
507 bdsp = 0;
508
509 for (i = 0; i < cnt; i++) {
510 if (rcbp->rc_snd[i] == 0) {
511 if ((len = UAS_VALUE(bdsp->bdsBuffSz)))
512 gbuf_rinc(m0,len);
513
514 } else {
515 m2 = rc_xmt[i];
516 gbuf_rinc(m2,AT_WR_OFFSET);
517 gbuf_wset(m2,TOTAL_ATP_HDR_SIZE);
518 *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m));
519 athp = AT_ATP_HDR(m2);
520 ATP_CLEAR_CONTROL(athp);
521 athp->cmd = ATP_CMD_TRESP;
522 athp->bitmap = i;
523 if (i == (cnt - 1))
524 athp->eom = 1; /* for the last fragment */
525 if (bdsp)
526 UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
527
528 if (bdsp)
529 if (len = UAS_VALUE(bdsp->bdsBuffSz)) { /* copy in data */
530 if (m0 && gbuf_len(m0)) {
531 if ((m1 = gbuf_dupb(m0)) == NULL) {
532 for (i = 0; i < cnt; i++)
533 if (rc_xmt[i])
534 gbuf_freem(rc_xmt[i]);
535 gbuf_rptr(m0) = m0_rptr;
536 gbuf_wset(m0,(m0_wptr-m0_rptr));
537 goto nothing_to_send;
538 }
539 gbuf_wset(m1,len);
540 gbuf_rinc(m0,len);
541 if ((len = gbuf_len(m0)) < 0) {
542 gbuf_rdec(m0,len);
543 gbuf_wdec(m1,len);
544 if (!append_copy((struct mbuf *)m1,
545 (struct mbuf *)gbuf_cont(m0), FALSE)) {
546 for (i = 0; i < cnt; i++)
547 if (rc_xmt[i])
548 gbuf_freem(rc_xmt[i]);
549 gbuf_rptr(m0) = m0_rptr;
550 gbuf_wset(m0,(m0_wptr-m0_rptr));
551 goto nothing_to_send;
552 }
553 } else
554 gbuf_cont(m1) = 0;
555 gbuf_cont(m2) = m1;
556
557 /* temp fix for page boundary problem - bug# 2703163 */
558 lastPage = (caddr_t)((int)(gbuf_wptr(m1) - 1) & ~PAGE_MASK); /* 4k page of last byte */
559 if (lastPage != (caddr_t)((int)(gbuf_rptr(m1)) & ~PAGE_MASK)) { /* 1st byte and last on same page ? */
560 if ((m3 = gbuf_dupb(m1)) == NULL) {
561 for (i = 0; i < cnt; i++)
562 if (rc_xmt[i])
563 gbuf_freem(rc_xmt[i]);
564 (gbuf_rptr(m0)) = m0_rptr;
565 gbuf_wset(m0, (m0_wptr - m0_rptr));
566 goto nothing_to_send;
567 }
568 (gbuf_rptr(m3)) = lastPage; /* new mbuf starts at beginning of page */
569 gbuf_wset(m3, (gbuf_wptr(m1) - lastPage)); /* len = remaining data crossing over page boundary */
570 gbuf_wset(m1, (lastPage - (gbuf_rptr(m1)))); /* adjust len of m1 */
571 (gbuf_cont(m1)) = m3;
572 (gbuf_cont(m3)) = 0;
573 }
574 }
575 }
576
577 AT_DDP_HDR(m2)->src_socket = src_socket;
578 dPrintf(D_M_ATP_LOW, D_L_OUTPUT,
579 ("atp_send_replies: %d, socket=%d, size=%d\n",
580 i, atp->atp_socket_no, gbuf_msgsize(gbuf_cont(m2))));
581
582 if (mlist)
583 gbuf_next(mprev) = m2;
584 else
585 mlist = m2;
586 mprev = m2;
587
588 rcbp->rc_snd[i] = 0;
589 rcbp->rc_not_sent_bitmap &= ~atp_mask[i];
590 if (rcbp->rc_not_sent_bitmap == 0)
591 break;
592 }
593 /*
594 * on to the next frag
595 */
596 bdsp++;
597 }
598 if (m0) {
599 gbuf_rptr(m0) = m0_rptr;
600 gbuf_wset(m0,(m0_wptr-m0_rptr));
601 }
602
603 if (mlist) {
604 ATENABLE(s, atp->atp_lock);
605 DDP_OUTPUT(mlist);
606 ATDISABLE(s, atp->atp_lock);
607 }
608
609 nothing_to_send:
610 /*
611 * If all replies from this reply block have been sent then
612 * remove it from the queue and mark it so
613 */
614 if (rcbp->rc_queue != atp) {
615 ATENABLE(s, atp->atp_lock);
616 return;
617 }
618 rcbp->rc_rep_waiting = 0;
619
620 /*
621 * If we are doing execute once re-set the rcb timeout
622 * each time we send back any part of the response. Note
623 * that this timer is started when an initial request is
624 * received. Each response reprimes the timer. Duplicate
625 * requests do not reprime the timer.
626 *
627 * We have sent all of a response so free the
628 * resources.
629 */
630 if (rcbp->rc_xo && rcbp->rc_state != RCB_RELEASED) {
631 ATDISABLE(s_gen, atpgen_lock);
632 if (rcbp->rc_timestamp == 0) {
633 rcbp->rc_timestamp = time.tv_sec;
634 if (rcbp->rc_timestamp == 0)
635 rcbp->rc_timestamp = 1;
636 ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist);
637 }
638 rcbp->rc_state = RCB_RESPONSE_FULL;
639 ATENABLE(s_gen, atpgen_lock);
640 } else
641 atp_rcb_free(rcbp);
642 ATENABLE(s, atp->atp_lock);
643 } /* atp_send_replies */
644
645
646 static void
647 atp_pack_bdsp(trp, bdsp)
648 register struct atp_trans *trp;
649 register struct atpBDS *bdsp;
650 {
651 register gbuf_t *m = NULL;
652 register int i, datsize = 0;
653 struct atpBDS *bdsbase = bdsp;
654
655 dPrintf(D_M_ATP, D_L_INFO, ("atp_pack_bdsp: socket=%d\n",
656 trp->tr_queue->atp_socket_no));
657
658 for (i = 0; i < ATP_TRESP_MAX; i++, bdsp++) {
659 short bufsize = UAS_VALUE(bdsp->bdsBuffSz);
660 long bufaddr = UAL_VALUE(bdsp->bdsBuffAddr);
661
662 if ((m = trp->tr_rcv[i]) == NULL)
663 break;
664
665 /* discard ddp hdr on first packet */
666 if (i == 0)
667 gbuf_rinc(m,DDP_X_HDR_SIZE);
668
669 /* this field may contain control information even when
670 no data is present */
671 UAL_UAL(bdsp->bdsUserData,
672 (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
673 gbuf_rinc(m, ATP_HDR_SIZE);
674
675 if ((bufsize != 0) && (bufaddr != 0)) {
676 /* user expects data back */
677 short tmp = 0;
678 register char *buf = (char *)bufaddr;
679
680 while (m) {
681 short len = (short)(gbuf_len(m));
682 if (len) {
683 if (len > bufsize)
684 len = bufsize;
685 copyout((caddr_t)gbuf_rptr(m),
686 (caddr_t)&buf[tmp],
687 len);
688 bufsize -= len;
689 tmp =+ len;
690 }
691 m = gbuf_cont(m);
692 }
693
694 UAS_ASSIGN(bdsp->bdsDataSz, tmp);
695 datsize += (int)tmp;
696 }
697 gbuf_freem(trp->tr_rcv[i]);
698 trp->tr_rcv[i] = NULL;
699 }
700
701 /* report the number of packets */
702 UAS_ASSIGN(((struct atpBDS *)bdsbase)->bdsBuffSz, i);
703
704 dPrintf(D_M_ATP, D_L_INFO, (" : size=%d\n",
705 datsize));
706 } /* atp_pack_bdsp */
707
708
709 static int
710 atp_unpack_bdsp(atp, m, rcbp, cnt, wait)
711 struct atp_state *atp;
712 gbuf_t *m; /* ddp, atp and bdsp gbuf_t */
713 register struct atp_rcb *rcbp;
714 register int cnt, wait;
715 {
716 register struct atpBDS *bdsp;
717 register gbuf_t *m2, *m1, *m0, *m3;
718 caddr_t lastPage;
719 register at_atp_t *athp;
720 register int i, len, s_gen;
721 at_socket src_socket;
722 struct ddp_atp {
723 char ddp_atp_hdr[TOTAL_ATP_HDR_SIZE];
724 };
725 gbuf_t *mprev, *mlist = 0;
726 gbuf_t *rc_xmt[ATP_TRESP_MAX];
727 unsigned char *m0_rptr, *m0_wptr;
728
729 /*
730 * get the user data structure pointer
731 */
732 bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
733
734 /*
735 * Guard against bogus count argument.
736 */
737 if ((unsigned) cnt > ATP_TRESP_MAX) {
738 dPrintf(D_M_ATP, D_L_ERROR,
739 ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt));
740 gbuf_freem(m);
741 return(EINVAL);
742 }
743 if ((src_socket = (at_socket)atp->atp_socket_no) == 0xFF) {
744 /* comparison was to -1, however src_socket is a u_char */
745 gbuf_freem(m);
746 return EPIPE;
747 }
748
749 m0 = gbuf_cont(m);
750 rcbp->rc_xmt = m;
751 rcbp->rc_pktcnt = cnt;
752 rcbp->rc_state = RCB_SENDING;
753 rcbp->rc_not_sent_bitmap = 0;
754
755 if (cnt <= 1) {
756 /*
757 * special case this to
758 * improve AFP write transactions to the server
759 */
760 rcbp->rc_pktcnt = 1;
761 if ((m2 = gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,
762 wait)) == NULL)
763 return 0;
764 gbuf_rinc(m2,AT_WR_OFFSET);
765 gbuf_wset(m2,TOTAL_ATP_HDR_SIZE);
766 *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m));
767 athp = AT_ATP_HDR(m2);
768 ATP_CLEAR_CONTROL(athp);
769 athp->cmd = ATP_CMD_TRESP;
770 athp->bitmap = 0;
771 athp->eom = 1; /* there's only 1 fragment */
772
773 /* *** why only if cnt > 0? *** */
774 if (cnt > 0)
775 UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
776 if (m0)
777 if (!append_copy((struct mbuf *)m2,
778 (struct mbuf *)m0, wait)) {
779 gbuf_freeb(m2);
780 return 0;
781 }
782 /*
783 * send the message and mark it as sent
784 */
785 AT_DDP_HDR(m2)->src_socket = src_socket;
786 dPrintf(D_M_ATP_LOW, D_L_INFO,
787 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
788 0,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(m2)),cnt));
789 mlist = m2;
790 goto l_send;
791 }
792
793 for (i = 0; i < cnt; i++) {
794 /* all hdrs, packet data and dst addr storage */
795 if ((rc_xmt[i] =
796 gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,
797 wait)) == NULL) {
798 for (cnt = 0; cnt < i; cnt++)
799 if (rc_xmt[cnt])
800 gbuf_freeb(rc_xmt[cnt]);
801 return 0;
802 }
803 }
804 if (m0) {
805 m0_rptr = gbuf_rptr(m0);
806 m0_wptr = gbuf_wptr(m0);
807 }
808
809 for (i = 0; i < cnt; i++) {
810 m2 = rc_xmt[i];
811 gbuf_rinc(m2,AT_WR_OFFSET);
812 gbuf_wset(m2,TOTAL_ATP_HDR_SIZE);
813 *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m));
814 athp = AT_ATP_HDR(m2);
815 ATP_CLEAR_CONTROL(athp);
816 athp->cmd = ATP_CMD_TRESP;
817 athp->bitmap = i;
818 if (i == (cnt - 1))
819 athp->eom = 1; /* for the last fragment */
820 UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
821
822 if ((len = UAS_VALUE(bdsp->bdsBuffSz))) { /* copy in data */
823 if (m0 && gbuf_len(m0)) {
824 if ((m1 = gbuf_dupb_wait(m0, wait)) == NULL) {
825 for (i = 0; i < cnt; i++)
826 if (rc_xmt[i])
827 gbuf_freem(rc_xmt[i]);
828 gbuf_rptr(m0) = m0_rptr;
829 gbuf_wset(m0,(m0_wptr-m0_rptr));
830 return 0;
831 }
832 gbuf_wset(m1,len); /* *** m1 is first len bytes of m0? *** */
833 gbuf_rinc(m0,len);
834 if ((len = gbuf_len(m0)) < 0) {
835 gbuf_rdec(m0,len);
836 gbuf_wdec(m1,len);
837 if (!append_copy((struct mbuf *)m1,
838 (struct mbuf *)gbuf_cont(m0), wait)) {
839 for (i = 0; i < cnt; i++)
840 if (rc_xmt[i])
841 gbuf_freem(rc_xmt[i]);
842 gbuf_rptr(m0) = m0_rptr;
843 gbuf_wset(m0,(m0_wptr-m0_rptr));
844 return 0;
845 }
846 } else
847 gbuf_cont(m1) = 0;
848 gbuf_cont(m2) = m1;
849
850 /* temp fix for page boundary problem - bug# 2703163 */
851 lastPage = (caddr_t)((int)(gbuf_wptr(m1) - 1) & ~PAGE_MASK); /* 4k page of last byte */
852 if (lastPage != (caddr_t)((int)(gbuf_rptr(m1)) & ~PAGE_MASK)) { /* 1st byte and last on same page ? */
853 if ((m3 = gbuf_dupb_wait(m1, wait)) == NULL) {
854 for (i = 0; i < cnt; i++)
855 if (rc_xmt[i])
856 gbuf_freem(rc_xmt[i]);
857 (gbuf_rptr(m0)) = m0_rptr;
858 gbuf_wset(m0, (m0_wptr - m0_rptr));
859 return 0;
860 }
861 (gbuf_rptr(m3)) = lastPage; /* new mbuf starts at beginning of page */
862 gbuf_wset(m3, (gbuf_wptr(m1) - lastPage)); /* len = remaining data crossing over page boundary */
863 gbuf_wset(m1, (lastPage - (gbuf_rptr(m1)))); /* adjust len of m1 */
864 (gbuf_cont(m1)) = m3;
865 (gbuf_cont(m3)) = 0;
866 }
867 }
868 }
869
870 AT_DDP_HDR(m2)->src_socket = src_socket;
871 dPrintf(D_M_ATP_LOW,D_L_INFO,
872 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
873 i,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(m2)),cnt));
874 if (mlist)
875 gbuf_next(mprev) = m2;
876 else
877 mlist = m2;
878 mprev = m2;
879 /*
880 * on to the next frag
881 */
882 bdsp++;
883 }
884 if (m0) {
885 gbuf_rptr(m0) = m0_rptr;
886 gbuf_wset(m0,(m0_wptr-m0_rptr));
887 }
888 /*
889 * send the message
890 */
891 l_send:
892 if (rcbp->rc_xo) {
893 ATDISABLE(s_gen, atpgen_lock);
894 if (rcbp->rc_timestamp == 0) {
895 if ((rcbp->rc_timestamp = time.tv_sec) == 0)
896 rcbp->rc_timestamp = 1;
897 ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist);
898 }
899 ATENABLE(s_gen, atpgen_lock);
900 }
901
902 DDP_OUTPUT(mlist);
903 return 0;
904 } /* atp_unpack_bdsp */
905
906 #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6)
907 #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
908 static unsigned int sNext = 0;
909
910 int atp_bind(gref, sVal, flag)
911 gref_t *gref;
912 unsigned int sVal;
913 unsigned char *flag;
914 {
915 extern unsigned char asp_inpC[];
916 extern asp_scb_t *asp_scbQ[];
917 unsigned char inpC, sNextUsed = 0;
918 unsigned int sMin, sMax, sSav;
919 struct atp_state *atp;
920 int s;
921
922 atp = (struct atp_state *)gref->info;
923 if (atp->dflag)
924 atp = (struct atp_state *)atp->atp_msgq;
925
926 sMax = ATP_SOCKET_LAST;
927 sMin = ATP_SOCKET_FIRST;
928 ATDISABLE(s, atpgen_lock);
929 if (flag && (*flag == 3)) {
930 sMin += 40;
931 if (sMin < sNext) {
932 sMin = sNext;
933 sNextUsed = 1;
934 }
935 }
936
937 if ( (sVal != 0) &&
938 ((sVal > sMax) || (sVal < 2) || (sVal == 6) ||
939 (ddp_socket_inuse(sVal, DDP_ATP) &&
940 (atp_inputQ[sVal] != (gref_t *)1)))) {
941 ATENABLE(s, atpgen_lock);
942 return 0;
943 }
944
945 if (sVal == 0) {
946 inpC = 255;
947 again:
948 for (sVal=sMin; sVal <= sMax; sVal++) {
949 if (!ddp_socket_inuse(sVal, DDP_ATP) ||
950 atp_inputQ[sVal] == (gref_t *)1)
951 break;
952 else if (flag && (*flag == 3) && asp_scbQ[sVal]) {
953 if ((asp_scbQ[sVal]->dflag == *flag)
954 && (asp_inpC[sVal] < inpC) ) {
955 inpC = asp_inpC[sVal];
956 sSav = sVal;
957 }
958 }
959 }
960 if (sVal > sMax) {
961 if (flag && (*flag == 3)) {
962 if (sNextUsed) {
963 sNextUsed = 0;
964 sMax = sNext - 1;
965 sMin = ATP_SOCKET_FIRST+40;
966 goto again;
967 }
968 sNext = 0;
969 *flag = (unsigned char)sSav;
970 }
971 ATENABLE(s, atpgen_lock);
972 return 0;
973 }
974 }
975 atp->atp_socket_no = (short)sVal;
976 atp_inputQ[sVal] = gref;
977 if (flag == 0)
978 atp_pidM[sVal] = atp->atp_pid;
979 else if (*flag == 3) {
980 sNext = sVal + 1;
981 if (sNext > ATP_SOCKET_LAST)
982 sNext = 0;
983 }
984
985 ATENABLE(s, atpgen_lock);
986 return (int)sVal;
987 }
988
989 void atp_req_ind(atp, mioc)
990 register struct atp_state *atp;
991 register gbuf_t *mioc;
992 {
993 register struct atp_rcb *rcbp;
994 int s;
995
996 if ((rcbp = atp->atp_attached.head) != 0) {
997 gbuf_cont(mioc) = rcbp->rc_ioctl;
998 rcbp->rc_ioctl = NULL;
999 ATDISABLE(s, atp->atp_lock);
1000 if (rcbp->rc_xo) {
1001 ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
1002 rcbp->rc_state = RCB_NOTIFIED;
1003 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
1004 } else
1005 atp_rcb_free(rcbp);
1006 ATENABLE(s, atp->atp_lock);
1007 if (gbuf_cont(mioc))
1008 ((ioc_t *)gbuf_rptr(mioc))->ioc_count = gbuf_msgsize(gbuf_cont(mioc));
1009 else
1010 ((ioc_t *)gbuf_rptr(mioc))->ioc_count = 0;
1011 asp_ack_reply(atp->atp_gref, mioc);
1012 } else
1013 gbuf_freeb(mioc);
1014 }
1015
1016 void atp_rsp_ind(trp, mioc)
1017 register struct atp_trans *trp;
1018 register gbuf_t *mioc;
1019 {
1020 register struct atp_state *atp = trp->tr_queue;
1021 register int err;
1022 gbuf_t *xm = 0;
1023
1024 err = 0;
1025 {
1026 switch (trp->tr_state) {
1027 case TRANS_DONE:
1028 if (asp_pack_bdsp(trp, &xm) < 0)
1029 err = EFAULT;
1030 gbuf_cont(mioc) = trp->tr_xmt;
1031 trp->tr_xmt = NULL;
1032 break;
1033
1034 case TRANS_FAILED:
1035 err = ETIMEDOUT;
1036 break;
1037
1038 default:
1039 err = ENOENT;
1040 break;
1041 }
1042 atp_free(trp);
1043
1044 if (err) {
1045 dPrintf(D_M_ATP, D_L_ERROR,
1046 ("atp_rsp_ind: TRANSACTION error\n"));
1047 atp_iocnak(atp, mioc, err);
1048 } else {
1049 gbuf_cont(gbuf_cont(mioc)) = xm;
1050 atp_iocack(atp, mioc);
1051 }
1052 }
1053 }
1054
1055 void atp_cancel_req(gref, tid)
1056 gref_t *gref;
1057 unsigned short tid;
1058 {
1059 int s;
1060 struct atp_state *atp;
1061 struct atp_trans *trp;
1062
1063 atp = (struct atp_state *)gref->info;
1064 if (atp->dflag)
1065 atp = (struct atp_state *)atp->atp_msgq;
1066
1067 ATDISABLE(s, atp->atp_lock);
1068 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
1069 if (trp->tr_tid == tid)
1070 break;
1071 }
1072 ATENABLE(s, atp->atp_lock);
1073 if (trp != NULL)
1074 atp_free(trp);
1075 }
1076
1077 /*
1078 * remove atp from the use list
1079 */
1080 void
1081 atp_dequeue_atp(atp)
1082 struct atp_state *atp;
1083 {
1084 int s;
1085
1086 ATDISABLE(s, atpall_lock);
1087 if (atp == atp_used_list) {
1088 if ((atp_used_list = atp->atp_trans_waiting) != 0)
1089 atp->atp_trans_waiting->atp_rcb_waiting = 0;
1090 } else if (atp->atp_rcb_waiting) {
1091 if ((atp->atp_rcb_waiting->atp_trans_waiting
1092 = atp->atp_trans_waiting) != 0)
1093 atp->atp_trans_waiting->atp_rcb_waiting = atp->atp_rcb_waiting;
1094 }
1095
1096 atp->atp_trans_waiting = 0;
1097 atp->atp_rcb_waiting = 0;
1098 ATENABLE(s, atpall_lock);
1099 }
1100
1101 void
1102 atp_timout(func, trp, ticks)
1103 void (*func)();
1104 struct atp_trans *trp;
1105 int ticks;
1106 {
1107 int s;
1108 unsigned int sum;
1109 struct atp_trans *curr_trp, *prev_trp;
1110
1111 ATDISABLE(s, atptmo_lock);
1112 if (trp->tr_tmo_func) {
1113 ATENABLE(s, atptmo_lock);
1114 return;
1115 }
1116
1117 trp->tr_tmo_func = func;
1118 trp->tr_tmo_delta = 1+(ticks>>5);
1119
1120 if (trp_tmo_list == 0) {
1121 trp->tr_tmo_next = trp->tr_tmo_prev = 0;
1122 trp_tmo_list = trp;
1123 ATENABLE(s, atptmo_lock);
1124 return;
1125 }
1126
1127 prev_trp = 0;
1128 curr_trp = trp_tmo_list;
1129 sum = 0;
1130
1131 while (1) {
1132 sum += curr_trp->tr_tmo_delta;
1133 if (sum > trp->tr_tmo_delta) {
1134 sum -= curr_trp->tr_tmo_delta;
1135 trp->tr_tmo_delta -= sum;
1136 curr_trp->tr_tmo_delta -= trp->tr_tmo_delta;
1137 break;
1138 }
1139 prev_trp = curr_trp;
1140 if ((curr_trp = curr_trp->tr_tmo_next) == 0) {
1141 trp->tr_tmo_delta -= sum;
1142 break;
1143 }
1144 }
1145
1146 if (prev_trp) {
1147 trp->tr_tmo_prev = prev_trp;
1148 if ((trp->tr_tmo_next = prev_trp->tr_tmo_next) != 0)
1149 prev_trp->tr_tmo_next->tr_tmo_prev = trp;
1150 prev_trp->tr_tmo_next = trp;
1151 } else {
1152 trp->tr_tmo_prev = 0;
1153 trp->tr_tmo_next = trp_tmo_list;
1154 trp_tmo_list->tr_tmo_prev = trp;
1155 trp_tmo_list = trp;
1156 }
1157 ATENABLE(s, atptmo_lock);
1158 }
1159
1160 void
1161 atp_untimout(func, trp)
1162 void (*func)();
1163 struct atp_trans *trp;
1164 {
1165 int s;
1166
1167 ATDISABLE(s, atptmo_lock);
1168 if (trp->tr_tmo_func == 0) {
1169 ATENABLE(s, atptmo_lock);
1170 return;
1171 }
1172
1173 if (trp_tmo_list == trp) {
1174 if ((trp_tmo_list = trp->tr_tmo_next) != 0) {
1175 trp_tmo_list->tr_tmo_prev = 0;
1176 trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
1177 }
1178 } else {
1179 if ((trp->tr_tmo_prev->tr_tmo_next = trp->tr_tmo_next) != 0) {
1180 trp->tr_tmo_next->tr_tmo_prev = trp->tr_tmo_prev;
1181 trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
1182 }
1183 }
1184 trp->tr_tmo_func = 0;
1185 ATENABLE(s, atptmo_lock);
1186 }
1187
1188 void
1189 atp_trp_clock_funnel(arg)
1190 void *arg;
1191 {
1192 thread_funnel_set(network_flock, TRUE);
1193 atp_trp_clock(arg);
1194 thread_funnel_set(network_flock, FALSE);
1195 }
1196
1197 void
1198 atp_trp_clock(arg)
1199 void *arg;
1200 {
1201 int s;
1202 struct atp_trans *trp;
1203 void (*tr_tmo_func)();
1204
1205 ATDISABLE(s, atptmo_lock);
1206 if (trp_tmo_list)
1207 trp_tmo_list->tr_tmo_delta--;
1208 while (((trp = trp_tmo_list) != 0) && (trp_tmo_list->tr_tmo_delta == 0)) {
1209 if ((trp_tmo_list = trp->tr_tmo_next) != 0)
1210 trp_tmo_list->tr_tmo_prev = 0;
1211 if ((tr_tmo_func = trp->tr_tmo_func) != 0) {
1212 trp->tr_tmo_func = 0;
1213 ATENABLE(s, atptmo_lock);
1214 (*tr_tmo_func)(trp);
1215 ATDISABLE(s, atptmo_lock);
1216 }
1217 }
1218 ATENABLE(s, atptmo_lock);
1219
1220 timeout(atp_trp_clock_funnel, (void *)arg, (1<<5));
1221 }
1222
1223 void
1224 atp_send_req(gref, mioc)
1225 gref_t *gref;
1226 gbuf_t *mioc;
1227 {
1228 register struct atp_state *atp;
1229 register struct atp_trans *trp;
1230 register ioc_t *iocbp;
1231 register at_atp_t *athp;
1232 register at_ddp_t *ddp;
1233 gbuf_t *m, *m2, *bds;
1234 struct atp_set_default *sdb;
1235 int s, old;
1236 unsigned int timer;
1237
1238 atp = (struct atp_state *)((struct atp_state *)gref->info)->atp_msgq;
1239 iocbp = (ioc_t *)gbuf_rptr(mioc);
1240
1241 if ((trp = atp_trans_alloc(atp)) == NULL) {
1242 l_retry:
1243 ((asp_scb_t *)gref->info)->stat_msg = mioc;
1244 iocbp->ioc_private = (void *)gref;
1245 timeout(atp_retry_req, mioc, 10);
1246 return;
1247 }
1248
1249 m2 = gbuf_cont(mioc);
1250 if ((bds = gbuf_dupb(m2)) == NULL) {
1251 atp_trans_free(trp);
1252 goto l_retry;
1253 }
1254 gbuf_rinc(m2,atpBDSsize);
1255 gbuf_wset(bds,atpBDSsize);
1256 iocbp->ioc_count -= atpBDSsize;
1257 gbuf_cont(m2) = NULL;
1258
1259 old = iocbp->ioc_cmd;
1260 iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST;
1261 sdb = (struct atp_set_default *)gbuf_rptr(m2);
1262
1263 /*
1264 * The at_snd_req library routine multiplies seconds by 100.
1265 * We need to divide by 100 in order to obtain the timer.
1266 */
1267 if ((timer = (sdb->def_rate * HZ)/100) == 0)
1268 timer = HZ;
1269 iocbp->ioc_count -= sizeof(struct atp_set_default);
1270 gbuf_rinc(m2,sizeof(struct atp_set_default));
1271
1272 trp->tr_retry = sdb->def_retries;
1273 trp->tr_timeout = timer;
1274 trp->tr_bdsp = bds;
1275 trp->tr_tid = atp_tid(atp);
1276 trp->tr_xmt = mioc;
1277
1278 /*
1279 * Now fill in the header (and remember the bits
1280 * we need to know)
1281 */
1282 athp = AT_ATP_HDR(m2);
1283 athp->cmd = ATP_CMD_TREQ;
1284 UAS_ASSIGN(athp->tid, trp->tr_tid);
1285 athp->eom = 0;
1286 athp->sts = 0;
1287 trp->tr_xo = athp->xo;
1288 trp->tr_bitmap = athp->bitmap;
1289 ddp = AT_DDP_HDR(m2);
1290 ddp->type = DDP_ATP;
1291 ddp->src_socket = (at_socket)atp->atp_socket_no;
1292 trp->tr_socket.socket = ddp->dst_socket;
1293 trp->tr_socket.node = ddp->dst_node;
1294 trp->tr_socket.net = NET_VALUE(ddp->dst_net);
1295 trp->tr_local_socket = atp->atp_socket_no;
1296 trp->tr_local_node = ddp->src_node;
1297 NET_NET(trp->tr_local_net, ddp->src_net);
1298
1299 #ifdef NOT_YET
1300 /* save the local information in the gref */
1301 atp->atp_gref->laddr.s_net = NET_VALUE(ddp->src_net);
1302 atp->atp_gref->laddr.s_node = ddp->src_node;
1303 atp->atp_gref->lport = ddp->src_node;
1304 atp->atp_gref->ddptype = DDP_ATP;
1305 #endif
1306
1307 /*
1308 * Put us in the transaction waiting queue
1309 */
1310 ATDISABLE(s, atp->atp_lock);
1311 ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
1312 ATENABLE(s, atp->atp_lock);
1313
1314 /*
1315 * Send the message and set the timer
1316 */
1317 m = (gbuf_t *)copy_pkt(m2, sizeof(llc_header_t));
1318 if (!trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo)
1319 atp_x_done(trp); /* no reason to tie up resources */
1320 else
1321 atp_timout(atp_req_timeout, trp, trp->tr_timeout);
1322 if (m) {
1323 trace_mbufs(D_M_ATP_LOW, " s", m);
1324 DDP_OUTPUT(m);
1325 }
1326 } /* atp_send_req */
1327
1328 void atp_retry_req(m)
1329 gbuf_t *m;
1330 {
1331 gref_t *gref;
1332 boolean_t funnel_state;
1333
1334 funnel_state = thread_funnel_set(network_flock, TRUE);
1335
1336 gref = (gref_t *)((ioc_t *)gbuf_rptr(m))->ioc_private;
1337 if (gref->info) {
1338 ((asp_scb_t *)gref->info)->stat_msg = 0;
1339 atp_send_req(gref, m);
1340 }
1341 (void) thread_funnel_set(network_flock, FALSE);
1342 }
1343
1344 void atp_send_rsp(gref, m, wait)
1345 gref_t *gref;
1346 gbuf_t *m;
1347 int wait;
1348 {
1349 register struct atp_state *atp;
1350 register struct atp_rcb *rcbp;
1351 register at_atp_t *athp;
1352 register at_ddp_t *ddp;
1353 int s, xcnt;
1354
1355 atp = (struct atp_state *)gref->info;
1356 if (atp->dflag)
1357 atp = (struct atp_state *)atp->atp_msgq;
1358 ddp = AT_DDP_HDR(m);
1359 athp = AT_ATP_HDR(m);
1360
1361 /*
1362 * search for the corresponding rcb
1363 */
1364 ATDISABLE(s, atp->atp_lock);
1365 for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
1366 if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) &&
1367 (rcbp->rc_socket.node == ddp->dst_node) &&
1368 (rcbp->rc_socket.net == NET_VALUE(ddp->dst_net)) &&
1369 (rcbp->rc_socket.socket == ddp->dst_socket) )
1370 break;
1371 }
1372
1373 /*
1374 * If it has already been sent then drop the request
1375 */
1376 if ((rcbp && (rcbp->rc_state != RCB_NOTIFIED)) ||
1377 (rcbp == NULL && athp->xo) ) {
1378 ATENABLE(s, atp->atp_lock);
1379 gbuf_freem(m);
1380 return;
1381 }
1382 ATENABLE(s, atp->atp_lock);
1383
1384 if (rcbp == NULL) { /* a response is being sent for an ALO transaction */
1385 if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
1386 gbuf_freem(m);
1387 return;
1388 }
1389 rcbp->rc_ioctl = 0;
1390 rcbp->rc_socket.socket = ddp->dst_socket;
1391 rcbp->rc_socket.node = ddp->dst_node;
1392 rcbp->rc_socket.net = NET_VALUE(ddp->dst_net);
1393 rcbp->rc_tid = UAS_VALUE(athp->tid);
1394 rcbp->rc_bitmap = 0xff;
1395 rcbp->rc_xo = 0;
1396 rcbp->rc_state = RCB_RESPONSE_FULL;
1397 ATDISABLE(s, atp->atp_lock);
1398 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
1399 ATENABLE(s, atp->atp_lock);
1400 }
1401 else if (ddp->src_node == 0) {
1402 NET_NET(ddp->src_net, rcbp->rc_local_net);
1403 ddp->src_node = rcbp->rc_local_node;
1404 }
1405
1406 xcnt = get_bds_entries(m);
1407 s = atp_unpack_bdsp(atp, m, rcbp, xcnt, wait);
1408 if (s == 0)
1409 atp_send_replies(atp, rcbp);
1410 } /* atp_send_rsp */
1411
1412 int asp_pack_bdsp(trp, xm)
1413 register struct atp_trans *trp;
1414 gbuf_t **xm;
1415 {
1416 register struct atpBDS *bdsp;
1417 register gbuf_t *m, *m2;
1418 register int i;
1419 gbuf_t *m_prev, *m_head = 0;
1420
1421 dPrintf(D_M_ATP, D_L_INFO, ("asp_pack_bdsp: socket=%d\n",
1422 trp->tr_queue->atp_socket_no));
1423
1424 if ((m2 = trp->tr_bdsp) == NULL)
1425 return 0;
1426 trp->tr_bdsp = NULL;
1427 bdsp = (struct atpBDS *)gbuf_rptr(m2);
1428
1429 for (i = 0; (i < ATP_TRESP_MAX &&
1430 bdsp < (struct atpBDS *)(gbuf_wptr(m2))); i++) {
1431 if ((m = trp->tr_rcv[i]) == NULL)
1432 break;
1433 if (i == 0) {
1434 /* discard ddp hdr on first packet */
1435 gbuf_rinc(m,DDP_X_HDR_SIZE);
1436 }
1437
1438 UAL_UAL(bdsp->bdsUserData, (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
1439 gbuf_rinc(m, ATP_HDR_SIZE);
1440
1441 if (UAL_VALUE(bdsp->bdsBuffAddr)) {
1442 short tmp;
1443
1444 /* user expects data back */
1445 m = gbuf_strip(m);
1446 if (m_head == 0)
1447 m_head = m;
1448 else
1449 gbuf_cont(m_prev) = m;
1450 if (m) {
1451 tmp = (short)gbuf_len(m);
1452 while (gbuf_cont(m)) {
1453 m = gbuf_cont(m);
1454 tmp += (short)(gbuf_len(m));
1455 }
1456 m_prev = m;
1457 }
1458 UAS_ASSIGN(bdsp->bdsDataSz, tmp);
1459 }
1460 trp->tr_rcv[i] = NULL;
1461 bdsp++;
1462
1463 }
1464 /*
1465 * report the number of packets
1466 */
1467 UAS_ASSIGN(((struct atpBDS *)gbuf_rptr(m2))->bdsBuffSz, i);
1468
1469 if (trp->tr_xmt) /* an ioctl block is still held? */
1470 gbuf_cont(trp->tr_xmt) = m2;
1471 else
1472 trp->tr_xmt = m2;
1473
1474 if (m_head)
1475 *xm = m_head;
1476 else
1477 *xm = 0;
1478
1479 dPrintf(D_M_ATP, D_L_INFO, (" : size=%d\n",
1480 gbuf_msgsize(*xm)));
1481
1482 return 0;
1483 }
1484
1485 /*
1486 * The following routines are direct entries from system
1487 * calls to allow fast sending and recving of ATP data.
1488 */
1489
1490 int
1491 _ATPsndreq(fd, buf, len, nowait, err, proc)
1492 int fd;
1493 unsigned char *buf;
1494 int len;
1495 int nowait;
1496 int *err;
1497 void *proc;
1498 {
1499 gref_t *gref;
1500 int s, rc;
1501 unsigned short tid;
1502 unsigned int timer;
1503 register struct atp_state *atp;
1504 register struct atp_trans *trp;
1505 register ioc_t *iocbp;
1506 register at_atp_t *athp;
1507 register at_ddp_t *ddp;
1508 struct atp_set_default *sdb;
1509 gbuf_t *m2, *m, *mioc;
1510 char bds[atpBDSsize];
1511
1512 if ((*err = atalk_getref(0, fd, &gref, proc)) != 0)
1513 return -1;
1514
1515 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1516 || (atp->atp_flags & ATP_CLOSING)) {
1517 dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
1518 (u_int) gref, gref->pid));
1519
1520 *err = EINVAL;
1521 return -1;
1522 }
1523
1524 while ((mioc = gbuf_alloc(sizeof(ioc_t), PRI_MED)) == 0) {
1525 ATDISABLE(s, atp->atp_delay_lock);
1526 rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atpmioc", 10);
1527 ATENABLE(s, atp->atp_delay_lock);
1528 if (rc != 0) {
1529 *err = rc;
1530 return -1;
1531 }
1532
1533 }
1534 gbuf_wset(mioc,sizeof(ioc_t));
1535 len -= atpBDSsize;
1536 while ((m2 = gbuf_alloc(len, PRI_MED)) == 0) {
1537 ATDISABLE(s, atp->atp_delay_lock);
1538 rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atpm2", 10);
1539 ATENABLE(s, atp->atp_delay_lock);
1540 if (rc != 0) {
1541 gbuf_freeb(mioc);
1542 *err = rc;
1543 return -1;
1544 }
1545 }
1546 gbuf_wset(m2, len);
1547 gbuf_cont(mioc) = m2;
1548 if (((*err = copyin((caddr_t)buf, (caddr_t)bds, atpBDSsize)) != 0)
1549 || ((*err = copyin((caddr_t)&buf[atpBDSsize],
1550 (caddr_t)gbuf_rptr(m2), len)) != 0)) {
1551 gbuf_freem(mioc);
1552 return -1;
1553 }
1554 gbuf_set_type(mioc, MSG_IOCTL);
1555 iocbp = (ioc_t *)gbuf_rptr(mioc);
1556 iocbp->ioc_count = len;
1557 iocbp->ioc_cmd = nowait ? AT_ATP_ISSUE_REQUEST_NOTE : AT_ATP_ISSUE_REQUEST;
1558 sdb = (struct atp_set_default *)gbuf_rptr(m2);
1559
1560 /*
1561 * The at_snd_req library routine multiplies seconds by 100.
1562 * We need to divide by 100 in order to obtain the timer.
1563 */
1564 if ((timer = (sdb->def_rate * HZ)/100) == 0)
1565 timer = HZ;
1566 iocbp->ioc_count -= sizeof(struct atp_set_default);
1567 gbuf_rinc(m2,sizeof(struct atp_set_default));
1568
1569 /*
1570 * allocate and set up the transaction record
1571 */
1572 while ((trp = atp_trans_alloc(atp)) == 0) {
1573 ATDISABLE(s, atp->atp_delay_lock);
1574 rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atptrp", 10);
1575 ATENABLE(s, atp->atp_delay_lock);
1576 if (rc != 0) {
1577 gbuf_freem(mioc);
1578 *err = rc;
1579 return -1;
1580 }
1581 }
1582 trp->tr_retry = sdb->def_retries;
1583 trp->tr_timeout = timer;
1584 trp->tr_bdsp = NULL;
1585 trp->tr_tid = atp_tid(atp);
1586 tid = trp->tr_tid;
1587
1588 /*
1589 * remember the IOCTL packet so we can ack it
1590 * later
1591 */
1592 trp->tr_xmt = mioc;
1593
1594 /*
1595 * Now fill in the header (and remember the bits
1596 * we need to know)
1597 */
1598 athp = AT_ATP_HDR(m2);
1599 athp->cmd = ATP_CMD_TREQ;
1600 UAS_ASSIGN(athp->tid, trp->tr_tid);
1601 athp->eom = 0;
1602 athp->sts = 0;
1603 trp->tr_xo = athp->xo;
1604 trp->tr_bitmap = athp->bitmap;
1605 ddp = AT_DDP_HDR(m2);
1606 ddp->type = DDP_ATP;
1607 ddp->src_socket = (at_socket)atp->atp_socket_no;
1608 ddp->src_node = 0;
1609 trp->tr_socket.socket = ddp->dst_socket;
1610 trp->tr_socket.node = ddp->dst_node;
1611 trp->tr_socket.net = NET_VALUE(ddp->dst_net);
1612 trp->tr_local_socket = atp->atp_socket_no;
1613
1614 #ifdef NOT_YET
1615 /* save the local information in the gref */
1616 atp->atp_gref->laddr.s_net = NET_VALUE(ddp->src_net);
1617 atp->atp_gref->laddr.s_node = ddp->src_node;
1618 atp->atp_gref->lport = ddp->src_node;
1619 atp->atp_gref->ddptype = DDP_ATP;
1620 #endif
1621
1622 /*
1623 * Put us in the transaction waiting queue
1624 */
1625 ATDISABLE(s, atp->atp_lock);
1626 ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
1627 ATENABLE(s, atp->atp_lock);
1628
1629 /*
1630 * Send the message and set the timer
1631 */
1632 m = (gbuf_t *)copy_pkt(m2, sizeof(llc_header_t));
1633 if ( !trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo)
1634 atp_x_done(trp); /* no reason to tie up resources */
1635 else
1636 atp_timout(atp_req_timeout, trp, trp->tr_timeout);
1637 if (m)
1638 DDP_OUTPUT(m);
1639
1640 if (nowait)
1641 return (int)tid;
1642
1643 /*
1644 * wait for the transaction to complete
1645 */
1646 ATDISABLE(s, trp->tr_lock);
1647 while ((trp->tr_state != TRANS_DONE) && (trp->tr_state != TRANS_FAILED) &&
1648 (trp->tr_state != TRANS_ABORTING)) {
1649 trp->tr_rsp_wait = 1;
1650 rc = tsleep(&trp->tr_event, PSOCK | PCATCH, "atpsndreq", 0);
1651 if (rc != 0) {
1652 trp->tr_rsp_wait = 0;
1653 ATENABLE(s, trp->tr_lock);
1654 *err = rc;
1655 return -1;
1656 }
1657 }
1658 trp->tr_rsp_wait = 0;
1659 ATENABLE(s, trp->tr_lock);
1660
1661
1662 if (trp->tr_state == TRANS_FAILED || trp->tr_state == TRANS_ABORTING) {
1663 /*
1664 * transaction timed out, return error
1665 */
1666 atp_free(trp);
1667 *err = ETIMEDOUT;
1668 return -1;
1669 }
1670
1671 /*
1672 * copy out the recv data
1673 */
1674 atp_pack_bdsp(trp, bds);
1675
1676 /*
1677 * copyout the result info
1678 */
1679 copyout((caddr_t)bds, (caddr_t)buf, atpBDSsize);
1680
1681 atp_free(trp);
1682
1683 return (int)tid;
1684 } /* _ATPsndreq */
1685
1686 int
1687 _ATPsndrsp(fd, respbuff, resplen, datalen, err, proc)
1688 int fd;
1689 unsigned char *respbuff;
1690 int resplen;
1691 int datalen;
1692 int *err;
1693 void *proc;
1694 {
1695 gref_t *gref;
1696 int s, rc;
1697 long bufaddr;
1698 gbuf_t *m, *mdata;
1699 register short len;
1700 register int size;
1701 register struct atp_state *atp;
1702 register struct atpBDS *bdsp;
1703 register char *buf;
1704
1705 if ((*err = atalk_getref(0, fd, &gref, proc)) != 0)
1706 return -1;
1707
1708 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1709 || (atp->atp_flags & ATP_CLOSING)) {
1710 dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
1711 (u_int) gref, gref->pid));
1712
1713 *err = EINVAL;
1714 return -1;
1715 }
1716
1717 /*
1718 * allocate buffer and copy in the response info
1719 */
1720 if ((m = gbuf_alloc_wait(resplen, TRUE)) == 0) {
1721 *err = ENOMEM;
1722 return -1;
1723 }
1724 if ((*err = copyin((caddr_t)respbuff, (caddr_t)gbuf_rptr(m), resplen)) != 0) {
1725 gbuf_freeb(m);
1726 return -1;
1727 }
1728 gbuf_wset(m,resplen);
1729 ((at_ddp_t *)gbuf_rptr(m))->src_node = 0;
1730 bdsp = (struct atpBDS *)(gbuf_rptr(m) + TOTAL_ATP_HDR_SIZE);
1731 if ((resplen == TOTAL_ATP_HDR_SIZE) || ((len = UAS_VALUE(bdsp->bdsDataSz)) == 1))
1732 len = 0;
1733 else
1734 len = 16 * sizeof(gbuf_t);
1735
1736 /*
1737 * allocate buffer and copy in the response data
1738 */
1739 if ((mdata = gbuf_alloc_wait(datalen+len, TRUE)) == 0) {
1740 gbuf_freem(m);
1741 *err = ENOMEM;
1742 return -1;
1743 }
1744 gbuf_cont(m) = mdata;
1745 for (size=0; bdsp < (struct atpBDS *)gbuf_wptr(m); bdsp++) {
1746 if ((bufaddr = UAL_VALUE(bdsp->bdsBuffAddr)) != 0) {
1747 len = UAS_VALUE(bdsp->bdsBuffSz);
1748 buf = (char *)bufaddr;
1749 if ((*err = copyin((caddr_t)buf,
1750 (caddr_t)&gbuf_rptr(mdata)[size], len)) != 0) {
1751 gbuf_freem(m);
1752 return -1;
1753 }
1754 size += len;
1755 }
1756 }
1757 gbuf_wset(mdata,size);
1758
1759 atp_send_rsp(gref, m, TRUE);
1760 return 0;
1761 }
1762
1763 int
1764 _ATPgetreq(fd, buf, buflen, err, proc)
1765 int fd;
1766 unsigned char *buf;
1767 int buflen;
1768 int *err;
1769 void *proc;
1770 {
1771 gref_t *gref;
1772 register struct atp_state *atp;
1773 register struct atp_rcb *rcbp;
1774 register gbuf_t *m, *m_head;
1775 int s, size, len;
1776
1777 if ((*err = atalk_getref(0, fd, &gref, proc)) != 0)
1778 return -1;
1779
1780 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1781 || (atp->atp_flags & ATP_CLOSING)) {
1782 dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
1783 (u_int) gref, gref->pid));
1784 *err = EINVAL;
1785 return -1;
1786 }
1787
1788 ATDISABLE(s, atp->atp_lock);
1789 if ((rcbp = atp->atp_attached.head) != NULL) {
1790 /*
1791 * Got one, move it to the active response Q
1792 */
1793 m_head = rcbp->rc_ioctl;
1794 rcbp->rc_ioctl = NULL;
1795
1796 if (rcbp->rc_xo) {
1797 ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
1798 rcbp->rc_state = RCB_NOTIFIED;
1799 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
1800 } else {
1801 /* detach rcbp from attached queue,
1802 * and free any outstanding resources
1803 */
1804 atp_rcb_free(rcbp);
1805 }
1806 ATENABLE(s, atp->atp_lock);
1807
1808 /*
1809 * copyout the request data, including the protocol header
1810 */
1811 for (size=0, m=m_head; m; m = gbuf_cont(m)) {
1812 if ((len = gbuf_len(m)) > buflen)
1813 len = buflen;
1814 copyout((caddr_t)gbuf_rptr(m), (caddr_t)&buf[size], len);
1815 size += len;
1816 if ((buflen -= len) == 0)
1817 break;
1818 }
1819 gbuf_freem(m_head);
1820
1821 return size;
1822 }
1823 ATENABLE(s, atp->atp_lock);
1824
1825 return -1;
1826 }
1827
1828 int
1829 _ATPgetrsp(fd, bdsp, err, proc)
1830 int fd;
1831 struct atpBDS *bdsp;
1832 int *err;
1833 void *proc;
1834 {
1835 gref_t *gref;
1836 register struct atp_state *atp;
1837 register struct atp_trans *trp;
1838 int s, tid;
1839 char bds[atpBDSsize];
1840
1841 if ((*err = atalk_getref(0, fd, &gref, proc)) != 0)
1842 return -1;
1843
1844 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1845 || (atp->atp_flags & ATP_CLOSING)) {
1846 dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
1847 (u_int) gref, gref->pid));
1848 *err = EINVAL;
1849 return -1;
1850 }
1851
1852 ATDISABLE(s, atp->atp_lock);
1853 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
1854 dPrintf(D_M_ATP, D_L_INFO,
1855 ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
1856 (u_int) atp, (u_int) trp, trp->tr_state));
1857
1858 switch (trp->tr_state) {
1859 case TRANS_DONE:
1860 ATENABLE(s, atp->atp_lock);
1861 if ((*err = copyin((caddr_t)bdsp,
1862 (caddr_t)bds, sizeof(bds))) != 0)
1863 return -1;
1864 atp_pack_bdsp(trp, bds);
1865 tid = (int)trp->tr_tid;
1866 atp_free(trp);
1867 copyout((caddr_t)bds, (caddr_t)bdsp, sizeof(bds));
1868 return tid;
1869
1870 case TRANS_FAILED:
1871 /*
1872 * transaction timed out, return error
1873 */
1874 ATENABLE(s, atp->atp_lock);
1875 atp_free(trp);
1876 *err = ETIMEDOUT;
1877 return -1;
1878
1879 default:
1880 continue;
1881 }
1882 }
1883 ATENABLE(s, atp->atp_lock);
1884
1885 *err = EINVAL;
1886 return -1;
1887 }
1888
1889 void
1890 atp_drop_req(gref, m)
1891 gref_t *gref;
1892 gbuf_t *m;
1893 {
1894 int s;
1895 struct atp_state *atp;
1896 struct atp_rcb *rcbp;
1897 at_atp_t *athp;
1898 at_ddp_t *ddp;
1899
1900 atp = (struct atp_state *)gref->info;
1901 if (atp->dflag)
1902 atp = (struct atp_state *)atp->atp_msgq;
1903 ddp = AT_DDP_HDR(m);
1904 athp = AT_ATP_HDR(m);
1905
1906 /*
1907 * search for the corresponding rcb
1908 */
1909 ATDISABLE(s, atp->atp_lock);
1910 for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
1911 if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) &&
1912 (rcbp->rc_socket.node == ddp->src_node) &&
1913 (rcbp->rc_socket.net == NET_VALUE(ddp->src_net)) &&
1914 (rcbp->rc_socket.socket == ddp->src_socket) )
1915 break;
1916 }
1917
1918 /*
1919 * drop the request
1920 */
1921 if (rcbp)
1922 atp_rcb_free(rcbp);
1923 ATENABLE(s, atp->atp_lock);
1924
1925 gbuf_freem(m);
1926 }