2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1996-1998 Apple Computer, Inc.
32 * All Rights Reserved.
35 /* Modified for MP, 1996 by Tuyen Nguyen
36 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
40 #include <sys/errno.h>
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <machine/spl.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
47 #include <sys/filedesc.h>
48 #include <sys/fcntl.h>
49 #include <kern/locks.h>
51 #include <sys/ioctl.h>
52 #include <sys/malloc.h>
53 #include <sys/socket.h>
54 #include <sys/socketvar.h>
58 #include <netat/sysglue.h>
59 #include <netat/appletalk.h>
60 #include <netat/ddp.h>
61 #include <netat/at_pcb.h>
62 #include <netat/atp.h>
63 #include <netat/at_var.h>
64 #include <netat/asp.h>
65 #include <netat/at_pat.h>
66 #include <netat/debug.h>
68 static int loop_cnt
; /* for debugging loops */
69 #define CHK_LOOP(str) { \
70 if (loop_cnt++ > 100) { \
76 static int atp_pack_bdsp(struct atp_trans
*, struct atpBDS
*);
77 static int atp_unpack_bdsp(struct atp_state
*, gbuf_t
*, struct atp_rcb
*,
79 void atp_trp_clock(), asp_clock(), asp_clock_locked(), atp_trp_clock_locked();;
81 extern struct atp_rcb_qhead atp_need_rel
;
82 extern int atp_inited
;
83 extern struct atp_state
*atp_used_list
;
84 extern asp_scb_t
*scb_free_list
;
86 extern gbuf_t
*scb_resource_m
;
87 extern gbuf_t
*atp_resource_m
;
88 extern gref_t
*atp_inputQ
[];
89 extern int atp_pidM
[];
90 extern at_ifaddr_t
*ifID_home
;
91 extern lck_mtx_t
* atalk_mutex
;
93 static struct atp_trans
*trp_tmo_list
;
94 struct atp_trans
*trp_tmo_rcb
;
96 /* first bds entry gives number of bds entries in total (hack) */
97 #define get_bds_entries(m) \
98 ((gbuf_len(m) > TOTAL_ATP_HDR_SIZE)? \
99 (UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz)): 0)
101 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
106 trp_tmo_rcb
= atp_trans_alloc(0);
107 atp_timout(atp_rcb_timer
, trp_tmo_rcb
, 10 * HZ
);
108 atp_trp_clock((void *)&atp_inited
);
109 asp_clock((void *)&atp_inited
);
114 untimeout(asp_clock_locked
, (void *)&atp_inited
);
115 untimeout(atp_trp_clock_locked
, (void *)&atp_inited
);
116 atp_untimout(atp_rcb_timer
, trp_tmo_rcb
);
120 /* allocated in asp_scb_alloc(), which is called
122 if (scb_resource_m
) {
123 gbuf_freem(scb_resource_m
);
127 /* allocated in atp_trans_alloc() */
128 if (atp_resource_m
) {
129 gbuf_freem(atp_resource_m
);
131 atp_trans_free_list
= 0;
137 * write queue put routine .... filter out other than IOCTLs
138 * Version 1.8 of atp_write.c on 89/02/09 17:53:26
143 register gref_t
*gref
;
146 register ioc_t
*iocbp
;
148 struct atp_state
*atp
;
149 struct atp_trans
*trp
;
150 struct atp_rcb
*rcbp
;
153 atp
= (struct atp_state
*)gref
->info
;
155 atp
= (struct atp_state
*)atp
->atp_msgq
;
157 switch(gbuf_type(m
)) {
161 dPrintf(D_M_ATP
, D_L_WARNING
,
162 ("atp_wput: atp_msgq discarded\n"));
168 /* Need to ensure that all copyin/copyout calls are made at
169 * put routine time which should be in the user context. (true when
170 * we are the stream head). The service routine can be called on an
171 * unpredictable context and copyin/copyout calls will get wrong results
172 * or even panic the kernel.
174 iocbp
= (ioc_t
*)gbuf_rptr(m
);
176 switch (iocbp
->ioc_cmd
) {
177 case AT_ATP_BIND_REQ
:
178 if (gbuf_cont(m
) == NULL
) {
179 iocbp
->ioc_rval
= -1;
180 atp_iocnak(atp
, m
, EINVAL
);
183 skt
= *(at_socket
*)gbuf_rptr(gbuf_cont(m
));
184 if ((skt
= (at_socket
)atp_bind(gref
, (unsigned int)skt
, 0)) == 0)
185 atp_iocnak(atp
, m
, EINVAL
);
187 *(at_socket
*)gbuf_rptr(gbuf_cont(m
)) = skt
;
190 atp_dequeue_atp(atp
);
194 case AT_ATP_GET_CHANID
:
195 if (gbuf_cont(m
) == NULL
) {
196 iocbp
->ioc_rval
= -1;
197 atp_iocnak(atp
, m
, EINVAL
);
200 *(gref_t
**)gbuf_rptr(gbuf_cont(m
)) = gref
;
204 /* not the close and not the tickle(?) */
205 case AT_ATP_ISSUE_REQUEST_DEF
:
206 case AT_ATP_ISSUE_REQUEST_DEF_NOTE
: {
207 gbuf_t
*bds
, *tmp
, *m2
;
208 struct atp_rcb
*rcbp
;
212 if ((tmp
= gbuf_cont(m
)) != 0) {
213 if ((bds
= gbuf_dupb(tmp
)) == NULL
) {
214 atp_iocnak(atp
, m
, ENOBUFS
);
217 gbuf_rinc(tmp
,atpBDSsize
);
218 gbuf_wset(bds
,atpBDSsize
);
219 iocbp
->ioc_count
-= atpBDSsize
;
220 gbuf_cont(tmp
) = bds
;
224 * send a response to a transaction
227 if (iocbp
->ioc_count
< TOTAL_ATP_HDR_SIZE
) {
228 atp_iocnak(atp
, m
, EINVAL
);
233 * remove the response from the message
237 iocbp
->ioc_count
= 0;
238 ddp
= AT_DDP_HDR(m2
);
239 athp
= AT_ATP_HDR(m2
);
241 gbuf_cont(m2
) = atp
->atp_msgq
;
246 * search for the corresponding rcb
248 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
249 if (rcbp
->rc_tid
== UAS_VALUE_NTOH(athp
->tid
) &&
250 rcbp
->rc_socket
.node
== ddp
->dst_node
&&
251 rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
) &&
252 rcbp
->rc_socket
.socket
== ddp
->dst_socket
)
257 * If it has already been sent then return an error
259 if ((rcbp
&& rcbp
->rc_state
!= RCB_NOTIFIED
) ||
260 (rcbp
== NULL
&& athp
->xo
)) {
261 atp_iocnak(atp
, m
, ENOENT
);
265 if (rcbp
== NULL
) { /* a response for an ALO transaction */
266 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
267 atp_iocnak(atp
, m
, ENOBUFS
);
272 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
273 rcbp
->rc_socket
.node
= ddp
->dst_node
;
274 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
275 rcbp
->rc_tid
= UAS_VALUE_NTOH(athp
->tid
);
276 rcbp
->rc_bitmap
= 0xff;
278 rcbp
->rc_state
= RCB_SENDING
;
279 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
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 if ((rcbp
= atp
->atp_attached
.head
)) {
309 * Got one, move it to the active response Q
311 gbuf_cont(m
) = rcbp
->rc_ioctl
;
312 rcbp
->rc_ioctl
= NULL
;
314 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
315 rcbp
->rc_state
= RCB_NOTIFIED
;
316 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
318 /* detach rcbp from attached queue,
319 * and free any outstanding resources
326 * None available - can out
328 atp_iocnak(atp
, m
, EAGAIN
);
333 case AT_ATP_CANCEL_REQUEST
: {
335 * Cancel a pending request
337 if (iocbp
->ioc_count
!= sizeof(int)) {
338 atp_iocnak(atp
, m
, EINVAL
);
341 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
342 gbuf_freem(gbuf_cont(m
));
344 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
345 if (trp
->tr_tid
== i
)
349 atp_iocnak(atp
, m
, ENOENT
);
359 if (atalk_peek(gref
, &event
) == -1)
360 atp_iocnak(atp
, m
, EAGAIN
);
362 *gbuf_rptr(gbuf_cont(m
)) = event
;
368 case DDP_IOC_GET_CFG
:
369 #ifdef APPLETALK_DEBUG
370 kprintf("atp_wput: DDP_IOC_GET_CFG\n");
372 if (gbuf_cont(m
) == 0) {
373 atp_iocnak(atp
, m
, EINVAL
);
377 /* *** was ddp_get_cfg() *** */
379 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(m
));
380 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
381 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
382 cfgp
->inet
.socket
= atp
->atp_socket_no
;
383 cfgp
->ddptype
= DDP_ATP
;
385 cfgp
->inet
.net
= atp
->atp_gref
->laddr
.s_net
;
386 cfgp
->inet
.node
= atp
->atp_gref
->laddr
.s_node
;
387 cfgp
->inet
.socket
= atp
->atp_gref
->lport
;
388 cfgp
->ddptype
= atp
->atp_gref
->ddptype
;
391 gbuf_wset(gbuf_cont(m
), sizeof(ddp_addr_t
));
397 * Otherwise pass it on, if possible
399 iocbp
->ioc_private
= (void *)gref
;
411 gbuf_t
*atp_build_release(trp
)
412 register struct atp_trans
*trp
;
415 register at_ddp_t
*ddp
;
416 register at_atp_t
*athp
;
419 * Now try and allocate enough space to send the message
420 * if none is available the caller will schedule
421 * a timeout so we can retry for more space soon
423 if ((m
= (gbuf_t
*)gbuf_alloc(AT_WR_OFFSET
+ATP_HDR_SIZE
, PRI_HI
)) != NULL
) {
424 gbuf_rinc(m
,AT_WR_OFFSET
);
425 gbuf_wset(m
,TOTAL_ATP_HDR_SIZE
);
428 UAS_ASSIGN_HTON(ddp
->checksum
, 0);
429 ddp
->dst_socket
= trp
->tr_socket
.socket
;
430 ddp
->dst_node
= trp
->tr_socket
.node
;
431 NET_ASSIGN(ddp
->dst_net
, trp
->tr_socket
.net
);
432 ddp
->src_node
= trp
->tr_local_node
;
433 NET_NET(ddp
->src_net
, trp
->tr_local_net
);
436 * clear the cmd/xo/eom/sts/unused fields
438 athp
= AT_ATP_HDR(m
);
439 ATP_CLEAR_CONTROL(athp
);
440 athp
->cmd
= ATP_CMD_TREL
;
441 UAS_ASSIGN_HTON(athp
->tid
, trp
->tr_tid
);
447 void atp_send_replies(atp
, rcbp
)
448 register struct atp_state
*atp
;
449 register struct atp_rcb
*rcbp
;
450 { register gbuf_t
*m
;
452 int s_gen
, cnt
, err
, offset
, space
;
453 unsigned char *m0_rptr
= NULL
, *m0_wptr
= NULL
;
454 register at_atp_t
*athp
;
455 register struct atpBDS
*bdsp
;
456 register gbuf_t
*m2
, *m1
, *m0
, *mhdr
;
458 gbuf_t
*mprev
, *mlist
= 0;
459 at_socket src_socket
= (at_socket
)atp
->atp_socket_no
;
460 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
462 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
464 struct timeval timenow
;
466 if (rcbp
->rc_queue
!= atp
)
468 if (rcbp
->rc_not_sent_bitmap
== 0)
469 goto nothing_to_send
;
471 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
, ("atp_send_replies\n"));
473 * Do this for each message that hasn't been sent
475 cnt
= rcbp
->rc_pktcnt
;
476 for (i
= 0; i
< cnt
; i
++) {
478 if (rcbp
->rc_snd
[i
]) {
480 gbuf_alloc(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,PRI_MED
))
482 for (cnt
= 0; cnt
< i
; cnt
++)
484 gbuf_freeb(rc_xmt
[cnt
]);
485 goto nothing_to_send
;
492 if (gbuf_len(m
) > TOTAL_ATP_HDR_SIZE
)
493 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
498 space
= gbuf_msgsize(m0
);
501 for (i
= 0; i
< cnt
; i
++) {
502 if (rcbp
->rc_snd
[i
] == 0) {
503 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
))) {
509 /* setup header fields */
510 gbuf_rinc(mhdr
,AT_WR_OFFSET
);
511 gbuf_wset(mhdr
,TOTAL_ATP_HDR_SIZE
);
512 *(struct ddp_atp
*)(gbuf_rptr(mhdr
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
513 athp
= AT_ATP_HDR(mhdr
);
514 ATP_CLEAR_CONTROL(athp
);
515 athp
->cmd
= ATP_CMD_TRESP
;
518 athp
->eom
= 1; /* for the last fragment */
520 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
521 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)) && m0
!= 0 && space
> 0) {
522 if ((m1
= m_copym(m0
, offset
, len
, M_DONTWAIT
)) == 0) {
523 for (i
= 0; i
< cnt
; i
++)
525 gbuf_freem(rc_xmt
[i
]);
526 goto nothing_to_send
;
530 gbuf_cont(mhdr
) = m1
;
534 AT_DDP_HDR(mhdr
)->src_socket
= src_socket
;
535 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
,
536 ("atp_send_replies: %d, socket=%d, size=%d\n",
537 i
, atp
->atp_socket_no
, gbuf_msgsize(gbuf_cont(m2
))));
540 gbuf_next(mprev
) = mhdr
;
546 rcbp
->rc_not_sent_bitmap
&= ~atp_mask
[i
];
547 if (rcbp
->rc_not_sent_bitmap
== 0)
551 * on to the next frag
561 * If all replies from this reply block have been sent then
562 * remove it from the queue and mark it so
564 if (rcbp
->rc_queue
!= atp
)
566 rcbp
->rc_rep_waiting
= 0;
569 * If we are doing execute once re-set the rcb timeout
570 * each time we send back any part of the response. Note
571 * that this timer is started when an initial request is
572 * received. Each response reprimes the timer. Duplicate
573 * requests do not reprime the timer.
575 * We have sent all of a response so free the
578 if (rcbp
->rc_xo
&& rcbp
->rc_state
!= RCB_RELEASED
) {
579 getmicrouptime(&timenow
);
580 if (rcbp
->rc_timestamp
== 0) {
581 rcbp
->rc_timestamp
= timenow
.tv_sec
;
582 if (rcbp
->rc_timestamp
== 0)
583 rcbp
->rc_timestamp
= 1;
584 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
586 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
589 } /* atp_send_replies */
593 atp_pack_bdsp(trp
, bdsp
)
594 register struct atp_trans
*trp
;
595 register struct atpBDS
*bdsp
;
597 register gbuf_t
*m
= NULL
;
598 register int i
, datsize
= 0;
599 struct atpBDS
*bdsbase
= bdsp
;
602 dPrintf(D_M_ATP
, D_L_INFO
, ("atp_pack_bdsp: socket=%d\n",
603 trp
->tr_queue
->atp_socket_no
));
605 for (i
= 0; i
< ATP_TRESP_MAX
; i
++, bdsp
++) {
606 unsigned short bufsize
= UAS_VALUE(bdsp
->bdsBuffSz
);
607 long bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
);
609 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
612 /* discard ddp hdr on first packet */
614 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
616 /* this field may contain control information even when
617 no data is present */
618 UAL_UAL(bdsp
->bdsUserData
,
619 (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
620 gbuf_rinc(m
, ATP_HDR_SIZE
);
622 if ((bufsize
!= 0) && (bufaddr
!= 0)) {
623 /* user expects data back */
625 register char *buf
= (char *)bufaddr
;
628 unsigned short len
= (unsigned short)(gbuf_len(m
));
632 if ((error
= copyout((caddr_t
)gbuf_rptr(m
),
633 CAST_USER_ADDR_T(&buf
[tmp
]),
643 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
646 gbuf_freem(trp
->tr_rcv
[i
]);
647 trp
->tr_rcv
[i
] = NULL
;
650 /* report the number of packets */
651 UAS_ASSIGN(((struct atpBDS
*)bdsbase
)->bdsBuffSz
, i
);
653 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
657 } /* atp_pack_bdsp */
660 /* create an mbuf chain with mbuf packet headers for each ATP response packet
661 * to be sent. m contains the DDP hdr, ATP hdr, and and array of atpBDS structs.
662 * chained to m is an mbuf that contians the actual data pointed to by the atpBDS
666 atp_unpack_bdsp(atp
, m
, rcbp
, cnt
, wait
)
667 struct atp_state
*atp
;
668 gbuf_t
*m
; /* ddp, atp and bdsp gbuf_t */
669 register struct atp_rcb
*rcbp
;
670 register int cnt
, wait
;
672 register struct atpBDS
*bdsp
;
673 register gbuf_t
*m2
, *m1
, *m0
, *mhdr
;
677 at_socket src_socket
;
680 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
682 gbuf_t
*mprev
, *mlist
= 0;
683 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
684 unsigned char *m0_rptr
, *m0_wptr
;
685 int err
, offset
, space
;
686 struct timeval timenow
;
689 * get the user data structure pointer
691 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
694 * Guard against bogus count argument.
696 if ((unsigned) cnt
> ATP_TRESP_MAX
) {
697 dPrintf(D_M_ATP
, D_L_ERROR
,
698 ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt
));
702 if ((src_socket
= (at_socket
)atp
->atp_socket_no
) == 0xFF) {
703 /* comparison was to -1, however src_socket is a u_char */
710 rcbp
->rc_pktcnt
= cnt
;
711 rcbp
->rc_state
= RCB_SENDING
;
712 rcbp
->rc_not_sent_bitmap
= 0;
716 * special case this to
717 * improve AFP write transactions to the server
720 if ((m2
= gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,
723 gbuf_rinc(m2
,AT_WR_OFFSET
);
724 gbuf_wset(m2
,TOTAL_ATP_HDR_SIZE
);
725 *(struct ddp_atp
*)(gbuf_rptr(m2
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
726 athp
= AT_ATP_HDR(m2
);
727 ATP_CLEAR_CONTROL(athp
);
728 athp
->cmd
= ATP_CMD_TRESP
;
730 athp
->eom
= 1; /* there's only 1 fragment */
732 /* *** why only if cnt > 0? *** */
734 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
736 if (!append_copy((struct mbuf
*)m2
,
737 (struct mbuf
*)m0
, wait
)) {
742 * send the message and mark it as sent
744 AT_DDP_HDR(m2
)->src_socket
= src_socket
;
745 dPrintf(D_M_ATP_LOW
, D_L_INFO
,
746 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
747 0,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(m2
)),cnt
));
752 /* create an array of mbuf packet headers for the packets to be sent
753 * to contain the atp and ddp headers with room at the front for the
756 for (i
= 0; i
< cnt
; i
++) {
757 /* all hdrs, packet data and dst addr storage */
759 gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
, wait
)) == NULL
) {
760 for (cnt
= 0; cnt
< i
; cnt
++)
762 gbuf_freeb(rc_xmt
[cnt
]);
767 /* run through the atpBDS structs and create an mbuf for the data
768 * portion of each packet to be sent. these get chained to the mbufs
769 * containing the ATP and DDP headers. this code assumes that no ATP
770 * packet is contained in more than 2 mbufs (e.i crosses mbuf boundary
771 * no more than one time).
775 space
= gbuf_msgsize(m0
);
776 for (i
= 0; i
< cnt
; i
++) { /* for each hdr mbuf */
778 /* setup header fields */
779 gbuf_rinc(mhdr
,AT_WR_OFFSET
);
780 gbuf_wset(mhdr
,TOTAL_ATP_HDR_SIZE
);
781 *(struct ddp_atp
*)(gbuf_rptr(mhdr
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
782 athp
= AT_ATP_HDR(mhdr
);
783 ATP_CLEAR_CONTROL(athp
);
784 athp
->cmd
= ATP_CMD_TRESP
;
787 athp
->eom
= 1; /* for the last fragment */
788 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
790 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)) != 0 && m0
!= 0 && space
> 0) {
791 if ((m1
= m_copym(m0
, offset
, len
, wait
)) == 0) {
792 for (i
= 0; i
< cnt
; i
++)
794 gbuf_freem(rc_xmt
[i
]);
797 gbuf_cont(mhdr
) = m1
;
802 AT_DDP_HDR(mhdr
)->src_socket
= src_socket
;
803 dPrintf(D_M_ATP_LOW
,D_L_INFO
,
804 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
805 i
,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(mhdr
)),cnt
));
807 gbuf_next(mprev
) = mhdr
;
812 * on to the next frag
821 getmicrouptime(&timenow
);
822 if (rcbp
->rc_timestamp
== 0) {
823 if ((rcbp
->rc_timestamp
= timenow
.tv_sec
) == 0)
824 rcbp
->rc_timestamp
= 1;
825 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
832 } /* atp_unpack_bdsp */
834 #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6)
835 #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
836 static unsigned int sNext
= 0;
838 int atp_bind(gref
, sVal
, flag
)
843 extern unsigned char asp_inpC
[];
844 extern asp_scb_t
*asp_scbQ
[];
845 unsigned char inpC
, sNextUsed
= 0;
846 unsigned int sMin
, sMax
, sSav
;
847 struct atp_state
*atp
;
849 atp
= (struct atp_state
*)gref
->info
;
851 atp
= (struct atp_state
*)atp
->atp_msgq
;
853 sMax
= ATP_SOCKET_LAST
;
854 sMin
= ATP_SOCKET_FIRST
;
855 if (flag
&& (*flag
== 3)) {
864 ((sVal
> sMax
) || (sVal
< 2) || (sVal
== 6) ||
865 (ddp_socket_inuse(sVal
, DDP_ATP
) &&
866 (atp_inputQ
[sVal
] != (gref_t
*)1)))) {
873 for (sVal
=sMin
; sVal
<= sMax
; sVal
++) {
874 if (!ddp_socket_inuse(sVal
, DDP_ATP
) ||
875 atp_inputQ
[sVal
] == (gref_t
*)1)
877 else if (flag
&& (*flag
== 3) && asp_scbQ
[sVal
]) {
878 if ((asp_scbQ
[sVal
]->dflag
== *flag
)
879 && (asp_inpC
[sVal
] < inpC
) ) {
880 inpC
= asp_inpC
[sVal
];
886 if (flag
&& (*flag
== 3)) {
890 sMin
= ATP_SOCKET_FIRST
+40;
894 *flag
= (unsigned char)sSav
;
899 atp
->atp_socket_no
= (short)sVal
;
900 atp_inputQ
[sVal
] = gref
;
902 atp_pidM
[sVal
] = atp
->atp_pid
;
903 else if (*flag
== 3) {
905 if (sNext
> ATP_SOCKET_LAST
)
912 void atp_req_ind(atp
, mioc
)
913 register struct atp_state
*atp
;
914 register gbuf_t
*mioc
;
916 register struct atp_rcb
*rcbp
;
918 if ((rcbp
= atp
->atp_attached
.head
) != 0) {
919 gbuf_cont(mioc
) = rcbp
->rc_ioctl
;
920 rcbp
->rc_ioctl
= NULL
;
922 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
923 rcbp
->rc_state
= RCB_NOTIFIED
;
924 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
928 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
930 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
931 asp_ack_reply(atp
->atp_gref
, mioc
);
936 void atp_rsp_ind(trp
, mioc
)
937 register struct atp_trans
*trp
;
938 register gbuf_t
*mioc
;
940 register struct atp_state
*atp
= trp
->tr_queue
;
946 switch (trp
->tr_state
) {
948 if (asp_pack_bdsp(trp
, &xm
) < 0)
950 gbuf_cont(mioc
) = trp
->tr_xmt
;
965 dPrintf(D_M_ATP
, D_L_ERROR
,
966 ("atp_rsp_ind: TRANSACTION error\n"));
967 atp_iocnak(atp
, mioc
, err
);
969 gbuf_cont(gbuf_cont(mioc
)) = xm
;
970 atp_iocack(atp
, mioc
);
975 void atp_cancel_req(gref
, tid
)
979 struct atp_state
*atp
;
980 struct atp_trans
*trp
;
982 atp
= (struct atp_state
*)gref
->info
;
984 atp
= (struct atp_state
*)atp
->atp_msgq
;
986 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
987 if (trp
->tr_tid
== tid
)
995 * remove atp from the use list
999 struct atp_state
*atp
;
1002 if (atp
== atp_used_list
) {
1003 if ((atp_used_list
= atp
->atp_trans_waiting
) != 0)
1004 atp
->atp_trans_waiting
->atp_rcb_waiting
= 0;
1005 } else if (atp
->atp_rcb_waiting
) {
1006 if ((atp
->atp_rcb_waiting
->atp_trans_waiting
1007 = atp
->atp_trans_waiting
) != 0)
1008 atp
->atp_trans_waiting
->atp_rcb_waiting
= atp
->atp_rcb_waiting
;
1011 atp
->atp_trans_waiting
= 0;
1012 atp
->atp_rcb_waiting
= 0;
1016 atp_timout(func
, trp
, ticks
)
1018 struct atp_trans
*trp
;
1022 struct atp_trans
*curr_trp
, *prev_trp
;
1024 if (trp
->tr_tmo_func
)
1027 trp
->tr_tmo_func
= func
;
1028 trp
->tr_tmo_delta
= 1+(ticks
>>5);
1030 if (trp_tmo_list
== 0) {
1031 trp
->tr_tmo_next
= trp
->tr_tmo_prev
= 0;
1037 curr_trp
= trp_tmo_list
;
1041 sum
+= curr_trp
->tr_tmo_delta
;
1042 if (sum
> trp
->tr_tmo_delta
) {
1043 sum
-= curr_trp
->tr_tmo_delta
;
1044 trp
->tr_tmo_delta
-= sum
;
1045 curr_trp
->tr_tmo_delta
-= trp
->tr_tmo_delta
;
1048 prev_trp
= curr_trp
;
1049 if ((curr_trp
= curr_trp
->tr_tmo_next
) == 0) {
1050 trp
->tr_tmo_delta
-= sum
;
1056 trp
->tr_tmo_prev
= prev_trp
;
1057 if ((trp
->tr_tmo_next
= prev_trp
->tr_tmo_next
) != 0)
1058 prev_trp
->tr_tmo_next
->tr_tmo_prev
= trp
;
1059 prev_trp
->tr_tmo_next
= trp
;
1061 trp
->tr_tmo_prev
= 0;
1062 trp
->tr_tmo_next
= trp_tmo_list
;
1063 trp_tmo_list
->tr_tmo_prev
= trp
;
1069 atp_untimout(func
, trp
)
1071 struct atp_trans
*trp
;
1074 if (trp
->tr_tmo_func
== 0)
1077 if (trp_tmo_list
== trp
) {
1078 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0) {
1079 trp_tmo_list
->tr_tmo_prev
= 0;
1080 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1083 if ((trp
->tr_tmo_prev
->tr_tmo_next
= trp
->tr_tmo_next
) != 0) {
1084 trp
->tr_tmo_next
->tr_tmo_prev
= trp
->tr_tmo_prev
;
1085 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1088 trp
->tr_tmo_func
= 0;
1092 atp_trp_clock_locked(arg
)
1104 struct atp_trans
*trp
;
1105 void (*tr_tmo_func
)();
1108 trp_tmo_list
->tr_tmo_delta
--;
1109 while (((trp
= trp_tmo_list
) != 0) && (trp_tmo_list
->tr_tmo_delta
== 0)) {
1110 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0)
1111 trp_tmo_list
->tr_tmo_prev
= 0;
1112 if ((tr_tmo_func
= trp
->tr_tmo_func
) != 0) {
1113 trp
->tr_tmo_func
= 0;
1114 (*tr_tmo_func
)(trp
);
1118 timeout(atp_trp_clock_locked
, (void *)arg
, (1<<5));
1122 atp_send_req(gref
, mioc
)
1126 register struct atp_state
*atp
;
1127 register struct atp_trans
*trp
;
1128 register ioc_t
*iocbp
;
1129 register at_atp_t
*athp
;
1130 register at_ddp_t
*ddp
;
1131 gbuf_t
*m
, *m2
, *bds
;
1132 struct atp_set_default
*sdb
;
1137 atp
= (struct atp_state
*)((struct atp_state
*)gref
->info
)->atp_msgq
;
1138 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1140 if ((trp
= atp_trans_alloc(atp
)) == NULL
) {
1142 ((asp_scb_t
*)gref
->info
)->stat_msg
= mioc
;
1143 iocbp
->ioc_private
= (void *)gref
;
1144 timeout(atp_retry_req
, mioc
, 10);
1148 m2
= gbuf_cont(mioc
);
1149 if ((bds
= gbuf_dupb(m2
)) == NULL
) {
1150 atp_trans_free(trp
);
1153 gbuf_rinc(m2
,atpBDSsize
);
1154 gbuf_wset(bds
,atpBDSsize
);
1155 iocbp
->ioc_count
-= atpBDSsize
;
1156 gbuf_cont(m2
) = NULL
;
1158 old
= iocbp
->ioc_cmd
;
1159 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
1160 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1163 * The at_snd_req library routine multiplies seconds by 100.
1164 * We need to divide by 100 in order to obtain the timer.
1166 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1168 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1169 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1171 trp
->tr_retry
= sdb
->def_retries
;
1172 trp
->tr_timeout
= timer
;
1174 trp
->tr_tid
= atp_tid(atp
);
1178 * Now fill in the header (and remember the bits
1181 athp
= AT_ATP_HDR(m2
);
1182 athp
->cmd
= ATP_CMD_TREQ
;
1183 UAS_ASSIGN_HTON(athp
->tid
, trp
->tr_tid
);
1186 trp
->tr_xo
= athp
->xo
;
1187 trp
->tr_bitmap
= athp
->bitmap
;
1188 ddp
= AT_DDP_HDR(m2
);
1189 ddp
->type
= DDP_ATP
;
1190 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1191 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1192 trp
->tr_socket
.node
= ddp
->dst_node
;
1193 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1194 trp
->tr_local_socket
= atp
->atp_socket_no
;
1195 trp
->tr_local_node
= ddp
->src_node
;
1196 temp_net
= NET_VALUE(ddp
->src_net
);
1197 NET_ASSIGN_NOSWAP(trp
->tr_local_net
, temp_net
);
1200 /* save the local information in the gref */
1201 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1202 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1203 atp
->atp_gref
->lport
= ddp
->src_node
;
1204 atp
->atp_gref
->ddptype
= DDP_ATP
;
1208 * Put us in the transaction waiting queue
1210 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1213 * Send the message and set the timer
1215 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1216 if (!trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1217 atp_x_done(trp
); /* no reason to tie up resources */
1219 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1221 trace_mbufs(D_M_ATP_LOW
, " s", m
);
1224 } /* atp_send_req */
1226 void atp_retry_req(arg
)
1229 gbuf_t
*m
= (gbuf_t
*)arg
;
1234 gref
= (gref_t
*)((ioc_t
*)gbuf_rptr(m
))->ioc_private
;
1236 ((asp_scb_t
*)gref
->info
)->stat_msg
= 0;
1237 atp_send_req(gref
, m
);
1242 void atp_send_rsp(gref
, m
, wait
)
1247 register struct atp_state
*atp
;
1248 register struct atp_rcb
*rcbp
;
1249 register at_atp_t
*athp
;
1250 register at_ddp_t
*ddp
;
1254 atp
= (struct atp_state
*)gref
->info
;
1256 atp
= (struct atp_state
*)atp
->atp_msgq
;
1257 ddp
= AT_DDP_HDR(m
);
1258 athp
= AT_ATP_HDR(m
);
1261 * search for the corresponding rcb
1263 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1264 if ( (rcbp
->rc_tid
== UAS_VALUE_NTOH(athp
->tid
)) &&
1265 (rcbp
->rc_socket
.node
== ddp
->dst_node
) &&
1266 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
)) &&
1267 (rcbp
->rc_socket
.socket
== ddp
->dst_socket
) )
1272 * If it has already been sent then drop the request
1274 if ((rcbp
&& (rcbp
->rc_state
!= RCB_NOTIFIED
)) ||
1275 (rcbp
== NULL
&& athp
->xo
) ) {
1280 if (rcbp
== NULL
) { /* a response is being sent for an ALO transaction */
1281 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
1286 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
1287 rcbp
->rc_socket
.node
= ddp
->dst_node
;
1288 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
1289 rcbp
->rc_tid
= UAS_VALUE_NTOH(athp
->tid
);
1290 rcbp
->rc_bitmap
= 0xff;
1292 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
1293 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1295 else if (ddp
->src_node
== 0) {
1296 temp_net
= NET_VALUE_NOSWAP(rcbp
->rc_local_net
);
1297 NET_ASSIGN(ddp
->src_net
, temp_net
);
1298 ddp
->src_node
= rcbp
->rc_local_node
;
1301 xcnt
= get_bds_entries(m
);
1302 s
= atp_unpack_bdsp(atp
, m
, rcbp
, xcnt
, wait
);
1304 atp_send_replies(atp
, rcbp
);
1305 } /* atp_send_rsp */
1307 int asp_pack_bdsp(trp
, xm
)
1308 register struct atp_trans
*trp
;
1311 register struct atpBDS
*bdsp
;
1312 register gbuf_t
*m
, *m2
;
1314 gbuf_t
*m_prev
, *m_head
= 0;
1316 dPrintf(D_M_ATP
, D_L_INFO
, ("asp_pack_bdsp: socket=%d\n",
1317 trp
->tr_queue
->atp_socket_no
));
1319 if ((m2
= trp
->tr_bdsp
) == NULL
)
1321 trp
->tr_bdsp
= NULL
;
1322 bdsp
= (struct atpBDS
*)gbuf_rptr(m2
);
1324 for (i
= 0; (i
< ATP_TRESP_MAX
&&
1325 bdsp
< (struct atpBDS
*)(gbuf_wptr(m2
))); i
++) {
1326 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
1329 /* discard ddp hdr on first packet */
1330 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
1333 UAL_UAL(bdsp
->bdsUserData
, (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
1334 gbuf_rinc(m
, ATP_HDR_SIZE
);
1336 if (UAL_VALUE(bdsp
->bdsBuffAddr
)) {
1339 /* user expects data back */
1344 gbuf_cont(m_prev
) = m
;
1346 tmp
= (short)gbuf_len(m
);
1347 while (gbuf_cont(m
)) {
1349 tmp
+= (short)(gbuf_len(m
));
1353 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
1355 trp
->tr_rcv
[i
] = NULL
;
1360 * report the number of packets
1362 UAS_ASSIGN(((struct atpBDS
*)gbuf_rptr(m2
))->bdsBuffSz
, i
);
1364 if (trp
->tr_xmt
) /* an ioctl block is still held? */
1365 gbuf_cont(trp
->tr_xmt
) = m2
;
1374 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
1375 gbuf_msgsize(*xm
)));
1381 * The following routines are direct entries from system
1382 * calls to allow fast sending and recving of ATP data.
1386 _ATPsndreq(fd
, buf
, len
, nowait
, err
, proc
)
1398 register struct atp_state
*atp
;
1399 register struct atp_trans
*trp
;
1400 register ioc_t
*iocbp
;
1401 register at_atp_t
*athp
;
1402 register at_ddp_t
*ddp
;
1403 struct atp_set_default
*sdb
;
1404 gbuf_t
*m2
, *m
, *mioc
;
1405 char bds
[atpBDSsize
];
1407 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1410 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1411 || (atp
->atp_flags
& ATP_CLOSING
)) {
1412 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
1413 (u_int
) gref
, gref
->pid
));
1420 while ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_MED
)) == 0) {
1422 /* the vaue of 10n terms of hz is 100ms */
1424 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1426 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpmioc", &ts
);
1434 gbuf_wset(mioc
,sizeof(ioc_t
));
1436 while ((m2
= gbuf_alloc(len
, PRI_MED
)) == 0) {
1438 /* the vaue of 10n terms of hz is 100ms */
1440 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1442 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpm2", &ts
);
1451 gbuf_cont(mioc
) = m2
;
1452 if (((*err
= copyin(CAST_USER_ADDR_T(buf
), (caddr_t
)bds
, atpBDSsize
)) != 0)
1453 || ((*err
= copyin(CAST_USER_ADDR_T(&buf
[atpBDSsize
]),
1454 (caddr_t
)gbuf_rptr(m2
), len
)) != 0)) {
1459 gbuf_set_type(mioc
, MSG_IOCTL
);
1460 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1461 iocbp
->ioc_count
= len
;
1462 iocbp
->ioc_cmd
= nowait
? AT_ATP_ISSUE_REQUEST_NOTE
: AT_ATP_ISSUE_REQUEST
;
1463 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1466 * The at_snd_req library routine multiplies seconds by 100.
1467 * We need to divide by 100 in order to obtain the timer.
1469 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1471 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1472 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1475 * allocate and set up the transaction record
1477 while ((trp
= atp_trans_alloc(atp
)) == 0) {
1479 /* the vaue of 10n terms of hz is 100ms */
1481 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1483 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atptrp", &ts
);
1491 trp
->tr_retry
= sdb
->def_retries
;
1492 trp
->tr_timeout
= timer
;
1493 trp
->tr_bdsp
= NULL
;
1494 trp
->tr_tid
= atp_tid(atp
);
1498 * remember the IOCTL packet so we can ack it
1504 * Now fill in the header (and remember the bits
1507 athp
= AT_ATP_HDR(m2
);
1508 athp
->cmd
= ATP_CMD_TREQ
;
1509 UAS_ASSIGN_HTON(athp
->tid
, trp
->tr_tid
);
1512 trp
->tr_xo
= athp
->xo
;
1513 trp
->tr_bitmap
= athp
->bitmap
;
1514 ddp
= AT_DDP_HDR(m2
);
1515 ddp
->type
= DDP_ATP
;
1516 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1518 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1519 trp
->tr_socket
.node
= ddp
->dst_node
;
1520 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1521 trp
->tr_local_socket
= atp
->atp_socket_no
;
1524 /* save the local information in the gref */
1525 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1526 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1527 atp
->atp_gref
->lport
= ddp
->src_node
;
1528 atp
->atp_gref
->ddptype
= DDP_ATP
;
1532 * Put us in the transaction waiting queue
1534 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1537 * Send the message and set the timer
1539 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1540 if ( !trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1541 atp_x_done(trp
); /* no reason to tie up resources */
1543 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1553 * wait for the transaction to complete
1555 while ((trp
->tr_state
!= TRANS_DONE
) && (trp
->tr_state
!= TRANS_FAILED
) &&
1556 (trp
->tr_state
!= TRANS_ABORTING
)) {
1557 trp
->tr_rsp_wait
= 1;
1558 rc
= msleep(&trp
->tr_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpsndreq", 0);
1560 trp
->tr_rsp_wait
= 0;
1566 trp
->tr_rsp_wait
= 0;
1569 if (trp
->tr_state
== TRANS_FAILED
|| trp
->tr_state
== TRANS_ABORTING
) {
1571 * transaction timed out, return error
1580 * copy out the recv data
1582 if ((*err
= atp_pack_bdsp(trp
, (struct atpBDS
*)bds
)) != 0) {
1589 * copyout the result info
1591 if ((*err
= copyout((caddr_t
)bds
, CAST_USER_ADDR_T(buf
), atpBDSsize
)) != 0) {
1604 /* entry point for ATP send response. respbuf contains a DDP hdr,
1605 * ATP hdr, and atpBDS array. The bdsDataSz field of the first atpBDS
1606 * struct contains the number of atpBDS structs in the array. resplen
1607 * contains the len of the data in respbuf and datalen contains the
1608 * len of the data buffer holding the response packets which the atpBDS
1609 * struct entries point to.
1612 _ATPsndrsp(fd
, respbuff
, resplen
, datalen
, err
, proc
)
1614 unsigned char *respbuff
;
1626 struct atp_state
*atp
;
1627 struct atpBDS
*bdsp
;
1630 int bds_cnt
, count
, len
;
1633 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1636 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1637 || (atp
->atp_flags
& ATP_CLOSING
)) {
1638 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
1639 (u_int
) gref
, gref
->pid
));
1647 * allocate buffer and copy in the response info
1649 if ((m
= gbuf_alloc_wait(resplen
, TRUE
)) == 0) {
1654 if ((*err
= copyin(CAST_USER_ADDR_T(respbuff
), (caddr_t
)gbuf_rptr(m
), resplen
)) != 0) {
1659 gbuf_wset(m
,resplen
);
1660 ((at_ddp_t
*)gbuf_rptr(m
))->src_node
= 0;
1661 bdsp
= (struct atpBDS
*)(gbuf_rptr(m
) + TOTAL_ATP_HDR_SIZE
);
1664 * allocate buffers and copy in the response data.
1665 * note that only the size field of the atpBDS field
1666 * is used internally in the kernel.
1668 bds_cnt
= get_bds_entries(m
); /* count of # entries */
1669 /* check correctness of parameters */
1670 if (bds_cnt
> ATP_TRESP_MAX
) {
1677 for (size
= 0, count
= 0; count
< bds_cnt
; count
++) {
1678 size
+= UAS_VALUE(bdsp
[count
].bdsBuffSz
);
1680 if (size
> datalen
) {
1687 /* get the first mbuf */
1688 if ((mdata
= gbuf_alloc_wait((space
= (size
> MCLBYTES
? MCLBYTES
: size
)), TRUE
)) == 0) {
1694 gbuf_cont(m
) = mdata
;
1695 dataptr
= mtod(mdata
, caddr_t
);
1696 for (count
= 0; count
< bds_cnt
; bdsp
++, count
++) {
1697 if ((bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
)) != 0 &&
1698 (len
= UAS_VALUE(bdsp
->bdsBuffSz
)) != 0) {
1699 if (len
> space
) { /* enough room ? */
1700 gbuf_wset(mdata
, dataptr
- mtod(mdata
, caddr_t
)); /* set len of last mbuf */
1701 /* allocate the next mbuf */
1702 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
1708 mdata
= gbuf_cont(mdata
);
1709 MCLGET(mdata
, M_WAIT
);
1710 if (!(mdata
->m_flags
& M_EXT
)) {
1715 dataptr
= mtod(mdata
, caddr_t
);
1719 if ((*err
= copyin(CAST_USER_ADDR_T(bufaddr
), dataptr
, len
)) != 0) {
1728 gbuf_wset(mdata
, dataptr
- mtod(mdata
, caddr_t
)); /* set len of last mbuf */
1729 gbuf_cont(m
)->m_pkthdr
.len
= size
; /* set packet hdr len */
1731 atp_send_rsp(gref
, m
, TRUE
);
1737 _ATPgetreq(fd
, buf
, buflen
, err
, proc
)
1745 register struct atp_state
*atp
;
1746 register struct atp_rcb
*rcbp
;
1747 register gbuf_t
*m
, *m_head
;
1750 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1753 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1754 || (atp
->atp_flags
& ATP_CLOSING
)) {
1755 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
1756 (u_int
) gref
, gref
->pid
));
1762 if ((rcbp
= atp
->atp_attached
.head
) != NULL
) {
1764 * Got one, move it to the active response Q
1766 m_head
= rcbp
->rc_ioctl
;
1767 rcbp
->rc_ioctl
= NULL
;
1770 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
1771 rcbp
->rc_state
= RCB_NOTIFIED
;
1772 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1774 /* detach rcbp from attached queue,
1775 * and free any outstanding resources
1781 * copyout the request data, including the protocol header
1783 for (size
=0, m
=m_head
; m
; m
= gbuf_cont(m
)) {
1784 if ((len
= gbuf_len(m
)) > buflen
)
1786 copyout((caddr_t
)gbuf_rptr(m
), CAST_USER_ADDR_T(&buf
[size
]), len
);
1788 if ((buflen
-= len
) == 0)
1802 _ATPgetrsp(fd
, bdsp
, err
, proc
)
1804 struct atpBDS
*bdsp
;
1809 register struct atp_state
*atp
;
1810 register struct atp_trans
*trp
;
1812 char bds
[atpBDSsize
];
1814 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1817 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1818 || (atp
->atp_flags
& ATP_CLOSING
)) {
1819 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
1820 (u_int
) gref
, gref
->pid
));
1826 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1827 dPrintf(D_M_ATP
, D_L_INFO
,
1828 ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
1829 (u_int
) atp
, (u_int
) trp
, trp
->tr_state
));
1831 switch (trp
->tr_state
) {
1833 if ((*err
= copyin(CAST_USER_ADDR_T(bdsp
),
1834 (caddr_t
)bds
, sizeof(bds
))) != 0) {
1839 if ((*err
= atp_pack_bdsp(trp
, (struct atpBDS
*)bds
)) != 0) {
1844 tid
= (int)trp
->tr_tid
;
1846 if ((*err
= copyout((caddr_t
)bds
, CAST_USER_ADDR_T(bdsp
), sizeof(bds
))) != 0) {
1855 * transaction timed out, return error
1873 atp_drop_req(gref
, m
)
1877 struct atp_state
*atp
;
1878 struct atp_rcb
*rcbp
;
1882 atp
= (struct atp_state
*)gref
->info
;
1884 atp
= (struct atp_state
*)atp
->atp_msgq
;
1885 ddp
= AT_DDP_HDR(m
);
1886 athp
= AT_ATP_HDR(m
);
1889 * search for the corresponding rcb
1891 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1892 if ( (rcbp
->rc_tid
== UAS_VALUE_NTOH(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
) )