]> git.saurik.com Git - apple/xnu.git/blame - bsd/netat/atp_write.c
xnu-792.2.4.tar.gz
[apple/xnu.git] / bsd / netat / atp_write.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
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.
1c79356b 11 *
e5568f75
A
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
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
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.
1c79356b
A
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>
91447636 41#include <kern/locks.h>
1c79356b
A
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
60static 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
68static void atp_pack_bdsp(struct atp_trans *, struct atpBDS *);
69static int atp_unpack_bdsp(struct atp_state *, gbuf_t *, struct atp_rcb *,
70 int, int);
91447636 71void atp_trp_clock(), asp_clock(), asp_clock_locked(), atp_trp_clock_locked();;
1c79356b
A
72
73extern struct atp_rcb_qhead atp_need_rel;
74extern int atp_inited;
75extern struct atp_state *atp_used_list;
76extern asp_scb_t *scb_free_list;
77extern atlock_t atpgen_lock;
78extern atlock_t atpall_lock;
79extern atlock_t atptmo_lock;
80
81extern gbuf_t *scb_resource_m;
82extern gbuf_t *atp_resource_m;
83extern gref_t *atp_inputQ[];
84extern int atp_pidM[];
85extern at_ifaddr_t *ifID_home;
91447636 86extern lck_mtx_t * atalk_mutex;
1c79356b
A
87
88static struct atp_trans *trp_tmo_list;
89struct 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
98void 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
107void atp_unlink()
108{
91447636
A
109 untimeout(asp_clock_locked, (void *)&atp_inited);
110 untimeout(atp_trp_clock_locked, (void *)&atp_inited);
1c79356b
A
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
136void
137atp_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
416gbuf_t *atp_build_release(trp)
417register 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
452void 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;
55e303ae 457 int s_gen, s, cnt, err, offset, space;
1c79356b
A
458 unsigned char *m0_rptr = NULL, *m0_wptr = NULL;
459 register at_atp_t *athp;
460 register struct atpBDS *bdsp;
55e303ae 461 register gbuf_t *m2, *m1, *m0, *mhdr;
0b4e3aa0 462 caddr_t lastPage;
1c79356b
A
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 };
91447636 469 struct timeval timenow;
1c79356b
A
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);
1c79356b
A
500 if (gbuf_len(m) > TOTAL_ATP_HDR_SIZE)
501 bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
502 else
503 bdsp = 0;
55e303ae
A
504 offset = 0;
505 if (m0)
506 space = gbuf_msgsize(m0);
91447636
A
507 else
508 space = 0;
1c79356b 509 for (i = 0; i < cnt; i++) {
55e303ae
A
510 if (rcbp->rc_snd[i] == 0) {
511 if ((len = UAS_VALUE(bdsp->bdsBuffSz))) {
512 offset += len;
513 space -= len;
1c79356b 514 }
55e303ae
A
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;
1c79356b 539 }
55e303ae 540 }
0b4e3aa0 541
55e303ae
A
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;
1c79356b 557 }
55e303ae
A
558 /*
559 * on to the next frag
560 */
561 bdsp++;
de355530 562 }
1c79356b
A
563 if (mlist) {
564 ATENABLE(s, atp->atp_lock);
565 DDP_OUTPUT(mlist);
566 ATDISABLE(s, atp->atp_lock);
567 }
568
569nothing_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) {
91447636 591 getmicrouptime(&timenow);
1c79356b
A
592 ATDISABLE(s_gen, atpgen_lock);
593 if (rcbp->rc_timestamp == 0) {
91447636 594 rcbp->rc_timestamp = timenow.tv_sec;
1c79356b
A
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
607static void
608atp_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
616 dPrintf(D_M_ATP, D_L_INFO, ("atp_pack_bdsp: socket=%d\n",
617 trp->tr_queue->atp_socket_no));
618
619 for (i = 0; i < ATP_TRESP_MAX; i++, bdsp++) {
620 short bufsize = UAS_VALUE(bdsp->bdsBuffSz);
621 long bufaddr = UAL_VALUE(bdsp->bdsBuffAddr);
622
623 if ((m = trp->tr_rcv[i]) == NULL)
624 break;
625
626 /* discard ddp hdr on first packet */
627 if (i == 0)
628 gbuf_rinc(m,DDP_X_HDR_SIZE);
629
630 /* this field may contain control information even when
631 no data is present */
632 UAL_UAL(bdsp->bdsUserData,
633 (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
634 gbuf_rinc(m, ATP_HDR_SIZE);
635
636 if ((bufsize != 0) && (bufaddr != 0)) {
637 /* user expects data back */
638 short tmp = 0;
639 register char *buf = (char *)bufaddr;
640
641 while (m) {
642 short len = (short)(gbuf_len(m));
643 if (len) {
644 if (len > bufsize)
645 len = bufsize;
646 copyout((caddr_t)gbuf_rptr(m),
91447636 647 CAST_USER_ADDR_T(&buf[tmp]),
1c79356b
A
648 len);
649 bufsize -= len;
e5568f75 650 tmp += len;
1c79356b
A
651 }
652 m = gbuf_cont(m);
653 }
654
655 UAS_ASSIGN(bdsp->bdsDataSz, tmp);
656 datsize += (int)tmp;
657 }
658 gbuf_freem(trp->tr_rcv[i]);
659 trp->tr_rcv[i] = NULL;
660 }
661
662 /* report the number of packets */
663 UAS_ASSIGN(((struct atpBDS *)bdsbase)->bdsBuffSz, i);
664
665 dPrintf(D_M_ATP, D_L_INFO, (" : size=%d\n",
666 datsize));
667} /* atp_pack_bdsp */
668
669
55e303ae
A
670/* create an mbuf chain with mbuf packet headers for each ATP response packet
671 * to be sent. m contains the DDP hdr, ATP hdr, and and array of atpBDS structs.
672 * chained to m is an mbuf that contians the actual data pointed to by the atpBDS
673 * structs.
674 */
1c79356b
A
675static int
676atp_unpack_bdsp(atp, m, rcbp, cnt, wait)
677 struct atp_state *atp;
678 gbuf_t *m; /* ddp, atp and bdsp gbuf_t */
679 register struct atp_rcb *rcbp;
0b4e3aa0 680 register int cnt, wait;
1c79356b
A
681{
682 register struct atpBDS *bdsp;
55e303ae
A
683 register gbuf_t *m2, *m1, *m0, *mhdr;
684 caddr_t lastPage;
685 at_atp_t *athp;
686 int i, len, s_gen;
687 at_socket src_socket;
688
689 struct ddp_atp {
1c79356b
A
690 char ddp_atp_hdr[TOTAL_ATP_HDR_SIZE];
691 };
55e303ae
A
692 gbuf_t *mprev, *mlist = 0;
693 gbuf_t *rc_xmt[ATP_TRESP_MAX];
694 unsigned char *m0_rptr, *m0_wptr;
695 int err, offset, space;
91447636 696 struct timeval timenow;
1c79356b
A
697
698 /*
699 * get the user data structure pointer
700 */
701 bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
702
703 /*
704 * Guard against bogus count argument.
705 */
706 if ((unsigned) cnt > ATP_TRESP_MAX) {
707 dPrintf(D_M_ATP, D_L_ERROR,
708 ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt));
709 gbuf_freem(m);
710 return(EINVAL);
711 }
712 if ((src_socket = (at_socket)atp->atp_socket_no) == 0xFF) {
713 /* comparison was to -1, however src_socket is a u_char */
714 gbuf_freem(m);
715 return EPIPE;
716 }
717
718 m0 = gbuf_cont(m);
719 rcbp->rc_xmt = m;
720 rcbp->rc_pktcnt = cnt;
721 rcbp->rc_state = RCB_SENDING;
722 rcbp->rc_not_sent_bitmap = 0;
723
724 if (cnt <= 1) {
725 /*
726 * special case this to
727 * improve AFP write transactions to the server
728 */
729 rcbp->rc_pktcnt = 1;
730 if ((m2 = gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,
731 wait)) == NULL)
732 return 0;
733 gbuf_rinc(m2,AT_WR_OFFSET);
734 gbuf_wset(m2,TOTAL_ATP_HDR_SIZE);
735 *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m));
736 athp = AT_ATP_HDR(m2);
737 ATP_CLEAR_CONTROL(athp);
738 athp->cmd = ATP_CMD_TRESP;
739 athp->bitmap = 0;
740 athp->eom = 1; /* there's only 1 fragment */
741
742 /* *** why only if cnt > 0? *** */
743 if (cnt > 0)
744 UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
745 if (m0)
746 if (!append_copy((struct mbuf *)m2,
747 (struct mbuf *)m0, wait)) {
748 gbuf_freeb(m2);
749 return 0;
750 }
751 /*
752 * send the message and mark it as sent
753 */
754 AT_DDP_HDR(m2)->src_socket = src_socket;
755 dPrintf(D_M_ATP_LOW, D_L_INFO,
756 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
757 0,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(m2)),cnt));
758 mlist = m2;
759 goto l_send;
760 }
761
55e303ae
A
762 /* create an array of mbuf packet headers for the packets to be sent
763 * to contain the atp and ddp headers with room at the front for the
764 * datalink header.
765 */
1c79356b
A
766 for (i = 0; i < cnt; i++) {
767 /* all hdrs, packet data and dst addr storage */
768 if ((rc_xmt[i] =
55e303ae
A
769 gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE, wait)) == NULL) {
770 for (cnt = 0; cnt < i; cnt++)
771 if (rc_xmt[cnt])
772 gbuf_freeb(rc_xmt[cnt]);
773 return 0;
1c79356b
A
774 }
775 }
1c79356b 776
55e303ae
A
777 /* run through the atpBDS structs and create an mbuf for the data
778 * portion of each packet to be sent. these get chained to the mbufs
779 * containing the ATP and DDP headers. this code assumes that no ATP
780 * packet is contained in more than 2 mbufs (e.i crosses mbuf boundary
781 * no more than one time).
782 */
783 offset = 0;
784 if (m0)
785 space = gbuf_msgsize(m0);
786 for (i = 0; i < cnt; i++) { /* for each hdr mbuf */
787 mhdr = rc_xmt[i];
788 /* setup header fields */
789 gbuf_rinc(mhdr,AT_WR_OFFSET);
790 gbuf_wset(mhdr,TOTAL_ATP_HDR_SIZE);
791 *(struct ddp_atp *)(gbuf_rptr(mhdr))= *(struct ddp_atp *)(gbuf_rptr(m));
792 athp = AT_ATP_HDR(mhdr);
1c79356b
A
793 ATP_CLEAR_CONTROL(athp);
794 athp->cmd = ATP_CMD_TRESP;
795 athp->bitmap = i;
796 if (i == (cnt - 1))
797 athp->eom = 1; /* for the last fragment */
798 UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
55e303ae
A
799
800 if ((len = UAS_VALUE(bdsp->bdsBuffSz)) != 0 && m0 != 0 && space > 0) {
801 if ((m1 = m_copym(m0, offset, len, wait)) == 0) {
1c79356b
A
802 for (i = 0; i < cnt; i++)
803 if (rc_xmt[i])
804 gbuf_freem(rc_xmt[i]);
1c79356b
A
805 return 0;
806 }
55e303ae
A
807 gbuf_cont(mhdr) = m1;
808 space -= len;
809 offset += len;
0b4e3aa0 810 }
55e303ae
A
811
812 AT_DDP_HDR(mhdr)->src_socket = src_socket;
1c79356b
A
813 dPrintf(D_M_ATP_LOW,D_L_INFO,
814 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
55e303ae 815 i,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(mhdr)),cnt));
1c79356b 816 if (mlist)
55e303ae 817 gbuf_next(mprev) = mhdr;
1c79356b 818 else
55e303ae
A
819 mlist = mhdr;
820 mprev = mhdr;
1c79356b
A
821 /*
822 * on to the next frag
823 */
824 bdsp++;
825 }
1c79356b
A
826 /*
827 * send the message
828 */
829l_send:
830 if (rcbp->rc_xo) {
91447636 831 getmicrouptime(&timenow);
1c79356b
A
832 ATDISABLE(s_gen, atpgen_lock);
833 if (rcbp->rc_timestamp == 0) {
91447636 834 if ((rcbp->rc_timestamp = timenow.tv_sec) == 0)
1c79356b
A
835 rcbp->rc_timestamp = 1;
836 ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist);
837 }
838 ATENABLE(s_gen, atpgen_lock);
839 }
840
841 DDP_OUTPUT(mlist);
842 return 0;
55e303ae 843
1c79356b
A
844} /* atp_unpack_bdsp */
845
846#define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6)
14353aa8 847#define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
1c79356b
A
848static unsigned int sNext = 0;
849
850int atp_bind(gref, sVal, flag)
851 gref_t *gref;
852 unsigned int sVal;
853 unsigned char *flag;
854{
855 extern unsigned char asp_inpC[];
856 extern asp_scb_t *asp_scbQ[];
857 unsigned char inpC, sNextUsed = 0;
858 unsigned int sMin, sMax, sSav;
859 struct atp_state *atp;
860 int s;
861
862 atp = (struct atp_state *)gref->info;
863 if (atp->dflag)
864 atp = (struct atp_state *)atp->atp_msgq;
865
866 sMax = ATP_SOCKET_LAST;
867 sMin = ATP_SOCKET_FIRST;
868 ATDISABLE(s, atpgen_lock);
869 if (flag && (*flag == 3)) {
870 sMin += 40;
871 if (sMin < sNext) {
872 sMin = sNext;
873 sNextUsed = 1;
874 }
875 }
876
877 if ( (sVal != 0) &&
878 ((sVal > sMax) || (sVal < 2) || (sVal == 6) ||
879 (ddp_socket_inuse(sVal, DDP_ATP) &&
880 (atp_inputQ[sVal] != (gref_t *)1)))) {
881 ATENABLE(s, atpgen_lock);
882 return 0;
883 }
884
885 if (sVal == 0) {
886 inpC = 255;
887again:
888 for (sVal=sMin; sVal <= sMax; sVal++) {
889 if (!ddp_socket_inuse(sVal, DDP_ATP) ||
890 atp_inputQ[sVal] == (gref_t *)1)
891 break;
892 else if (flag && (*flag == 3) && asp_scbQ[sVal]) {
893 if ((asp_scbQ[sVal]->dflag == *flag)
894 && (asp_inpC[sVal] < inpC) ) {
895 inpC = asp_inpC[sVal];
896 sSav = sVal;
897 }
898 }
899 }
900 if (sVal > sMax) {
901 if (flag && (*flag == 3)) {
902 if (sNextUsed) {
903 sNextUsed = 0;
904 sMax = sNext - 1;
905 sMin = ATP_SOCKET_FIRST+40;
906 goto again;
907 }
908 sNext = 0;
909 *flag = (unsigned char)sSav;
910 }
911 ATENABLE(s, atpgen_lock);
912 return 0;
913 }
914 }
915 atp->atp_socket_no = (short)sVal;
916 atp_inputQ[sVal] = gref;
917 if (flag == 0)
918 atp_pidM[sVal] = atp->atp_pid;
919 else if (*flag == 3) {
920 sNext = sVal + 1;
921 if (sNext > ATP_SOCKET_LAST)
922 sNext = 0;
923 }
924
925 ATENABLE(s, atpgen_lock);
926 return (int)sVal;
927}
928
929void atp_req_ind(atp, mioc)
930 register struct atp_state *atp;
931 register gbuf_t *mioc;
932{
933 register struct atp_rcb *rcbp;
934 int s;
935
936 if ((rcbp = atp->atp_attached.head) != 0) {
937 gbuf_cont(mioc) = rcbp->rc_ioctl;
938 rcbp->rc_ioctl = NULL;
939 ATDISABLE(s, atp->atp_lock);
940 if (rcbp->rc_xo) {
941 ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
942 rcbp->rc_state = RCB_NOTIFIED;
943 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
944 } else
945 atp_rcb_free(rcbp);
946 ATENABLE(s, atp->atp_lock);
947 if (gbuf_cont(mioc))
948 ((ioc_t *)gbuf_rptr(mioc))->ioc_count = gbuf_msgsize(gbuf_cont(mioc));
949 else
950 ((ioc_t *)gbuf_rptr(mioc))->ioc_count = 0;
951 asp_ack_reply(atp->atp_gref, mioc);
952 } else
953 gbuf_freeb(mioc);
954}
955
956void atp_rsp_ind(trp, mioc)
957 register struct atp_trans *trp;
958 register gbuf_t *mioc;
959{
960 register struct atp_state *atp = trp->tr_queue;
961 register int err;
962 gbuf_t *xm = 0;
963
964 err = 0;
965 {
966 switch (trp->tr_state) {
967 case TRANS_DONE:
968 if (asp_pack_bdsp(trp, &xm) < 0)
969 err = EFAULT;
970 gbuf_cont(mioc) = trp->tr_xmt;
971 trp->tr_xmt = NULL;
972 break;
973
974 case TRANS_FAILED:
975 err = ETIMEDOUT;
976 break;
977
978 default:
979 err = ENOENT;
980 break;
981 }
982 atp_free(trp);
983
984 if (err) {
985 dPrintf(D_M_ATP, D_L_ERROR,
986 ("atp_rsp_ind: TRANSACTION error\n"));
987 atp_iocnak(atp, mioc, err);
988 } else {
989 gbuf_cont(gbuf_cont(mioc)) = xm;
990 atp_iocack(atp, mioc);
991 }
992 }
993}
994
995void atp_cancel_req(gref, tid)
996 gref_t *gref;
997 unsigned short tid;
998{
999 int s;
1000 struct atp_state *atp;
1001 struct atp_trans *trp;
1002
1003 atp = (struct atp_state *)gref->info;
1004 if (atp->dflag)
1005 atp = (struct atp_state *)atp->atp_msgq;
1006
1007 ATDISABLE(s, atp->atp_lock);
1008 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
1009 if (trp->tr_tid == tid)
1010 break;
1011 }
1012 ATENABLE(s, atp->atp_lock);
1013 if (trp != NULL)
1014 atp_free(trp);
1015}
1016
1017/*
1018 * remove atp from the use list
1019 */
1020void
1021atp_dequeue_atp(atp)
1022 struct atp_state *atp;
1023{
1024 int s;
1025
1026 ATDISABLE(s, atpall_lock);
1027 if (atp == atp_used_list) {
1028 if ((atp_used_list = atp->atp_trans_waiting) != 0)
1029 atp->atp_trans_waiting->atp_rcb_waiting = 0;
1030 } else if (atp->atp_rcb_waiting) {
1031 if ((atp->atp_rcb_waiting->atp_trans_waiting
1032 = atp->atp_trans_waiting) != 0)
1033 atp->atp_trans_waiting->atp_rcb_waiting = atp->atp_rcb_waiting;
1034 }
1035
1036 atp->atp_trans_waiting = 0;
1037 atp->atp_rcb_waiting = 0;
1038 ATENABLE(s, atpall_lock);
1039}
1040
1041void
1042atp_timout(func, trp, ticks)
1043 void (*func)();
1044 struct atp_trans *trp;
1045 int ticks;
1046{
1047 int s;
1048 unsigned int sum;
1049 struct atp_trans *curr_trp, *prev_trp;
1050
1051 ATDISABLE(s, atptmo_lock);
1052 if (trp->tr_tmo_func) {
1053 ATENABLE(s, atptmo_lock);
1054 return;
1055 }
1056
1057 trp->tr_tmo_func = func;
1058 trp->tr_tmo_delta = 1+(ticks>>5);
1059
1060 if (trp_tmo_list == 0) {
1061 trp->tr_tmo_next = trp->tr_tmo_prev = 0;
1062 trp_tmo_list = trp;
1063 ATENABLE(s, atptmo_lock);
1064 return;
1065 }
1066
1067 prev_trp = 0;
1068 curr_trp = trp_tmo_list;
1069 sum = 0;
1070
1071 while (1) {
1072 sum += curr_trp->tr_tmo_delta;
1073 if (sum > trp->tr_tmo_delta) {
1074 sum -= curr_trp->tr_tmo_delta;
1075 trp->tr_tmo_delta -= sum;
1076 curr_trp->tr_tmo_delta -= trp->tr_tmo_delta;
1077 break;
1078 }
1079 prev_trp = curr_trp;
1080 if ((curr_trp = curr_trp->tr_tmo_next) == 0) {
1081 trp->tr_tmo_delta -= sum;
1082 break;
1083 }
1084 }
1085
1086 if (prev_trp) {
1087 trp->tr_tmo_prev = prev_trp;
1088 if ((trp->tr_tmo_next = prev_trp->tr_tmo_next) != 0)
1089 prev_trp->tr_tmo_next->tr_tmo_prev = trp;
1090 prev_trp->tr_tmo_next = trp;
1091 } else {
1092 trp->tr_tmo_prev = 0;
1093 trp->tr_tmo_next = trp_tmo_list;
1094 trp_tmo_list->tr_tmo_prev = trp;
1095 trp_tmo_list = trp;
1096 }
1097 ATENABLE(s, atptmo_lock);
1098}
1099
1100void
1101atp_untimout(func, trp)
1102 void (*func)();
1103 struct atp_trans *trp;
1104{
1105 int s;
1106
1107 ATDISABLE(s, atptmo_lock);
1108 if (trp->tr_tmo_func == 0) {
1109 ATENABLE(s, atptmo_lock);
1110 return;
1111 }
1112
1113 if (trp_tmo_list == trp) {
1114 if ((trp_tmo_list = trp->tr_tmo_next) != 0) {
1115 trp_tmo_list->tr_tmo_prev = 0;
1116 trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
1117 }
1118 } else {
1119 if ((trp->tr_tmo_prev->tr_tmo_next = trp->tr_tmo_next) != 0) {
1120 trp->tr_tmo_next->tr_tmo_prev = trp->tr_tmo_prev;
1121 trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
1122 }
1123 }
1124 trp->tr_tmo_func = 0;
1125 ATENABLE(s, atptmo_lock);
1126}
1127
1128void
91447636 1129atp_trp_clock_locked(arg)
1c79356b
A
1130 void *arg;
1131{
91447636 1132 atalk_lock();
1c79356b 1133 atp_trp_clock(arg);
91447636 1134 atalk_unlock();
1c79356b
A
1135}
1136
1137void
1138atp_trp_clock(arg)
1139 void *arg;
1140{
1141 int s;
1142 struct atp_trans *trp;
1143 void (*tr_tmo_func)();
1144
1145 ATDISABLE(s, atptmo_lock);
1146 if (trp_tmo_list)
1147 trp_tmo_list->tr_tmo_delta--;
1148 while (((trp = trp_tmo_list) != 0) && (trp_tmo_list->tr_tmo_delta == 0)) {
1149 if ((trp_tmo_list = trp->tr_tmo_next) != 0)
1150 trp_tmo_list->tr_tmo_prev = 0;
1151 if ((tr_tmo_func = trp->tr_tmo_func) != 0) {
1152 trp->tr_tmo_func = 0;
1153 ATENABLE(s, atptmo_lock);
1154 (*tr_tmo_func)(trp);
1155 ATDISABLE(s, atptmo_lock);
1156 }
1157 }
1158 ATENABLE(s, atptmo_lock);
1159
91447636 1160 timeout(atp_trp_clock_locked, (void *)arg, (1<<5));
1c79356b
A
1161}
1162
1163void
1164atp_send_req(gref, mioc)
1165 gref_t *gref;
1166 gbuf_t *mioc;
1167{
1168 register struct atp_state *atp;
1169 register struct atp_trans *trp;
1170 register ioc_t *iocbp;
1171 register at_atp_t *athp;
1172 register at_ddp_t *ddp;
1173 gbuf_t *m, *m2, *bds;
1174 struct atp_set_default *sdb;
1175 int s, old;
1176 unsigned int timer;
1177
1178 atp = (struct atp_state *)((struct atp_state *)gref->info)->atp_msgq;
1179 iocbp = (ioc_t *)gbuf_rptr(mioc);
1180
1181 if ((trp = atp_trans_alloc(atp)) == NULL) {
1182l_retry:
1183 ((asp_scb_t *)gref->info)->stat_msg = mioc;
1184 iocbp->ioc_private = (void *)gref;
1185 timeout(atp_retry_req, mioc, 10);
1186 return;
1187 }
1188
1189 m2 = gbuf_cont(mioc);
1190 if ((bds = gbuf_dupb(m2)) == NULL) {
1191 atp_trans_free(trp);
1192 goto l_retry;
1193 }
1194 gbuf_rinc(m2,atpBDSsize);
1195 gbuf_wset(bds,atpBDSsize);
1196 iocbp->ioc_count -= atpBDSsize;
1197 gbuf_cont(m2) = NULL;
1198
1199 old = iocbp->ioc_cmd;
1200 iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST;
1201 sdb = (struct atp_set_default *)gbuf_rptr(m2);
1202
1203 /*
1204 * The at_snd_req library routine multiplies seconds by 100.
1205 * We need to divide by 100 in order to obtain the timer.
1206 */
1207 if ((timer = (sdb->def_rate * HZ)/100) == 0)
1208 timer = HZ;
1209 iocbp->ioc_count -= sizeof(struct atp_set_default);
1210 gbuf_rinc(m2,sizeof(struct atp_set_default));
1211
1212 trp->tr_retry = sdb->def_retries;
1213 trp->tr_timeout = timer;
1214 trp->tr_bdsp = bds;
1215 trp->tr_tid = atp_tid(atp);
1216 trp->tr_xmt = mioc;
1217
1218 /*
1219 * Now fill in the header (and remember the bits
1220 * we need to know)
1221 */
1222 athp = AT_ATP_HDR(m2);
1223 athp->cmd = ATP_CMD_TREQ;
1224 UAS_ASSIGN(athp->tid, trp->tr_tid);
1225 athp->eom = 0;
1226 athp->sts = 0;
1227 trp->tr_xo = athp->xo;
1228 trp->tr_bitmap = athp->bitmap;
1229 ddp = AT_DDP_HDR(m2);
1230 ddp->type = DDP_ATP;
1231 ddp->src_socket = (at_socket)atp->atp_socket_no;
1232 trp->tr_socket.socket = ddp->dst_socket;
1233 trp->tr_socket.node = ddp->dst_node;
1234 trp->tr_socket.net = NET_VALUE(ddp->dst_net);
1235 trp->tr_local_socket = atp->atp_socket_no;
1236 trp->tr_local_node = ddp->src_node;
1237 NET_NET(trp->tr_local_net, ddp->src_net);
1238
1239#ifdef NOT_YET
1240 /* save the local information in the gref */
1241 atp->atp_gref->laddr.s_net = NET_VALUE(ddp->src_net);
1242 atp->atp_gref->laddr.s_node = ddp->src_node;
1243 atp->atp_gref->lport = ddp->src_node;
1244 atp->atp_gref->ddptype = DDP_ATP;
1245#endif
1246
1247 /*
1248 * Put us in the transaction waiting queue
1249 */
1250 ATDISABLE(s, atp->atp_lock);
1251 ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
1252 ATENABLE(s, atp->atp_lock);
1253
1254 /*
1255 * Send the message and set the timer
1256 */
1257 m = (gbuf_t *)copy_pkt(m2, sizeof(llc_header_t));
1258 if (!trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo)
1259 atp_x_done(trp); /* no reason to tie up resources */
1260 else
1261 atp_timout(atp_req_timeout, trp, trp->tr_timeout);
1262 if (m) {
1263 trace_mbufs(D_M_ATP_LOW, " s", m);
1264 DDP_OUTPUT(m);
1265 }
1266} /* atp_send_req */
1267
55e303ae
A
1268void atp_retry_req(arg)
1269 void *arg;
1c79356b 1270{
55e303ae 1271 gbuf_t *m = (gbuf_t *)arg;
1c79356b 1272 gref_t *gref;
1c79356b 1273
91447636 1274 atalk_lock();
1c79356b
A
1275
1276 gref = (gref_t *)((ioc_t *)gbuf_rptr(m))->ioc_private;
1277 if (gref->info) {
1278 ((asp_scb_t *)gref->info)->stat_msg = 0;
1279 atp_send_req(gref, m);
1280 }
91447636 1281 atalk_unlock();
1c79356b
A
1282}
1283
1284void atp_send_rsp(gref, m, wait)
1285 gref_t *gref;
1286 gbuf_t *m;
1287 int wait;
1288{
1289 register struct atp_state *atp;
1290 register struct atp_rcb *rcbp;
1291 register at_atp_t *athp;
1292 register at_ddp_t *ddp;
1293 int s, xcnt;
1294
1295 atp = (struct atp_state *)gref->info;
1296 if (atp->dflag)
1297 atp = (struct atp_state *)atp->atp_msgq;
1298 ddp = AT_DDP_HDR(m);
1299 athp = AT_ATP_HDR(m);
1300
1301 /*
1302 * search for the corresponding rcb
1303 */
1304 ATDISABLE(s, atp->atp_lock);
1305 for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
1306 if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) &&
1307 (rcbp->rc_socket.node == ddp->dst_node) &&
1308 (rcbp->rc_socket.net == NET_VALUE(ddp->dst_net)) &&
1309 (rcbp->rc_socket.socket == ddp->dst_socket) )
1310 break;
1311 }
1312
1313 /*
1314 * If it has already been sent then drop the request
1315 */
1316 if ((rcbp && (rcbp->rc_state != RCB_NOTIFIED)) ||
1317 (rcbp == NULL && athp->xo) ) {
1318 ATENABLE(s, atp->atp_lock);
1319 gbuf_freem(m);
1320 return;
1321 }
1322 ATENABLE(s, atp->atp_lock);
1323
1324 if (rcbp == NULL) { /* a response is being sent for an ALO transaction */
1325 if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
1326 gbuf_freem(m);
1327 return;
1328 }
1329 rcbp->rc_ioctl = 0;
1330 rcbp->rc_socket.socket = ddp->dst_socket;
1331 rcbp->rc_socket.node = ddp->dst_node;
1332 rcbp->rc_socket.net = NET_VALUE(ddp->dst_net);
1333 rcbp->rc_tid = UAS_VALUE(athp->tid);
1334 rcbp->rc_bitmap = 0xff;
1335 rcbp->rc_xo = 0;
1336 rcbp->rc_state = RCB_RESPONSE_FULL;
1337 ATDISABLE(s, atp->atp_lock);
1338 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
1339 ATENABLE(s, atp->atp_lock);
1340 }
1341 else if (ddp->src_node == 0) {
1342 NET_NET(ddp->src_net, rcbp->rc_local_net);
1343 ddp->src_node = rcbp->rc_local_node;
1344 }
1345
1346 xcnt = get_bds_entries(m);
1347 s = atp_unpack_bdsp(atp, m, rcbp, xcnt, wait);
1348 if (s == 0)
1349 atp_send_replies(atp, rcbp);
1350} /* atp_send_rsp */
1351
1352int asp_pack_bdsp(trp, xm)
1353 register struct atp_trans *trp;
1354 gbuf_t **xm;
1355{
1356 register struct atpBDS *bdsp;
1357 register gbuf_t *m, *m2;
1358 register int i;
1359 gbuf_t *m_prev, *m_head = 0;
1360
1361 dPrintf(D_M_ATP, D_L_INFO, ("asp_pack_bdsp: socket=%d\n",
1362 trp->tr_queue->atp_socket_no));
1363
1364 if ((m2 = trp->tr_bdsp) == NULL)
1365 return 0;
1366 trp->tr_bdsp = NULL;
1367 bdsp = (struct atpBDS *)gbuf_rptr(m2);
1368
1369 for (i = 0; (i < ATP_TRESP_MAX &&
1370 bdsp < (struct atpBDS *)(gbuf_wptr(m2))); i++) {
1371 if ((m = trp->tr_rcv[i]) == NULL)
1372 break;
1373 if (i == 0) {
1374 /* discard ddp hdr on first packet */
1375 gbuf_rinc(m,DDP_X_HDR_SIZE);
1376 }
1377
1378 UAL_UAL(bdsp->bdsUserData, (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
1379 gbuf_rinc(m, ATP_HDR_SIZE);
1380
1381 if (UAL_VALUE(bdsp->bdsBuffAddr)) {
91447636 1382 short tmp = 0;
1c79356b
A
1383
1384 /* user expects data back */
1385 m = gbuf_strip(m);
1386 if (m_head == 0)
1387 m_head = m;
1388 else
1389 gbuf_cont(m_prev) = m;
1390 if (m) {
1391 tmp = (short)gbuf_len(m);
1392 while (gbuf_cont(m)) {
1393 m = gbuf_cont(m);
1394 tmp += (short)(gbuf_len(m));
1395 }
1396 m_prev = m;
1397 }
1398 UAS_ASSIGN(bdsp->bdsDataSz, tmp);
1399 }
1400 trp->tr_rcv[i] = NULL;
1401 bdsp++;
1402
1403 }
1404 /*
1405 * report the number of packets
1406 */
1407 UAS_ASSIGN(((struct atpBDS *)gbuf_rptr(m2))->bdsBuffSz, i);
1408
1409 if (trp->tr_xmt) /* an ioctl block is still held? */
1410 gbuf_cont(trp->tr_xmt) = m2;
1411 else
1412 trp->tr_xmt = m2;
1413
1414 if (m_head)
1415 *xm = m_head;
1416 else
1417 *xm = 0;
1418
1419 dPrintf(D_M_ATP, D_L_INFO, (" : size=%d\n",
1420 gbuf_msgsize(*xm)));
1421
1422 return 0;
1423}
1424
1425/*
1426 * The following routines are direct entries from system
1427 * calls to allow fast sending and recving of ATP data.
1428 */
1429
1430int
1431_ATPsndreq(fd, buf, len, nowait, err, proc)
1432 int fd;
1433 unsigned char *buf;
1434 int len;
1435 int nowait;
1436 int *err;
1437 void *proc;
1438{
1439 gref_t *gref;
1440 int s, rc;
1441 unsigned short tid;
1442 unsigned int timer;
1443 register struct atp_state *atp;
1444 register struct atp_trans *trp;
1445 register ioc_t *iocbp;
1446 register at_atp_t *athp;
1447 register at_ddp_t *ddp;
1448 struct atp_set_default *sdb;
1449 gbuf_t *m2, *m, *mioc;
1450 char bds[atpBDSsize];
1451
91447636 1452 if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
1c79356b
A
1453 return -1;
1454
1455 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1456 || (atp->atp_flags & ATP_CLOSING)) {
1457 dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
1458 (u_int) gref, gref->pid));
91447636 1459 file_drop(fd);
1c79356b
A
1460 *err = EINVAL;
1461 return -1;
1462 }
1463
91447636 1464
1c79356b 1465 while ((mioc = gbuf_alloc(sizeof(ioc_t), PRI_MED)) == 0) {
91447636
A
1466 struct timespec ts;
1467 /* the vaue of 10n terms of hz is 100ms */
1468 ts.tv_sec = 0;
1469 ts.tv_nsec = 100 *1000 * NSEC_PER_USEC;
1470
1c79356b 1471 ATDISABLE(s, atp->atp_delay_lock);
91447636 1472 rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atpmioc", &ts);
1c79356b
A
1473 ATENABLE(s, atp->atp_delay_lock);
1474 if (rc != 0) {
1475 *err = rc;
91447636 1476 file_drop(fd);
1c79356b
A
1477 return -1;
1478 }
1479
1480 }
1481 gbuf_wset(mioc,sizeof(ioc_t));
1482 len -= atpBDSsize;
1483 while ((m2 = gbuf_alloc(len, PRI_MED)) == 0) {
91447636
A
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
1c79356b 1489 ATDISABLE(s, atp->atp_delay_lock);
91447636 1490 rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atpm2", &ts);
1c79356b
A
1491 ATENABLE(s, atp->atp_delay_lock);
1492 if (rc != 0) {
1493 gbuf_freeb(mioc);
91447636 1494 file_drop(fd);
1c79356b
A
1495 *err = rc;
1496 return -1;
1497 }
1498 }
1499 gbuf_wset(m2, len);
1500 gbuf_cont(mioc) = m2;
91447636
A
1501 if (((*err = copyin(CAST_USER_ADDR_T(buf), (caddr_t)bds, atpBDSsize)) != 0)
1502 || ((*err = copyin(CAST_USER_ADDR_T(&buf[atpBDSsize]),
1c79356b
A
1503 (caddr_t)gbuf_rptr(m2), len)) != 0)) {
1504 gbuf_freem(mioc);
91447636 1505 file_drop(fd);
1c79356b
A
1506 return -1;
1507 }
1508 gbuf_set_type(mioc, MSG_IOCTL);
1509 iocbp = (ioc_t *)gbuf_rptr(mioc);
1510 iocbp->ioc_count = len;
1511 iocbp->ioc_cmd = nowait ? AT_ATP_ISSUE_REQUEST_NOTE : AT_ATP_ISSUE_REQUEST;
1512 sdb = (struct atp_set_default *)gbuf_rptr(m2);
1513
1514 /*
1515 * The at_snd_req library routine multiplies seconds by 100.
1516 * We need to divide by 100 in order to obtain the timer.
1517 */
1518 if ((timer = (sdb->def_rate * HZ)/100) == 0)
1519 timer = HZ;
1520 iocbp->ioc_count -= sizeof(struct atp_set_default);
1521 gbuf_rinc(m2,sizeof(struct atp_set_default));
1522
1523 /*
1524 * allocate and set up the transaction record
1525 */
1526 while ((trp = atp_trans_alloc(atp)) == 0) {
91447636
A
1527 struct timespec ts;
1528 /* the vaue of 10n terms of hz is 100ms */
1529 ts.tv_sec = 0;
1530 ts.tv_nsec = 100 *1000 * NSEC_PER_USEC;
1531
1c79356b 1532 ATDISABLE(s, atp->atp_delay_lock);
91447636 1533 rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atptrp", &ts);
1c79356b
A
1534 ATENABLE(s, atp->atp_delay_lock);
1535 if (rc != 0) {
1536 gbuf_freem(mioc);
91447636 1537 file_drop(fd);
1c79356b
A
1538 *err = rc;
1539 return -1;
1540 }
1541 }
1542 trp->tr_retry = sdb->def_retries;
1543 trp->tr_timeout = timer;
1544 trp->tr_bdsp = NULL;
1545 trp->tr_tid = atp_tid(atp);
1546 tid = trp->tr_tid;
1547
1548 /*
1549 * remember the IOCTL packet so we can ack it
1550 * later
1551 */
1552 trp->tr_xmt = mioc;
1553
1554 /*
1555 * Now fill in the header (and remember the bits
1556 * we need to know)
1557 */
1558 athp = AT_ATP_HDR(m2);
1559 athp->cmd = ATP_CMD_TREQ;
1560 UAS_ASSIGN(athp->tid, trp->tr_tid);
1561 athp->eom = 0;
1562 athp->sts = 0;
1563 trp->tr_xo = athp->xo;
1564 trp->tr_bitmap = athp->bitmap;
1565 ddp = AT_DDP_HDR(m2);
1566 ddp->type = DDP_ATP;
1567 ddp->src_socket = (at_socket)atp->atp_socket_no;
1568 ddp->src_node = 0;
1569 trp->tr_socket.socket = ddp->dst_socket;
1570 trp->tr_socket.node = ddp->dst_node;
1571 trp->tr_socket.net = NET_VALUE(ddp->dst_net);
1572 trp->tr_local_socket = atp->atp_socket_no;
1573
1574#ifdef NOT_YET
1575 /* save the local information in the gref */
1576 atp->atp_gref->laddr.s_net = NET_VALUE(ddp->src_net);
1577 atp->atp_gref->laddr.s_node = ddp->src_node;
1578 atp->atp_gref->lport = ddp->src_node;
1579 atp->atp_gref->ddptype = DDP_ATP;
1580#endif
1581
1582 /*
1583 * Put us in the transaction waiting queue
1584 */
1585 ATDISABLE(s, atp->atp_lock);
1586 ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
1587 ATENABLE(s, atp->atp_lock);
1588
1589 /*
1590 * Send the message and set the timer
1591 */
1592 m = (gbuf_t *)copy_pkt(m2, sizeof(llc_header_t));
1593 if ( !trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo)
1594 atp_x_done(trp); /* no reason to tie up resources */
1595 else
1596 atp_timout(atp_req_timeout, trp, trp->tr_timeout);
1597 if (m)
1598 DDP_OUTPUT(m);
1599
91447636
A
1600 if (nowait) {
1601 file_drop(fd);
1c79356b 1602 return (int)tid;
91447636 1603 }
1c79356b
A
1604
1605 /*
1606 * wait for the transaction to complete
1607 */
1608 ATDISABLE(s, trp->tr_lock);
0b4e3aa0
A
1609 while ((trp->tr_state != TRANS_DONE) && (trp->tr_state != TRANS_FAILED) &&
1610 (trp->tr_state != TRANS_ABORTING)) {
1c79356b 1611 trp->tr_rsp_wait = 1;
91447636 1612 rc = msleep(&trp->tr_event, atalk_mutex, PSOCK | PCATCH, "atpsndreq", 0);
1c79356b
A
1613 if (rc != 0) {
1614 trp->tr_rsp_wait = 0;
1615 ATENABLE(s, trp->tr_lock);
91447636 1616 file_drop(fd);
1c79356b
A
1617 *err = rc;
1618 return -1;
1619 }
1620 }
1621 trp->tr_rsp_wait = 0;
1622 ATENABLE(s, trp->tr_lock);
1623
0b4e3aa0
A
1624
1625 if (trp->tr_state == TRANS_FAILED || trp->tr_state == TRANS_ABORTING) {
1c79356b
A
1626 /*
1627 * transaction timed out, return error
1628 */
1629 atp_free(trp);
91447636 1630 file_drop(fd);
1c79356b
A
1631 *err = ETIMEDOUT;
1632 return -1;
1633 }
1634
1635 /*
1636 * copy out the recv data
1637 */
55e303ae 1638 atp_pack_bdsp(trp, (struct atpBDS *)bds);
1c79356b
A
1639
1640 /*
1641 * copyout the result info
1642 */
91447636 1643 copyout((caddr_t)bds, CAST_USER_ADDR_T(buf), atpBDSsize);
1c79356b
A
1644
1645 atp_free(trp);
91447636 1646 file_drop(fd);
1c79356b
A
1647
1648 return (int)tid;
1649} /* _ATPsndreq */
1650
55e303ae
A
1651
1652/* entry point for ATP send response. respbuf contains a DDP hdr,
1653 * ATP hdr, and atpBDS array. The bdsDataSz field of the first atpBDS
1654 * struct contains the number of atpBDS structs in the array. resplen
1655 * contains the len of the data in respbuf and datalen contains the
1656 * len of the data buffer holding the response packets which the atpBDS
1657 * struct entries point to.
1658 */
1c79356b
A
1659int
1660_ATPsndrsp(fd, respbuff, resplen, datalen, err, proc)
1661 int fd;
1662 unsigned char *respbuff;
1663 int resplen;
1664 int datalen;
1665 int *err;
1666 void *proc;
1667{
55e303ae
A
1668 gref_t *gref;
1669 int s, rc;
1670 long bufaddr;
1671 gbuf_t *m, *mdata;
1672 short space;
1673 int size;
1674 struct atp_state *atp;
1675 struct atpBDS *bdsp;
1676 u_int16_t *bufsz;
1677 char *buf;
1678 int bds_cnt, count, len;
1679 caddr_t dataptr;
1c79356b 1680
91447636 1681 if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
1c79356b
A
1682 return -1;
1683
1684 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1685 || (atp->atp_flags & ATP_CLOSING)) {
1686 dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
1687 (u_int) gref, gref->pid));
1688
91447636 1689 file_drop(fd);
1c79356b
A
1690 *err = EINVAL;
1691 return -1;
1692 }
1693
1694 /*
1695 * allocate buffer and copy in the response info
1696 */
0b4e3aa0
A
1697 if ((m = gbuf_alloc_wait(resplen, TRUE)) == 0) {
1698 *err = ENOMEM;
91447636 1699 file_drop(fd);
0b4e3aa0 1700 return -1;
1c79356b 1701 }
91447636 1702 if ((*err = copyin(CAST_USER_ADDR_T(respbuff), (caddr_t)gbuf_rptr(m), resplen)) != 0) {
1c79356b 1703 gbuf_freeb(m);
91447636 1704 file_drop(fd);
1c79356b
A
1705 return -1;
1706 }
1707 gbuf_wset(m,resplen);
1708 ((at_ddp_t *)gbuf_rptr(m))->src_node = 0;
1709 bdsp = (struct atpBDS *)(gbuf_rptr(m) + TOTAL_ATP_HDR_SIZE);
1c79356b
A
1710
1711 /*
55e303ae
A
1712 * allocate buffers and copy in the response data.
1713 * note that only the size field of the atpBDS field
1714 * is used internally in the kernel.
1c79356b 1715 */
55e303ae
A
1716 bds_cnt = get_bds_entries(m); /* count of # entries */
1717 /* check correctness of parameters */
1718 if (bds_cnt > ATP_TRESP_MAX) {
1719 gbuf_freem(m);
1720 *err = EINVAL;
91447636 1721 file_drop(fd);
55e303ae
A
1722 return -1;
1723 }
1724
1725 for (size = 0, count = 0; count < bds_cnt; count++) {
1726 size += UAS_VALUE(bdsp[count].bdsBuffSz);
1727 }
1728 if (size > datalen) {
1729 gbuf_freem(m);
1730 *err = EINVAL;
91447636 1731 file_drop(fd);
55e303ae
A
1732 return -1;
1733 }
1734
1735 /* get the first mbuf */
1736 if ((mdata = gbuf_alloc_wait((space = (size > MCLBYTES ? MCLBYTES : size)), TRUE)) == 0) {
1737 gbuf_freem(m);
91447636 1738 file_drop(fd);
0b4e3aa0
A
1739 *err = ENOMEM;
1740 return -1;
1c79356b
A
1741 }
1742 gbuf_cont(m) = mdata;
55e303ae
A
1743 dataptr = mtod(mdata, caddr_t);
1744 for (count = 0; count < bds_cnt; bdsp++, count++) {
1745 if ((bufaddr = UAL_VALUE(bdsp->bdsBuffAddr)) != 0 &&
1746 (len = UAS_VALUE(bdsp->bdsBuffSz)) != 0) {
1747 if (len > space) { /* enough room ? */
1748 gbuf_wset(mdata, dataptr - mtod(mdata, caddr_t)); /* set len of last mbuf */
1749 /* allocate the next mbuf */
1750 if ((gbuf_cont(mdata) = m_get((M_WAIT), MSG_DATA)) == 0) {
1751 gbuf_freem(m);
91447636 1752 file_drop(fd);
55e303ae
A
1753 *err = ENOMEM;
1754 return -1;
1755 }
1756 mdata = gbuf_cont(mdata);
1757 MCLGET(mdata, M_WAIT);
1758 if (!(mdata->m_flags & M_EXT)) {
1759 m_freem(m);
91447636 1760 file_drop(fd);
55e303ae
A
1761 return(NULL);
1762 }
1763 dataptr = mtod(mdata, caddr_t);
1764 space = MCLBYTES;
1765 }
1766 /* do the copyin */
91447636 1767 if ((*err = copyin(CAST_USER_ADDR_T(bufaddr), dataptr, len)) != 0) {
1c79356b 1768 gbuf_freem(m);
91447636 1769 file_drop(fd);
1c79356b
A
1770 return -1;
1771 }
55e303ae
A
1772 dataptr += len;
1773 space -= len;
1c79356b
A
1774 }
1775 }
55e303ae
A
1776 gbuf_wset(mdata, dataptr - mtod(mdata, caddr_t)); /* set len of last mbuf */
1777 gbuf_cont(m)->m_pkthdr.len = size; /* set packet hdr len */
1c79356b
A
1778
1779 atp_send_rsp(gref, m, TRUE);
91447636 1780 file_drop(fd);
1c79356b
A
1781 return 0;
1782}
1783
1784int
1785_ATPgetreq(fd, buf, buflen, err, proc)
1786 int fd;
1787 unsigned char *buf;
1788 int buflen;
1789 int *err;
1790 void *proc;
1791{
1792 gref_t *gref;
1793 register struct atp_state *atp;
1794 register struct atp_rcb *rcbp;
1795 register gbuf_t *m, *m_head;
1796 int s, size, len;
1797
91447636 1798 if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
1c79356b
A
1799 return -1;
1800
1801 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1802 || (atp->atp_flags & ATP_CLOSING)) {
1803 dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
1804 (u_int) gref, gref->pid));
91447636 1805 file_drop(fd);
1c79356b
A
1806 *err = EINVAL;
1807 return -1;
1808 }
1809
1810 ATDISABLE(s, atp->atp_lock);
1811 if ((rcbp = atp->atp_attached.head) != NULL) {
1812 /*
1813 * Got one, move it to the active response Q
1814 */
1815 m_head = rcbp->rc_ioctl;
1816 rcbp->rc_ioctl = NULL;
1817
1818 if (rcbp->rc_xo) {
1819 ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
1820 rcbp->rc_state = RCB_NOTIFIED;
1821 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
1822 } else {
1823 /* detach rcbp from attached queue,
1824 * and free any outstanding resources
1825 */
1826 atp_rcb_free(rcbp);
1827 }
1828 ATENABLE(s, atp->atp_lock);
1829
1830 /*
1831 * copyout the request data, including the protocol header
1832 */
1833 for (size=0, m=m_head; m; m = gbuf_cont(m)) {
1834 if ((len = gbuf_len(m)) > buflen)
1835 len = buflen;
91447636 1836 copyout((caddr_t)gbuf_rptr(m), CAST_USER_ADDR_T(&buf[size]), len);
1c79356b
A
1837 size += len;
1838 if ((buflen -= len) == 0)
1839 break;
1840 }
1841 gbuf_freem(m_head);
1842
91447636 1843 file_drop(fd);
1c79356b
A
1844 return size;
1845 }
1846 ATENABLE(s, atp->atp_lock);
1847
91447636 1848 file_drop(fd);
1c79356b
A
1849 return -1;
1850}
1851
1852int
1853_ATPgetrsp(fd, bdsp, err, proc)
1854 int fd;
1855 struct atpBDS *bdsp;
1856 int *err;
1857 void *proc;
1858{
1859 gref_t *gref;
1860 register struct atp_state *atp;
1861 register struct atp_trans *trp;
1862 int s, tid;
1863 char bds[atpBDSsize];
1864
91447636 1865 if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
1c79356b
A
1866 return -1;
1867
1868 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1869 || (atp->atp_flags & ATP_CLOSING)) {
1870 dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
1871 (u_int) gref, gref->pid));
91447636 1872 file_drop(fd);
1c79356b
A
1873 *err = EINVAL;
1874 return -1;
1875 }
1876
1877 ATDISABLE(s, atp->atp_lock);
1878 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
1879 dPrintf(D_M_ATP, D_L_INFO,
1880 ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
1881 (u_int) atp, (u_int) trp, trp->tr_state));
1882
1883 switch (trp->tr_state) {
1884 case TRANS_DONE:
1885 ATENABLE(s, atp->atp_lock);
91447636
A
1886 if ((*err = copyin(CAST_USER_ADDR_T(bdsp),
1887 (caddr_t)bds, sizeof(bds))) != 0) {
1888 file_drop(fd);
1c79356b 1889 return -1;
91447636 1890 }
55e303ae 1891 atp_pack_bdsp(trp, (struct atpBDS *)bds);
1c79356b
A
1892 tid = (int)trp->tr_tid;
1893 atp_free(trp);
91447636
A
1894 copyout((caddr_t)bds, CAST_USER_ADDR_T(bdsp), sizeof(bds));
1895 file_drop(fd);
1c79356b
A
1896 return tid;
1897
1898 case TRANS_FAILED:
1899 /*
1900 * transaction timed out, return error
1901 */
1902 ATENABLE(s, atp->atp_lock);
1903 atp_free(trp);
91447636 1904 file_drop(fd);
1c79356b
A
1905 *err = ETIMEDOUT;
1906 return -1;
1907
1908 default:
1909 continue;
1910 }
1911 }
1912 ATENABLE(s, atp->atp_lock);
1913
91447636 1914 file_drop(fd);
1c79356b
A
1915 *err = EINVAL;
1916 return -1;
1917}
1918
1919void
1920atp_drop_req(gref, m)
1921 gref_t *gref;
1922 gbuf_t *m;
1923{
1924 int s;
1925 struct atp_state *atp;
1926 struct atp_rcb *rcbp;
1927 at_atp_t *athp;
1928 at_ddp_t *ddp;
1929
1930 atp = (struct atp_state *)gref->info;
1931 if (atp->dflag)
1932 atp = (struct atp_state *)atp->atp_msgq;
1933 ddp = AT_DDP_HDR(m);
1934 athp = AT_ATP_HDR(m);
1935
1936 /*
1937 * search for the corresponding rcb
1938 */
1939 ATDISABLE(s, atp->atp_lock);
1940 for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
1941 if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) &&
1942 (rcbp->rc_socket.node == ddp->src_node) &&
1943 (rcbp->rc_socket.net == NET_VALUE(ddp->src_net)) &&
1944 (rcbp->rc_socket.socket == ddp->src_socket) )
1945 break;
1946 }
1947
1948 /*
1949 * drop the request
1950 */
1951 if (rcbp)
1952 atp_rcb_free(rcbp);
1953 ATENABLE(s, atp->atp_lock);
1954
1955 gbuf_freem(m);
1956}