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