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