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