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