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