2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1996-1998 Apple Computer, Inc.
27 * All Rights Reserved.
30 /* Modified for MP, 1996 by Tuyen Nguyen
31 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
35 #include <sys/errno.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <machine/spl.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
42 #include <sys/filedesc.h>
43 #include <sys/fcntl.h>
45 #include <sys/ioctl.h>
46 #include <sys/malloc.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
52 #include <netat/sysglue.h>
53 #include <netat/appletalk.h>
54 #include <netat/ddp.h>
55 #include <netat/at_pcb.h>
56 #include <netat/atp.h>
57 #include <netat/at_var.h>
58 #include <netat/asp.h>
59 #include <netat/at_pat.h>
60 #include <netat/debug.h>
62 static int loop_cnt
; /* for debugging loops */
63 #define CHK_LOOP(str) { \
64 if (loop_cnt++ > 100) { \
70 static void atp_pack_bdsp(struct atp_trans
*, struct atpBDS
*);
71 static int atp_unpack_bdsp(struct atp_state
*, gbuf_t
*, struct atp_rcb
*,
73 void atp_retry_req(), atp_trp_clock(), asp_clock(), asp_clock_funnel(), atp_trp_clock_funnel();;
75 extern struct atp_rcb_qhead atp_need_rel
;
76 extern int atp_inited
;
77 extern struct atp_state
*atp_used_list
;
78 extern asp_scb_t
*scb_free_list
;
79 extern atlock_t atpgen_lock
;
80 extern atlock_t atpall_lock
;
81 extern atlock_t atptmo_lock
;
83 extern gbuf_t
*scb_resource_m
;
84 extern gbuf_t
*atp_resource_m
;
85 extern gref_t
*atp_inputQ
[];
86 extern int atp_pidM
[];
87 extern at_ifaddr_t
*ifID_home
;
89 static struct atp_trans
*trp_tmo_list
;
90 struct atp_trans
*trp_tmo_rcb
;
92 /* first bds entry gives number of bds entries in total (hack) */
93 #define get_bds_entries(m) \
94 ((gbuf_len(m) > TOTAL_ATP_HDR_SIZE)? \
95 (UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz)): 0)
97 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
102 trp_tmo_rcb
= atp_trans_alloc(0);
103 atp_timout(atp_rcb_timer
, trp_tmo_rcb
, 10 * HZ
);
104 atp_trp_clock((void *)&atp_inited
);
105 asp_clock((void *)&atp_inited
);
110 untimeout(asp_clock_funnel
, (void *)&atp_inited
);
111 untimeout(atp_trp_clock_funnel
, (void *)&atp_inited
);
112 atp_untimout(atp_rcb_timer
, trp_tmo_rcb
);
116 /* allocated in asp_scb_alloc(), which is called
118 if (scb_resource_m
) {
119 gbuf_freem(scb_resource_m
);
123 /* allocated in atp_trans_alloc() */
124 if (atp_resource_m
) {
125 gbuf_freem(atp_resource_m
);
127 atp_trans_free_list
= 0;
133 * write queue put routine .... filter out other than IOCTLs
134 * Version 1.8 of atp_write.c on 89/02/09 17:53:26
139 register gref_t
*gref
;
142 register ioc_t
*iocbp
;
144 struct atp_state
*atp
;
145 struct atp_trans
*trp
;
146 struct atp_rcb
*rcbp
;
149 atp
= (struct atp_state
*)gref
->info
;
151 atp
= (struct atp_state
*)atp
->atp_msgq
;
153 switch(gbuf_type(m
)) {
157 dPrintf(D_M_ATP
, D_L_WARNING
,
158 ("atp_wput: atp_msgq discarded\n"));
164 /* Need to ensure that all copyin/copyout calls are made at
165 * put routine time which should be in the user context. (true when
166 * we are the stream head). The service routine can be called on an
167 * unpredictable context and copyin/copyout calls will get wrong results
168 * or even panic the kernel.
170 iocbp
= (ioc_t
*)gbuf_rptr(m
);
172 switch (iocbp
->ioc_cmd
) {
173 case AT_ATP_BIND_REQ
:
174 if (gbuf_cont(m
) == NULL
) {
175 iocbp
->ioc_rval
= -1;
176 atp_iocnak(atp
, m
, EINVAL
);
179 skt
= *(at_socket
*)gbuf_rptr(gbuf_cont(m
));
180 if ((skt
= (at_socket
)atp_bind(gref
, (unsigned int)skt
, 0)) == 0)
181 atp_iocnak(atp
, m
, EINVAL
);
183 *(at_socket
*)gbuf_rptr(gbuf_cont(m
)) = skt
;
186 atp_dequeue_atp(atp
);
190 case AT_ATP_GET_CHANID
:
191 if (gbuf_cont(m
) == NULL
) {
192 iocbp
->ioc_rval
= -1;
193 atp_iocnak(atp
, m
, EINVAL
);
196 *(gref_t
**)gbuf_rptr(gbuf_cont(m
)) = gref
;
200 /* not the close and not the tickle(?) */
201 case AT_ATP_ISSUE_REQUEST_DEF
:
202 case AT_ATP_ISSUE_REQUEST_DEF_NOTE
: {
203 gbuf_t
*bds
, *tmp
, *m2
;
204 struct atp_rcb
*rcbp
;
208 if ((tmp
= gbuf_cont(m
)) != 0) {
209 if ((bds
= gbuf_dupb(tmp
)) == NULL
) {
210 atp_iocnak(atp
, m
, ENOBUFS
);
213 gbuf_rinc(tmp
,atpBDSsize
);
214 gbuf_wset(bds
,atpBDSsize
);
215 iocbp
->ioc_count
-= atpBDSsize
;
216 gbuf_cont(tmp
) = bds
;
220 * send a response to a transaction
223 if (iocbp
->ioc_count
< TOTAL_ATP_HDR_SIZE
) {
224 atp_iocnak(atp
, m
, EINVAL
);
229 * remove the response from the message
233 iocbp
->ioc_count
= 0;
234 ddp
= AT_DDP_HDR(m2
);
235 athp
= AT_ATP_HDR(m2
);
237 gbuf_cont(m2
) = atp
->atp_msgq
;
241 ATDISABLE(s
, atp
->atp_lock
);
243 * search for the corresponding rcb
245 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
246 if (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
) &&
247 rcbp
->rc_socket
.node
== ddp
->dst_node
&&
248 rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
) &&
249 rcbp
->rc_socket
.socket
== ddp
->dst_socket
)
252 ATENABLE(s
, atp
->atp_lock
);
255 * If it has already been sent then return an error
257 if ((rcbp
&& rcbp
->rc_state
!= RCB_NOTIFIED
) ||
258 (rcbp
== NULL
&& athp
->xo
)) {
259 atp_iocnak(atp
, m
, ENOENT
);
263 if (rcbp
== NULL
) { /* a response for an ALO transaction */
264 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
265 atp_iocnak(atp
, m
, ENOBUFS
);
270 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
271 rcbp
->rc_socket
.node
= ddp
->dst_node
;
272 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
273 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
274 rcbp
->rc_bitmap
= 0xff;
276 ATDISABLE(s
, atp
->atp_lock
);
277 rcbp
->rc_state
= RCB_SENDING
;
278 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
279 ATENABLE(s
, atp
->atp_lock
);
281 xcnt
= get_bds_entries(m2
);
282 if ((i
= atp_unpack_bdsp(atp
, m2
, rcbp
, xcnt
, FALSE
))) {
285 atp_iocnak(atp
, m
, i
);
288 atp_send_replies(atp
, rcbp
);
291 * send the ack back to the responder
297 case AT_ATP_GET_POLL
: {
299 gbuf_freem(gbuf_cont(m
));
301 iocbp
->ioc_count
= 0;
305 * search for a waiting request
307 ATDISABLE(s
, atp
->atp_lock
);
308 if ((rcbp
= atp
->atp_attached
.head
)) {
310 * Got one, move it to the active response Q
312 gbuf_cont(m
) = rcbp
->rc_ioctl
;
313 rcbp
->rc_ioctl
= NULL
;
315 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
316 rcbp
->rc_state
= RCB_NOTIFIED
;
317 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
319 /* detach rcbp from attached queue,
320 * and free any outstanding resources
324 ATENABLE(s
, atp
->atp_lock
);
328 * None available - can out
330 ATENABLE(s
, atp
->atp_lock
);
331 atp_iocnak(atp
, m
, EAGAIN
);
336 case AT_ATP_CANCEL_REQUEST
: {
338 * Cancel a pending request
340 if (iocbp
->ioc_count
!= sizeof(int)) {
341 atp_iocnak(atp
, m
, EINVAL
);
344 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
345 gbuf_freem(gbuf_cont(m
));
347 ATDISABLE(s
, atp
->atp_lock
);
348 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
349 if (trp
->tr_tid
== i
)
353 ATENABLE(s
, atp
->atp_lock
);
354 atp_iocnak(atp
, m
, ENOENT
);
356 ATENABLE(s
, atp
->atp_lock
);
365 if (atalk_peek(gref
, &event
) == -1)
366 atp_iocnak(atp
, m
, EAGAIN
);
368 *gbuf_rptr(gbuf_cont(m
)) = event
;
374 case DDP_IOC_GET_CFG
:
375 #ifdef APPLETALK_DEBUG
376 kprintf("atp_wput: DDP_IOC_GET_CFG\n");
378 if (gbuf_cont(m
) == 0) {
379 atp_iocnak(atp
, m
, EINVAL
);
383 /* *** was ddp_get_cfg() *** */
385 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(m
));
386 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
387 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
388 cfgp
->inet
.socket
= atp
->atp_socket_no
;
389 cfgp
->ddptype
= DDP_ATP
;
391 cfgp
->inet
.net
= atp
->atp_gref
->laddr
.s_net
;
392 cfgp
->inet
.node
= atp
->atp_gref
->laddr
.s_node
;
393 cfgp
->inet
.socket
= atp
->atp_gref
->lport
;
394 cfgp
->ddptype
= atp
->atp_gref
->ddptype
;
397 gbuf_wset(gbuf_cont(m
), sizeof(ddp_addr_t
));
403 * Otherwise pass it on, if possible
405 iocbp
->ioc_private
= (void *)gref
;
417 gbuf_t
*atp_build_release(trp
)
418 register struct atp_trans
*trp
;
421 register at_ddp_t
*ddp
;
422 register at_atp_t
*athp
;
425 * Now try and allocate enough space to send the message
426 * if none is available the caller will schedule
427 * a timeout so we can retry for more space soon
429 if ((m
= (gbuf_t
*)gbuf_alloc(AT_WR_OFFSET
+ATP_HDR_SIZE
, PRI_HI
)) != NULL
) {
430 gbuf_rinc(m
,AT_WR_OFFSET
);
431 gbuf_wset(m
,TOTAL_ATP_HDR_SIZE
);
434 UAS_ASSIGN(ddp
->checksum
, 0);
435 ddp
->dst_socket
= trp
->tr_socket
.socket
;
436 ddp
->dst_node
= trp
->tr_socket
.node
;
437 NET_ASSIGN(ddp
->dst_net
, trp
->tr_socket
.net
);
438 ddp
->src_node
= trp
->tr_local_node
;
439 NET_NET(ddp
->src_net
, trp
->tr_local_net
);
442 * clear the cmd/xo/eom/sts/unused fields
444 athp
= AT_ATP_HDR(m
);
445 ATP_CLEAR_CONTROL(athp
);
446 athp
->cmd
= ATP_CMD_TREL
;
447 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
453 void atp_send_replies(atp
, rcbp
)
454 register struct atp_state
*atp
;
455 register struct atp_rcb
*rcbp
;
456 { register gbuf_t
*m
;
458 int s_gen
, s
, cnt
, err
, offset
, space
;
459 unsigned char *m0_rptr
= NULL
, *m0_wptr
= NULL
;
460 register at_atp_t
*athp
;
461 register struct atpBDS
*bdsp
;
462 register gbuf_t
*m2
, *m1
, *m0
, *mhdr
;
464 gbuf_t
*mprev
, *mlist
= 0;
465 at_socket src_socket
= (at_socket
)atp
->atp_socket_no
;
466 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
468 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
471 ATDISABLE(s
, atp
->atp_lock
);
472 if (rcbp
->rc_queue
!= atp
) {
473 ATENABLE(s
, atp
->atp_lock
);
476 if (rcbp
->rc_not_sent_bitmap
== 0)
477 goto nothing_to_send
;
479 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
, ("atp_send_replies\n"));
481 * Do this for each message that hasn't been sent
483 cnt
= rcbp
->rc_pktcnt
;
484 for (i
= 0; i
< cnt
; i
++) {
486 if (rcbp
->rc_snd
[i
]) {
488 gbuf_alloc(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,PRI_MED
))
490 for (cnt
= 0; cnt
< i
; cnt
++)
492 gbuf_freeb(rc_xmt
[cnt
]);
493 goto nothing_to_send
;
500 if (gbuf_len(m
) > TOTAL_ATP_HDR_SIZE
)
501 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
506 space
= gbuf_msgsize(m0
);
507 for (i
= 0; i
< cnt
; i
++) {
508 if (rcbp
->rc_snd
[i
] == 0) {
509 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
))) {
515 /* setup header fields */
516 gbuf_rinc(mhdr
,AT_WR_OFFSET
);
517 gbuf_wset(mhdr
,TOTAL_ATP_HDR_SIZE
);
518 *(struct ddp_atp
*)(gbuf_rptr(mhdr
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
519 athp
= AT_ATP_HDR(mhdr
);
520 ATP_CLEAR_CONTROL(athp
);
521 athp
->cmd
= ATP_CMD_TRESP
;
524 athp
->eom
= 1; /* for the last fragment */
526 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
527 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)) && m0
!= 0 && space
> 0) {
528 if ((m1
= m_copym(m0
, offset
, len
, M_DONTWAIT
)) == 0) {
529 for (i
= 0; i
< cnt
; i
++)
531 gbuf_freem(rc_xmt
[i
]);
532 goto nothing_to_send
;
536 gbuf_cont(mhdr
) = m1
;
540 AT_DDP_HDR(mhdr
)->src_socket
= src_socket
;
541 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
,
542 ("atp_send_replies: %d, socket=%d, size=%d\n",
543 i
, atp
->atp_socket_no
, gbuf_msgsize(gbuf_cont(m2
))));
546 gbuf_next(mprev
) = mhdr
;
552 rcbp
->rc_not_sent_bitmap
&= ~atp_mask
[i
];
553 if (rcbp
->rc_not_sent_bitmap
== 0)
557 * on to the next frag
562 ATENABLE(s
, atp
->atp_lock
);
564 ATDISABLE(s
, atp
->atp_lock
);
569 * If all replies from this reply block have been sent then
570 * remove it from the queue and mark it so
572 if (rcbp
->rc_queue
!= atp
) {
573 ATENABLE(s
, atp
->atp_lock
);
576 rcbp
->rc_rep_waiting
= 0;
579 * If we are doing execute once re-set the rcb timeout
580 * each time we send back any part of the response. Note
581 * that this timer is started when an initial request is
582 * received. Each response reprimes the timer. Duplicate
583 * requests do not reprime the timer.
585 * We have sent all of a response so free the
588 if (rcbp
->rc_xo
&& rcbp
->rc_state
!= RCB_RELEASED
) {
589 ATDISABLE(s_gen
, atpgen_lock
);
590 if (rcbp
->rc_timestamp
== 0) {
591 rcbp
->rc_timestamp
= time
.tv_sec
;
592 if (rcbp
->rc_timestamp
== 0)
593 rcbp
->rc_timestamp
= 1;
594 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
596 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
597 ATENABLE(s_gen
, atpgen_lock
);
600 ATENABLE(s
, atp
->atp_lock
);
601 } /* atp_send_replies */
605 atp_pack_bdsp(trp
, bdsp
)
606 register struct atp_trans
*trp
;
607 register struct atpBDS
*bdsp
;
609 register gbuf_t
*m
= NULL
;
610 register int i
, datsize
= 0;
611 struct atpBDS
*bdsbase
= bdsp
;
613 dPrintf(D_M_ATP
, D_L_INFO
, ("atp_pack_bdsp: socket=%d\n",
614 trp
->tr_queue
->atp_socket_no
));
616 for (i
= 0; i
< ATP_TRESP_MAX
; i
++, bdsp
++) {
617 short bufsize
= UAS_VALUE(bdsp
->bdsBuffSz
);
618 long bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
);
620 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
623 /* discard ddp hdr on first packet */
625 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
627 /* this field may contain control information even when
628 no data is present */
629 UAL_UAL(bdsp
->bdsUserData
,
630 (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
631 gbuf_rinc(m
, ATP_HDR_SIZE
);
633 if ((bufsize
!= 0) && (bufaddr
!= 0)) {
634 /* user expects data back */
636 register char *buf
= (char *)bufaddr
;
639 short len
= (short)(gbuf_len(m
));
643 copyout((caddr_t
)gbuf_rptr(m
),
652 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
655 gbuf_freem(trp
->tr_rcv
[i
]);
656 trp
->tr_rcv
[i
] = NULL
;
659 /* report the number of packets */
660 UAS_ASSIGN(((struct atpBDS
*)bdsbase
)->bdsBuffSz
, i
);
662 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
664 } /* atp_pack_bdsp */
667 /* create an mbuf chain with mbuf packet headers for each ATP response packet
668 * to be sent. m contains the DDP hdr, ATP hdr, and and array of atpBDS structs.
669 * chained to m is an mbuf that contians the actual data pointed to by the atpBDS
673 atp_unpack_bdsp(atp
, m
, rcbp
, cnt
, wait
)
674 struct atp_state
*atp
;
675 gbuf_t
*m
; /* ddp, atp and bdsp gbuf_t */
676 register struct atp_rcb
*rcbp
;
677 register int cnt
, wait
;
679 register struct atpBDS
*bdsp
;
680 register gbuf_t
*m2
, *m1
, *m0
, *mhdr
;
684 at_socket src_socket
;
687 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
689 gbuf_t
*mprev
, *mlist
= 0;
690 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
691 unsigned char *m0_rptr
, *m0_wptr
;
692 int err
, offset
, space
;
695 * get the user data structure pointer
697 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
700 * Guard against bogus count argument.
702 if ((unsigned) cnt
> ATP_TRESP_MAX
) {
703 dPrintf(D_M_ATP
, D_L_ERROR
,
704 ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt
));
708 if ((src_socket
= (at_socket
)atp
->atp_socket_no
) == 0xFF) {
709 /* comparison was to -1, however src_socket is a u_char */
716 rcbp
->rc_pktcnt
= cnt
;
717 rcbp
->rc_state
= RCB_SENDING
;
718 rcbp
->rc_not_sent_bitmap
= 0;
722 * special case this to
723 * improve AFP write transactions to the server
726 if ((m2
= gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,
729 gbuf_rinc(m2
,AT_WR_OFFSET
);
730 gbuf_wset(m2
,TOTAL_ATP_HDR_SIZE
);
731 *(struct ddp_atp
*)(gbuf_rptr(m2
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
732 athp
= AT_ATP_HDR(m2
);
733 ATP_CLEAR_CONTROL(athp
);
734 athp
->cmd
= ATP_CMD_TRESP
;
736 athp
->eom
= 1; /* there's only 1 fragment */
738 /* *** why only if cnt > 0? *** */
740 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
742 if (!append_copy((struct mbuf
*)m2
,
743 (struct mbuf
*)m0
, wait
)) {
748 * send the message and mark it as sent
750 AT_DDP_HDR(m2
)->src_socket
= src_socket
;
751 dPrintf(D_M_ATP_LOW
, D_L_INFO
,
752 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
753 0,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(m2
)),cnt
));
758 /* create an array of mbuf packet headers for the packets to be sent
759 * to contain the atp and ddp headers with room at the front for the
762 for (i
= 0; i
< cnt
; i
++) {
763 /* all hdrs, packet data and dst addr storage */
765 gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
, wait
)) == NULL
) {
766 for (cnt
= 0; cnt
< i
; cnt
++)
768 gbuf_freeb(rc_xmt
[cnt
]);
773 /* run through the atpBDS structs and create an mbuf for the data
774 * portion of each packet to be sent. these get chained to the mbufs
775 * containing the ATP and DDP headers. this code assumes that no ATP
776 * packet is contained in more than 2 mbufs (e.i crosses mbuf boundary
777 * no more than one time).
781 space
= gbuf_msgsize(m0
);
782 for (i
= 0; i
< cnt
; i
++) { /* for each hdr mbuf */
784 /* setup header fields */
785 gbuf_rinc(mhdr
,AT_WR_OFFSET
);
786 gbuf_wset(mhdr
,TOTAL_ATP_HDR_SIZE
);
787 *(struct ddp_atp
*)(gbuf_rptr(mhdr
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
788 athp
= AT_ATP_HDR(mhdr
);
789 ATP_CLEAR_CONTROL(athp
);
790 athp
->cmd
= ATP_CMD_TRESP
;
793 athp
->eom
= 1; /* for the last fragment */
794 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
796 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)) != 0 && m0
!= 0 && space
> 0) {
797 if ((m1
= m_copym(m0
, offset
, len
, wait
)) == 0) {
798 for (i
= 0; i
< cnt
; i
++)
800 gbuf_freem(rc_xmt
[i
]);
803 gbuf_cont(mhdr
) = m1
;
808 AT_DDP_HDR(mhdr
)->src_socket
= src_socket
;
809 dPrintf(D_M_ATP_LOW
,D_L_INFO
,
810 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
811 i
,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(mhdr
)),cnt
));
813 gbuf_next(mprev
) = mhdr
;
818 * on to the next frag
827 ATDISABLE(s_gen
, atpgen_lock
);
828 if (rcbp
->rc_timestamp
== 0) {
829 if ((rcbp
->rc_timestamp
= time
.tv_sec
) == 0)
830 rcbp
->rc_timestamp
= 1;
831 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
833 ATENABLE(s_gen
, atpgen_lock
);
839 } /* atp_unpack_bdsp */
841 #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6)
842 #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
843 static unsigned int sNext
= 0;
845 int atp_bind(gref
, sVal
, flag
)
850 extern unsigned char asp_inpC
[];
851 extern asp_scb_t
*asp_scbQ
[];
852 unsigned char inpC
, sNextUsed
= 0;
853 unsigned int sMin
, sMax
, sSav
;
854 struct atp_state
*atp
;
857 atp
= (struct atp_state
*)gref
->info
;
859 atp
= (struct atp_state
*)atp
->atp_msgq
;
861 sMax
= ATP_SOCKET_LAST
;
862 sMin
= ATP_SOCKET_FIRST
;
863 ATDISABLE(s
, atpgen_lock
);
864 if (flag
&& (*flag
== 3)) {
873 ((sVal
> sMax
) || (sVal
< 2) || (sVal
== 6) ||
874 (ddp_socket_inuse(sVal
, DDP_ATP
) &&
875 (atp_inputQ
[sVal
] != (gref_t
*)1)))) {
876 ATENABLE(s
, atpgen_lock
);
883 for (sVal
=sMin
; sVal
<= sMax
; sVal
++) {
884 if (!ddp_socket_inuse(sVal
, DDP_ATP
) ||
885 atp_inputQ
[sVal
] == (gref_t
*)1)
887 else if (flag
&& (*flag
== 3) && asp_scbQ
[sVal
]) {
888 if ((asp_scbQ
[sVal
]->dflag
== *flag
)
889 && (asp_inpC
[sVal
] < inpC
) ) {
890 inpC
= asp_inpC
[sVal
];
896 if (flag
&& (*flag
== 3)) {
900 sMin
= ATP_SOCKET_FIRST
+40;
904 *flag
= (unsigned char)sSav
;
906 ATENABLE(s
, atpgen_lock
);
910 atp
->atp_socket_no
= (short)sVal
;
911 atp_inputQ
[sVal
] = gref
;
913 atp_pidM
[sVal
] = atp
->atp_pid
;
914 else if (*flag
== 3) {
916 if (sNext
> ATP_SOCKET_LAST
)
920 ATENABLE(s
, atpgen_lock
);
924 void atp_req_ind(atp
, mioc
)
925 register struct atp_state
*atp
;
926 register gbuf_t
*mioc
;
928 register struct atp_rcb
*rcbp
;
931 if ((rcbp
= atp
->atp_attached
.head
) != 0) {
932 gbuf_cont(mioc
) = rcbp
->rc_ioctl
;
933 rcbp
->rc_ioctl
= NULL
;
934 ATDISABLE(s
, atp
->atp_lock
);
936 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
937 rcbp
->rc_state
= RCB_NOTIFIED
;
938 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
941 ATENABLE(s
, atp
->atp_lock
);
943 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
945 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
946 asp_ack_reply(atp
->atp_gref
, mioc
);
951 void atp_rsp_ind(trp
, mioc
)
952 register struct atp_trans
*trp
;
953 register gbuf_t
*mioc
;
955 register struct atp_state
*atp
= trp
->tr_queue
;
961 switch (trp
->tr_state
) {
963 if (asp_pack_bdsp(trp
, &xm
) < 0)
965 gbuf_cont(mioc
) = trp
->tr_xmt
;
980 dPrintf(D_M_ATP
, D_L_ERROR
,
981 ("atp_rsp_ind: TRANSACTION error\n"));
982 atp_iocnak(atp
, mioc
, err
);
984 gbuf_cont(gbuf_cont(mioc
)) = xm
;
985 atp_iocack(atp
, mioc
);
990 void atp_cancel_req(gref
, tid
)
995 struct atp_state
*atp
;
996 struct atp_trans
*trp
;
998 atp
= (struct atp_state
*)gref
->info
;
1000 atp
= (struct atp_state
*)atp
->atp_msgq
;
1002 ATDISABLE(s
, atp
->atp_lock
);
1003 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1004 if (trp
->tr_tid
== tid
)
1007 ATENABLE(s
, atp
->atp_lock
);
1013 * remove atp from the use list
1016 atp_dequeue_atp(atp
)
1017 struct atp_state
*atp
;
1021 ATDISABLE(s
, atpall_lock
);
1022 if (atp
== atp_used_list
) {
1023 if ((atp_used_list
= atp
->atp_trans_waiting
) != 0)
1024 atp
->atp_trans_waiting
->atp_rcb_waiting
= 0;
1025 } else if (atp
->atp_rcb_waiting
) {
1026 if ((atp
->atp_rcb_waiting
->atp_trans_waiting
1027 = atp
->atp_trans_waiting
) != 0)
1028 atp
->atp_trans_waiting
->atp_rcb_waiting
= atp
->atp_rcb_waiting
;
1031 atp
->atp_trans_waiting
= 0;
1032 atp
->atp_rcb_waiting
= 0;
1033 ATENABLE(s
, atpall_lock
);
1037 atp_timout(func
, trp
, ticks
)
1039 struct atp_trans
*trp
;
1044 struct atp_trans
*curr_trp
, *prev_trp
;
1046 ATDISABLE(s
, atptmo_lock
);
1047 if (trp
->tr_tmo_func
) {
1048 ATENABLE(s
, atptmo_lock
);
1052 trp
->tr_tmo_func
= func
;
1053 trp
->tr_tmo_delta
= 1+(ticks
>>5);
1055 if (trp_tmo_list
== 0) {
1056 trp
->tr_tmo_next
= trp
->tr_tmo_prev
= 0;
1058 ATENABLE(s
, atptmo_lock
);
1063 curr_trp
= trp_tmo_list
;
1067 sum
+= curr_trp
->tr_tmo_delta
;
1068 if (sum
> trp
->tr_tmo_delta
) {
1069 sum
-= curr_trp
->tr_tmo_delta
;
1070 trp
->tr_tmo_delta
-= sum
;
1071 curr_trp
->tr_tmo_delta
-= trp
->tr_tmo_delta
;
1074 prev_trp
= curr_trp
;
1075 if ((curr_trp
= curr_trp
->tr_tmo_next
) == 0) {
1076 trp
->tr_tmo_delta
-= sum
;
1082 trp
->tr_tmo_prev
= prev_trp
;
1083 if ((trp
->tr_tmo_next
= prev_trp
->tr_tmo_next
) != 0)
1084 prev_trp
->tr_tmo_next
->tr_tmo_prev
= trp
;
1085 prev_trp
->tr_tmo_next
= trp
;
1087 trp
->tr_tmo_prev
= 0;
1088 trp
->tr_tmo_next
= trp_tmo_list
;
1089 trp_tmo_list
->tr_tmo_prev
= trp
;
1092 ATENABLE(s
, atptmo_lock
);
1096 atp_untimout(func
, trp
)
1098 struct atp_trans
*trp
;
1102 ATDISABLE(s
, atptmo_lock
);
1103 if (trp
->tr_tmo_func
== 0) {
1104 ATENABLE(s
, atptmo_lock
);
1108 if (trp_tmo_list
== trp
) {
1109 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0) {
1110 trp_tmo_list
->tr_tmo_prev
= 0;
1111 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1114 if ((trp
->tr_tmo_prev
->tr_tmo_next
= trp
->tr_tmo_next
) != 0) {
1115 trp
->tr_tmo_next
->tr_tmo_prev
= trp
->tr_tmo_prev
;
1116 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1119 trp
->tr_tmo_func
= 0;
1120 ATENABLE(s
, atptmo_lock
);
1124 atp_trp_clock_funnel(arg
)
1127 thread_funnel_set(network_flock
, TRUE
);
1129 thread_funnel_set(network_flock
, FALSE
);
1137 struct atp_trans
*trp
;
1138 void (*tr_tmo_func
)();
1140 ATDISABLE(s
, atptmo_lock
);
1142 trp_tmo_list
->tr_tmo_delta
--;
1143 while (((trp
= trp_tmo_list
) != 0) && (trp_tmo_list
->tr_tmo_delta
== 0)) {
1144 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0)
1145 trp_tmo_list
->tr_tmo_prev
= 0;
1146 if ((tr_tmo_func
= trp
->tr_tmo_func
) != 0) {
1147 trp
->tr_tmo_func
= 0;
1148 ATENABLE(s
, atptmo_lock
);
1149 (*tr_tmo_func
)(trp
);
1150 ATDISABLE(s
, atptmo_lock
);
1153 ATENABLE(s
, atptmo_lock
);
1155 timeout(atp_trp_clock_funnel
, (void *)arg
, (1<<5));
1159 atp_send_req(gref
, mioc
)
1163 register struct atp_state
*atp
;
1164 register struct atp_trans
*trp
;
1165 register ioc_t
*iocbp
;
1166 register at_atp_t
*athp
;
1167 register at_ddp_t
*ddp
;
1168 gbuf_t
*m
, *m2
, *bds
;
1169 struct atp_set_default
*sdb
;
1173 atp
= (struct atp_state
*)((struct atp_state
*)gref
->info
)->atp_msgq
;
1174 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1176 if ((trp
= atp_trans_alloc(atp
)) == NULL
) {
1178 ((asp_scb_t
*)gref
->info
)->stat_msg
= mioc
;
1179 iocbp
->ioc_private
= (void *)gref
;
1180 timeout(atp_retry_req
, mioc
, 10);
1184 m2
= gbuf_cont(mioc
);
1185 if ((bds
= gbuf_dupb(m2
)) == NULL
) {
1186 atp_trans_free(trp
);
1189 gbuf_rinc(m2
,atpBDSsize
);
1190 gbuf_wset(bds
,atpBDSsize
);
1191 iocbp
->ioc_count
-= atpBDSsize
;
1192 gbuf_cont(m2
) = NULL
;
1194 old
= iocbp
->ioc_cmd
;
1195 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
1196 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1199 * The at_snd_req library routine multiplies seconds by 100.
1200 * We need to divide by 100 in order to obtain the timer.
1202 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1204 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1205 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1207 trp
->tr_retry
= sdb
->def_retries
;
1208 trp
->tr_timeout
= timer
;
1210 trp
->tr_tid
= atp_tid(atp
);
1214 * Now fill in the header (and remember the bits
1217 athp
= AT_ATP_HDR(m2
);
1218 athp
->cmd
= ATP_CMD_TREQ
;
1219 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1222 trp
->tr_xo
= athp
->xo
;
1223 trp
->tr_bitmap
= athp
->bitmap
;
1224 ddp
= AT_DDP_HDR(m2
);
1225 ddp
->type
= DDP_ATP
;
1226 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1227 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1228 trp
->tr_socket
.node
= ddp
->dst_node
;
1229 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1230 trp
->tr_local_socket
= atp
->atp_socket_no
;
1231 trp
->tr_local_node
= ddp
->src_node
;
1232 NET_NET(trp
->tr_local_net
, ddp
->src_net
);
1235 /* save the local information in the gref */
1236 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1237 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1238 atp
->atp_gref
->lport
= ddp
->src_node
;
1239 atp
->atp_gref
->ddptype
= DDP_ATP
;
1243 * Put us in the transaction waiting queue
1245 ATDISABLE(s
, atp
->atp_lock
);
1246 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1247 ATENABLE(s
, atp
->atp_lock
);
1250 * Send the message and set the timer
1252 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1253 if (!trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1254 atp_x_done(trp
); /* no reason to tie up resources */
1256 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1258 trace_mbufs(D_M_ATP_LOW
, " s", m
);
1261 } /* atp_send_req */
1263 void atp_retry_req(m
)
1267 boolean_t funnel_state
;
1269 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1271 gref
= (gref_t
*)((ioc_t
*)gbuf_rptr(m
))->ioc_private
;
1273 ((asp_scb_t
*)gref
->info
)->stat_msg
= 0;
1274 atp_send_req(gref
, m
);
1276 (void) thread_funnel_set(network_flock
, FALSE
);
1279 void atp_send_rsp(gref
, m
, wait
)
1284 register struct atp_state
*atp
;
1285 register struct atp_rcb
*rcbp
;
1286 register at_atp_t
*athp
;
1287 register at_ddp_t
*ddp
;
1290 atp
= (struct atp_state
*)gref
->info
;
1292 atp
= (struct atp_state
*)atp
->atp_msgq
;
1293 ddp
= AT_DDP_HDR(m
);
1294 athp
= AT_ATP_HDR(m
);
1297 * search for the corresponding rcb
1299 ATDISABLE(s
, atp
->atp_lock
);
1300 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1301 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1302 (rcbp
->rc_socket
.node
== ddp
->dst_node
) &&
1303 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
)) &&
1304 (rcbp
->rc_socket
.socket
== ddp
->dst_socket
) )
1309 * If it has already been sent then drop the request
1311 if ((rcbp
&& (rcbp
->rc_state
!= RCB_NOTIFIED
)) ||
1312 (rcbp
== NULL
&& athp
->xo
) ) {
1313 ATENABLE(s
, atp
->atp_lock
);
1317 ATENABLE(s
, atp
->atp_lock
);
1319 if (rcbp
== NULL
) { /* a response is being sent for an ALO transaction */
1320 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
1325 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
1326 rcbp
->rc_socket
.node
= ddp
->dst_node
;
1327 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
1328 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
1329 rcbp
->rc_bitmap
= 0xff;
1331 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
1332 ATDISABLE(s
, atp
->atp_lock
);
1333 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1334 ATENABLE(s
, atp
->atp_lock
);
1336 else if (ddp
->src_node
== 0) {
1337 NET_NET(ddp
->src_net
, rcbp
->rc_local_net
);
1338 ddp
->src_node
= rcbp
->rc_local_node
;
1341 xcnt
= get_bds_entries(m
);
1342 s
= atp_unpack_bdsp(atp
, m
, rcbp
, xcnt
, wait
);
1344 atp_send_replies(atp
, rcbp
);
1345 } /* atp_send_rsp */
1347 int asp_pack_bdsp(trp
, xm
)
1348 register struct atp_trans
*trp
;
1351 register struct atpBDS
*bdsp
;
1352 register gbuf_t
*m
, *m2
;
1354 gbuf_t
*m_prev
, *m_head
= 0;
1356 dPrintf(D_M_ATP
, D_L_INFO
, ("asp_pack_bdsp: socket=%d\n",
1357 trp
->tr_queue
->atp_socket_no
));
1359 if ((m2
= trp
->tr_bdsp
) == NULL
)
1361 trp
->tr_bdsp
= NULL
;
1362 bdsp
= (struct atpBDS
*)gbuf_rptr(m2
);
1364 for (i
= 0; (i
< ATP_TRESP_MAX
&&
1365 bdsp
< (struct atpBDS
*)(gbuf_wptr(m2
))); i
++) {
1366 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
1369 /* discard ddp hdr on first packet */
1370 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
1373 UAL_UAL(bdsp
->bdsUserData
, (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
1374 gbuf_rinc(m
, ATP_HDR_SIZE
);
1376 if (UAL_VALUE(bdsp
->bdsBuffAddr
)) {
1379 /* user expects data back */
1384 gbuf_cont(m_prev
) = m
;
1386 tmp
= (short)gbuf_len(m
);
1387 while (gbuf_cont(m
)) {
1389 tmp
+= (short)(gbuf_len(m
));
1393 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
1395 trp
->tr_rcv
[i
] = NULL
;
1400 * report the number of packets
1402 UAS_ASSIGN(((struct atpBDS
*)gbuf_rptr(m2
))->bdsBuffSz
, i
);
1404 if (trp
->tr_xmt
) /* an ioctl block is still held? */
1405 gbuf_cont(trp
->tr_xmt
) = m2
;
1414 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
1415 gbuf_msgsize(*xm
)));
1421 * The following routines are direct entries from system
1422 * calls to allow fast sending and recving of ATP data.
1426 _ATPsndreq(fd
, buf
, len
, nowait
, err
, proc
)
1438 register struct atp_state
*atp
;
1439 register struct atp_trans
*trp
;
1440 register ioc_t
*iocbp
;
1441 register at_atp_t
*athp
;
1442 register at_ddp_t
*ddp
;
1443 struct atp_set_default
*sdb
;
1444 gbuf_t
*m2
, *m
, *mioc
;
1445 char bds
[atpBDSsize
];
1447 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 0)
1450 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1451 || (atp
->atp_flags
& ATP_CLOSING
)) {
1452 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
1453 (u_int
) gref
, gref
->pid
));
1459 while ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_MED
)) == 0) {
1460 ATDISABLE(s
, atp
->atp_delay_lock
);
1461 rc
= tsleep(&atp
->atp_delay_event
, PSOCK
| PCATCH
, "atpmioc", 10);
1462 ATENABLE(s
, atp
->atp_delay_lock
);
1469 gbuf_wset(mioc
,sizeof(ioc_t
));
1471 while ((m2
= gbuf_alloc(len
, PRI_MED
)) == 0) {
1472 ATDISABLE(s
, atp
->atp_delay_lock
);
1473 rc
= tsleep(&atp
->atp_delay_event
, PSOCK
| PCATCH
, "atpm2", 10);
1474 ATENABLE(s
, atp
->atp_delay_lock
);
1482 gbuf_cont(mioc
) = m2
;
1483 if (((*err
= copyin((caddr_t
)buf
, (caddr_t
)bds
, atpBDSsize
)) != 0)
1484 || ((*err
= copyin((caddr_t
)&buf
[atpBDSsize
],
1485 (caddr_t
)gbuf_rptr(m2
), len
)) != 0)) {
1489 gbuf_set_type(mioc
, MSG_IOCTL
);
1490 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1491 iocbp
->ioc_count
= len
;
1492 iocbp
->ioc_cmd
= nowait
? AT_ATP_ISSUE_REQUEST_NOTE
: AT_ATP_ISSUE_REQUEST
;
1493 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1496 * The at_snd_req library routine multiplies seconds by 100.
1497 * We need to divide by 100 in order to obtain the timer.
1499 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1501 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1502 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1505 * allocate and set up the transaction record
1507 while ((trp
= atp_trans_alloc(atp
)) == 0) {
1508 ATDISABLE(s
, atp
->atp_delay_lock
);
1509 rc
= tsleep(&atp
->atp_delay_event
, PSOCK
| PCATCH
, "atptrp", 10);
1510 ATENABLE(s
, atp
->atp_delay_lock
);
1517 trp
->tr_retry
= sdb
->def_retries
;
1518 trp
->tr_timeout
= timer
;
1519 trp
->tr_bdsp
= NULL
;
1520 trp
->tr_tid
= atp_tid(atp
);
1524 * remember the IOCTL packet so we can ack it
1530 * Now fill in the header (and remember the bits
1533 athp
= AT_ATP_HDR(m2
);
1534 athp
->cmd
= ATP_CMD_TREQ
;
1535 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1538 trp
->tr_xo
= athp
->xo
;
1539 trp
->tr_bitmap
= athp
->bitmap
;
1540 ddp
= AT_DDP_HDR(m2
);
1541 ddp
->type
= DDP_ATP
;
1542 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1544 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1545 trp
->tr_socket
.node
= ddp
->dst_node
;
1546 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1547 trp
->tr_local_socket
= atp
->atp_socket_no
;
1550 /* save the local information in the gref */
1551 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1552 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1553 atp
->atp_gref
->lport
= ddp
->src_node
;
1554 atp
->atp_gref
->ddptype
= DDP_ATP
;
1558 * Put us in the transaction waiting queue
1560 ATDISABLE(s
, atp
->atp_lock
);
1561 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1562 ATENABLE(s
, atp
->atp_lock
);
1565 * Send the message and set the timer
1567 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1568 if ( !trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1569 atp_x_done(trp
); /* no reason to tie up resources */
1571 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1579 * wait for the transaction to complete
1581 ATDISABLE(s
, trp
->tr_lock
);
1582 while ((trp
->tr_state
!= TRANS_DONE
) && (trp
->tr_state
!= TRANS_FAILED
) &&
1583 (trp
->tr_state
!= TRANS_ABORTING
)) {
1584 trp
->tr_rsp_wait
= 1;
1585 rc
= tsleep(&trp
->tr_event
, PSOCK
| PCATCH
, "atpsndreq", 0);
1587 trp
->tr_rsp_wait
= 0;
1588 ATENABLE(s
, trp
->tr_lock
);
1593 trp
->tr_rsp_wait
= 0;
1594 ATENABLE(s
, trp
->tr_lock
);
1597 if (trp
->tr_state
== TRANS_FAILED
|| trp
->tr_state
== TRANS_ABORTING
) {
1599 * transaction timed out, return error
1607 * copy out the recv data
1609 atp_pack_bdsp(trp
, bds
);
1612 * copyout the result info
1614 copyout((caddr_t
)bds
, (caddr_t
)buf
, atpBDSsize
);
1622 /* entry point for ATP send response. respbuf contains a DDP hdr,
1623 * ATP hdr, and atpBDS array. The bdsDataSz field of the first atpBDS
1624 * struct contains the number of atpBDS structs in the array. resplen
1625 * contains the len of the data in respbuf and datalen contains the
1626 * len of the data buffer holding the response packets which the atpBDS
1627 * struct entries point to.
1630 _ATPsndrsp(fd
, respbuff
, resplen
, datalen
, err
, proc
)
1632 unsigned char *respbuff
;
1644 struct atp_state
*atp
;
1645 struct atpBDS
*bdsp
;
1648 int bds_cnt
, count
, len
;
1651 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 0)
1654 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1655 || (atp
->atp_flags
& ATP_CLOSING
)) {
1656 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
1657 (u_int
) gref
, gref
->pid
));
1664 * allocate buffer and copy in the response info
1666 if ((m
= gbuf_alloc_wait(resplen
, TRUE
)) == 0) {
1670 if ((*err
= copyin((caddr_t
)respbuff
, (caddr_t
)gbuf_rptr(m
), resplen
)) != 0) {
1674 gbuf_wset(m
,resplen
);
1675 ((at_ddp_t
*)gbuf_rptr(m
))->src_node
= 0;
1676 bdsp
= (struct atpBDS
*)(gbuf_rptr(m
) + TOTAL_ATP_HDR_SIZE
);
1679 * allocate buffers and copy in the response data.
1680 * note that only the size field of the atpBDS field
1681 * is used internally in the kernel.
1683 bds_cnt
= get_bds_entries(m
); /* count of # entries */
1684 /* check correctness of parameters */
1685 if (bds_cnt
> ATP_TRESP_MAX
) {
1691 for (size
= 0, count
= 0; count
< bds_cnt
; count
++) {
1692 size
+= UAS_VALUE(bdsp
[count
].bdsBuffSz
);
1694 if (size
> datalen
) {
1700 /* get the first mbuf */
1701 if ((mdata
= gbuf_alloc_wait((space
= (size
> MCLBYTES
? MCLBYTES
: size
)), TRUE
)) == 0) {
1706 gbuf_cont(m
) = mdata
;
1707 dataptr
= mtod(mdata
, caddr_t
);
1708 for (count
= 0; count
< bds_cnt
; bdsp
++, count
++) {
1709 if ((bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
)) != 0 &&
1710 (len
= UAS_VALUE(bdsp
->bdsBuffSz
)) != 0) {
1711 if (len
> space
) { /* enough room ? */
1712 gbuf_wset(mdata
, dataptr
- mtod(mdata
, caddr_t
)); /* set len of last mbuf */
1713 /* allocate the next mbuf */
1714 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
1719 mdata
= gbuf_cont(mdata
);
1720 MCLGET(mdata
, M_WAIT
);
1721 if (!(mdata
->m_flags
& M_EXT
)) {
1725 dataptr
= mtod(mdata
, caddr_t
);
1729 if ((*err
= copyin((caddr_t
)bufaddr
, dataptr
, len
)) != 0) {
1737 gbuf_wset(mdata
, dataptr
- mtod(mdata
, caddr_t
)); /* set len of last mbuf */
1738 gbuf_cont(m
)->m_pkthdr
.len
= size
; /* set packet hdr len */
1740 atp_send_rsp(gref
, m
, TRUE
);
1745 _ATPgetreq(fd
, buf
, buflen
, err
, proc
)
1753 register struct atp_state
*atp
;
1754 register struct atp_rcb
*rcbp
;
1755 register gbuf_t
*m
, *m_head
;
1758 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 0)
1761 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1762 || (atp
->atp_flags
& ATP_CLOSING
)) {
1763 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
1764 (u_int
) gref
, gref
->pid
));
1769 ATDISABLE(s
, atp
->atp_lock
);
1770 if ((rcbp
= atp
->atp_attached
.head
) != NULL
) {
1772 * Got one, move it to the active response Q
1774 m_head
= rcbp
->rc_ioctl
;
1775 rcbp
->rc_ioctl
= NULL
;
1778 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
1779 rcbp
->rc_state
= RCB_NOTIFIED
;
1780 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1782 /* detach rcbp from attached queue,
1783 * and free any outstanding resources
1787 ATENABLE(s
, atp
->atp_lock
);
1790 * copyout the request data, including the protocol header
1792 for (size
=0, m
=m_head
; m
; m
= gbuf_cont(m
)) {
1793 if ((len
= gbuf_len(m
)) > buflen
)
1795 copyout((caddr_t
)gbuf_rptr(m
), (caddr_t
)&buf
[size
], len
);
1797 if ((buflen
-= len
) == 0)
1804 ATENABLE(s
, atp
->atp_lock
);
1810 _ATPgetrsp(fd
, bdsp
, err
, proc
)
1812 struct atpBDS
*bdsp
;
1817 register struct atp_state
*atp
;
1818 register struct atp_trans
*trp
;
1820 char bds
[atpBDSsize
];
1822 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 0)
1825 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1826 || (atp
->atp_flags
& ATP_CLOSING
)) {
1827 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
1828 (u_int
) gref
, gref
->pid
));
1833 ATDISABLE(s
, atp
->atp_lock
);
1834 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1835 dPrintf(D_M_ATP
, D_L_INFO
,
1836 ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
1837 (u_int
) atp
, (u_int
) trp
, trp
->tr_state
));
1839 switch (trp
->tr_state
) {
1841 ATENABLE(s
, atp
->atp_lock
);
1842 if ((*err
= copyin((caddr_t
)bdsp
,
1843 (caddr_t
)bds
, sizeof(bds
))) != 0)
1845 atp_pack_bdsp(trp
, bds
);
1846 tid
= (int)trp
->tr_tid
;
1848 copyout((caddr_t
)bds
, (caddr_t
)bdsp
, sizeof(bds
));
1853 * transaction timed out, return error
1855 ATENABLE(s
, atp
->atp_lock
);
1864 ATENABLE(s
, atp
->atp_lock
);
1871 atp_drop_req(gref
, m
)
1876 struct atp_state
*atp
;
1877 struct atp_rcb
*rcbp
;
1881 atp
= (struct atp_state
*)gref
->info
;
1883 atp
= (struct atp_state
*)atp
->atp_msgq
;
1884 ddp
= AT_DDP_HDR(m
);
1885 athp
= AT_ATP_HDR(m
);
1888 * search for the corresponding rcb
1890 ATDISABLE(s
, atp
->atp_lock
);
1891 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1892 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1893 (rcbp
->rc_socket
.node
== ddp
->src_node
) &&
1894 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->src_net
)) &&
1895 (rcbp
->rc_socket
.socket
== ddp
->src_socket
) )
1904 ATENABLE(s
, atp
->atp_lock
);