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