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