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