2 * Copyright (c) 1996-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_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 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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 /* Modified for MP, 1996 by Tuyen Nguyen
30 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
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>
41 #include <sys/filedesc.h>
42 #include <sys/fcntl.h>
43 #include <kern/locks.h>
45 #include <sys/ioctl.h>
46 #include <sys/malloc.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
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>
64 int asp_pack_bdsp(struct atp_trans
*, gbuf_t
**);
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
*,
69 void atp_trp_clock(void *arg
), atp_trp_clock_locked(void *arg
);
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
;
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
;
83 static struct atp_trans
*trp_tmo_list
;
84 struct atp_trans
*trp_tmo_rcb
;
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)
91 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
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
);
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
);
110 /* allocated in asp_scb_alloc(), which is called
112 if (scb_resource_m
) {
113 gbuf_freem(scb_resource_m
);
117 /* allocated in atp_trans_alloc() */
118 if (atp_resource_m
) {
119 gbuf_freem(atp_resource_m
);
121 atp_trans_free_list
= 0;
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
133 register gref_t
*gref
;
136 register ioc_t
*iocbp
;
138 struct atp_state
*atp
;
139 struct atp_trans
*trp
;
140 struct atp_rcb
*rcbp
;
143 atp
= (struct atp_state
*)gref
->info
;
145 atp
= (struct atp_state
*)atp
->atp_msgq
;
147 switch(gbuf_type(m
)) {
151 dPrintf(D_M_ATP
, D_L_WARNING
,
152 ("atp_wput: atp_msgq discarded\n"));
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.
164 iocbp
= (ioc_t
*)gbuf_rptr(m
);
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
);
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
);
177 *(at_socket
*)gbuf_rptr(gbuf_cont(m
)) = skt
;
180 atp_dequeue_atp(atp
);
184 case AT_ATP_GET_CHANID
:
185 if (gbuf_cont(m
) == NULL
) {
186 iocbp
->ioc_rval
= -1;
187 atp_iocnak(atp
, m
, EINVAL
);
190 *(gref_t
**)gbuf_rptr(gbuf_cont(m
)) = gref
;
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
;
201 if ((tmp
= gbuf_cont(m
)) != 0) {
202 if ((bds
= gbuf_dupb(tmp
)) == NULL
) {
203 atp_iocnak(atp
, m
, ENOBUFS
);
206 gbuf_rinc(tmp
,atpBDSsize
);
207 gbuf_wset(bds
,atpBDSsize
);
208 iocbp
->ioc_count
-= atpBDSsize
;
209 gbuf_cont(tmp
) = bds
;
213 * send a response to a transaction
216 if (iocbp
->ioc_count
< TOTAL_ATP_HDR_SIZE
) {
217 atp_iocnak(atp
, m
, EINVAL
);
222 * remove the response from the message
226 iocbp
->ioc_count
= 0;
227 ddp
= AT_DDP_HDR(m2
);
228 athp
= AT_ATP_HDR(m2
);
230 gbuf_cont(m2
) = atp
->atp_msgq
;
235 * search for the corresponding rcb
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
)
246 * If it has already been sent then return an error
248 if ((rcbp
&& rcbp
->rc_state
!= RCB_NOTIFIED
) ||
249 (rcbp
== NULL
&& athp
->xo
)) {
250 atp_iocnak(atp
, m
, ENOENT
);
254 if (rcbp
== NULL
) { /* a response for an ALO transaction */
255 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
256 atp_iocnak(atp
, m
, ENOBUFS
);
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;
267 rcbp
->rc_state
= RCB_SENDING
;
268 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
270 xcnt
= get_bds_entries(m2
);
271 if ((i
= atp_unpack_bdsp(atp
, m2
, rcbp
, xcnt
, FALSE
))) {
274 atp_iocnak(atp
, m
, i
);
277 atp_send_replies(atp
, rcbp
);
280 * send the ack back to the responder
286 case AT_ATP_GET_POLL
: {
288 gbuf_freem(gbuf_cont(m
));
290 iocbp
->ioc_count
= 0;
294 * search for a waiting request
296 if ((rcbp
= atp
->atp_attached
.head
)) {
298 * Got one, move it to the active response Q
300 gbuf_cont(m
) = rcbp
->rc_ioctl
;
301 rcbp
->rc_ioctl
= NULL
;
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
);
307 /* detach rcbp from attached queue,
308 * and free any outstanding resources
315 * None available - can out
317 atp_iocnak(atp
, m
, EAGAIN
);
322 case AT_ATP_CANCEL_REQUEST
: {
324 * Cancel a pending request
326 if (iocbp
->ioc_count
!= sizeof(int)) {
327 atp_iocnak(atp
, m
, EINVAL
);
330 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
331 gbuf_freem(gbuf_cont(m
));
333 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
334 if (trp
->tr_tid
== i
)
338 atp_iocnak(atp
, m
, ENOENT
);
348 if (atalk_peek(gref
, &event
) == -1)
349 atp_iocnak(atp
, m
, EAGAIN
);
351 *gbuf_rptr(gbuf_cont(m
)) = event
;
357 case DDP_IOC_GET_CFG
:
358 #ifdef APPLETALK_DEBUG
359 kprintf("atp_wput: DDP_IOC_GET_CFG\n");
361 if (gbuf_cont(m
) == 0) {
362 atp_iocnak(atp
, m
, EINVAL
);
366 /* *** was ddp_get_cfg() *** */
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
;
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
;
380 gbuf_wset(gbuf_cont(m
), sizeof(ddp_addr_t
));
386 * Otherwise pass it on, if possible
388 iocbp
->ioc_private
= (void *)gref
;
400 gbuf_t
*atp_build_release(trp
)
401 register struct atp_trans
*trp
;
404 register at_ddp_t
*ddp
;
405 register at_atp_t
*athp
;
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
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
);
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
);
425 * clear the cmd/xo/eom/sts/unused fields
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
);
436 void atp_send_replies(atp
, rcbp
)
437 register struct atp_state
*atp
;
438 register struct atp_rcb
*rcbp
;
439 { register gbuf_t
*m
;
441 int cnt
, offset
, space
;
442 register at_atp_t
*athp
;
443 register struct atpBDS
*bdsp
;
444 register gbuf_t
*m1
, *m0
, *mhdr
;
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
];
452 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
454 struct timeval timenow
;
456 if (rcbp
->rc_queue
!= atp
)
458 if (rcbp
->rc_not_sent_bitmap
== 0)
459 goto nothing_to_send
;
461 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
, ("atp_send_replies\n"));
463 * Do this for each message that hasn't been sent
465 cnt
= rcbp
->rc_pktcnt
;
466 for (i
= 0; i
< cnt
; i
++) {
468 if (rcbp
->rc_snd
[i
]) {
470 gbuf_alloc(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,PRI_MED
))
472 for (cnt
= 0; cnt
< i
; cnt
++)
474 gbuf_freeb(rc_xmt
[cnt
]);
475 goto nothing_to_send
;
482 if (gbuf_len(m
) > TOTAL_ATP_HDR_SIZE
)
483 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
488 space
= gbuf_msgsize(m0
);
491 for (i
= 0; i
< cnt
; i
++) {
492 if (rcbp
->rc_snd
[i
] == 0) {
493 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
))) {
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
;
508 athp
->eom
= 1; /* for the last fragment */
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
++)
515 gbuf_freem(rc_xmt
[i
]);
516 goto nothing_to_send
;
520 gbuf_cont(mhdr
) = m1
;
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
))));
530 gbuf_next(mprev
) = mhdr
;
536 rcbp
->rc_not_sent_bitmap
&= ~atp_mask
[i
];
537 if (rcbp
->rc_not_sent_bitmap
== 0)
541 * on to the next frag
551 * If all replies from this reply block have been sent then
552 * remove it from the queue and mark it so
554 if (rcbp
->rc_queue
!= atp
)
556 rcbp
->rc_rep_waiting
= 0;
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.
565 * We have sent all of a response so free the
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
);
576 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
579 } /* atp_send_replies */
583 atp_pack_bdsp(trp
, bdsp
)
584 register struct atp_trans
*trp
;
585 register struct atpBDS
*bdsp
;
587 register gbuf_t
*m
= NULL
;
588 register int i
, datsize
= 0;
589 struct atpBDS
*bdsbase
= bdsp
;
592 dPrintf(D_M_ATP
, D_L_INFO
, ("atp_pack_bdsp: socket=%d\n",
593 trp
->tr_queue
->atp_socket_no
));
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
);
599 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
602 /* discard ddp hdr on first packet */
604 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
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
);
612 if ((bufsize
!= 0) && (bufaddr
!= 0)) {
613 /* user expects data back */
615 register char *buf
= (char *)bufaddr
;
618 unsigned short len
= (unsigned short)(gbuf_len(m
));
622 if ((error
= copyout((caddr_t
)gbuf_rptr(m
),
623 CAST_USER_ADDR_T(&buf
[tmp
]),
633 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
636 gbuf_freem(trp
->tr_rcv
[i
]);
637 trp
->tr_rcv
[i
] = NULL
;
640 /* report the number of packets */
641 UAS_ASSIGN(((struct atpBDS
*)bdsbase
)->bdsBuffSz
, i
);
643 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
647 } /* atp_pack_bdsp */
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
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
;
662 register struct atpBDS
*bdsp
;
663 register gbuf_t
*m2
, *m1
, *m0
, *mhdr
;
666 at_socket src_socket
;
669 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
671 gbuf_t
*mprev
= 0, *mlist
= 0;
672 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
673 int offset
, space
= 0;
674 struct timeval timenow
;
677 * get the user data structure pointer
679 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
682 * Guard against bogus count argument.
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
));
690 if ((src_socket
= (at_socket
)atp
->atp_socket_no
) == 0xFF) {
691 /* comparison was to -1, however src_socket is a u_char */
698 rcbp
->rc_pktcnt
= cnt
;
699 rcbp
->rc_state
= RCB_SENDING
;
700 rcbp
->rc_not_sent_bitmap
= 0;
704 * special case this to
705 * improve AFP write transactions to the server
708 if ((m2
= gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,
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
;
718 athp
->eom
= 1; /* there's only 1 fragment */
720 /* *** why only if cnt > 0? *** */
722 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
724 if (!append_copy((struct mbuf
*)m2
,
725 (struct mbuf
*)m0
, wait
)) {
730 * send the message and mark it as sent
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
));
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
744 for (i
= 0; i
< cnt
; i
++) {
745 /* all hdrs, packet data and dst addr storage */
747 gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
, wait
)) == NULL
) {
748 for (cnt
= 0; cnt
< i
; cnt
++)
750 gbuf_freeb(rc_xmt
[cnt
]);
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).
763 space
= gbuf_msgsize(m0
);
764 for (i
= 0; i
< cnt
; i
++) { /* for each hdr mbuf */
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
;
775 athp
->eom
= 1; /* for the last fragment */
776 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
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
++)
782 gbuf_freem(rc_xmt
[i
]);
785 gbuf_cont(mhdr
) = m1
;
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
));
795 gbuf_next(mprev
) = mhdr
;
800 * on to the next frag
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
);
820 } /* atp_unpack_bdsp */
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
[];
828 int atp_bind(gref
, sVal
, flag
)
833 unsigned char inpC
, sNextUsed
= 0;
834 unsigned int sMin
, sMax
, sSav
= 0;
835 struct atp_state
*atp
;
837 atp
= (struct atp_state
*)gref
->info
;
839 atp
= (struct atp_state
*)atp
->atp_msgq
;
841 sMax
= ATP_SOCKET_LAST
;
842 sMin
= ATP_SOCKET_FIRST
;
843 if (flag
&& (*flag
== 3)) {
852 ((sVal
> sMax
) || (sVal
< 2) || (sVal
== 6) ||
853 (ddp_socket_inuse(sVal
, DDP_ATP
) &&
854 (atp_inputQ
[sVal
] != (gref_t
*)1)))) {
861 for (sVal
=sMin
; sVal
<= sMax
; sVal
++) {
862 if (!ddp_socket_inuse(sVal
, DDP_ATP
) ||
863 atp_inputQ
[sVal
] == (gref_t
*)1)
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
];
874 if (flag
&& (*flag
== 3)) {
878 sMin
= ATP_SOCKET_FIRST
+40;
882 *flag
= (unsigned char)sSav
;
887 atp
->atp_socket_no
= (short)sVal
;
888 atp_inputQ
[sVal
] = gref
;
890 atp_pidM
[sVal
] = atp
->atp_pid
;
891 else if (*flag
== 3) {
893 if (sNext
> ATP_SOCKET_LAST
)
900 void atp_req_ind(atp
, mioc
)
901 register struct atp_state
*atp
;
902 register gbuf_t
*mioc
;
904 register struct atp_rcb
*rcbp
;
906 if ((rcbp
= atp
->atp_attached
.head
) != 0) {
907 gbuf_cont(mioc
) = rcbp
->rc_ioctl
;
908 rcbp
->rc_ioctl
= NULL
;
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
);
916 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
918 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
919 asp_ack_reply(atp
->atp_gref
, mioc
);
924 void atp_rsp_ind(trp
, mioc
)
925 register struct atp_trans
*trp
;
926 register gbuf_t
*mioc
;
928 register struct atp_state
*atp
= trp
->tr_queue
;
934 switch (trp
->tr_state
) {
936 if (asp_pack_bdsp(trp
, &xm
) < 0)
938 gbuf_cont(mioc
) = trp
->tr_xmt
;
953 dPrintf(D_M_ATP
, D_L_ERROR
,
954 ("atp_rsp_ind: TRANSACTION error\n"));
955 atp_iocnak(atp
, mioc
, err
);
957 gbuf_cont(gbuf_cont(mioc
)) = xm
;
958 atp_iocack(atp
, mioc
);
963 void atp_cancel_req(gref
, tid
)
967 struct atp_state
*atp
;
968 struct atp_trans
*trp
;
970 atp
= (struct atp_state
*)gref
->info
;
972 atp
= (struct atp_state
*)atp
->atp_msgq
;
974 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
975 if (trp
->tr_tid
== tid
)
983 * remove atp from the use list
987 struct atp_state
*atp
;
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
;
999 atp
->atp_trans_waiting
= 0;
1000 atp
->atp_rcb_waiting
= 0;
1004 atp_timout(func
, trp
, ticks
)
1006 struct atp_trans
*trp
;
1010 struct atp_trans
*curr_trp
, *prev_trp
;
1012 if (trp
->tr_tmo_func
)
1015 trp
->tr_tmo_func
= func
;
1016 trp
->tr_tmo_delta
= 1+(ticks
>>5);
1018 if (trp_tmo_list
== 0) {
1019 trp
->tr_tmo_next
= trp
->tr_tmo_prev
= 0;
1025 curr_trp
= trp_tmo_list
;
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
;
1036 prev_trp
= curr_trp
;
1037 if ((curr_trp
= curr_trp
->tr_tmo_next
) == 0) {
1038 trp
->tr_tmo_delta
-= sum
;
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
;
1049 trp
->tr_tmo_prev
= 0;
1050 trp
->tr_tmo_next
= trp_tmo_list
;
1051 trp_tmo_list
->tr_tmo_prev
= trp
;
1058 __unused atp_tmo_func func
,
1059 struct atp_trans
*trp
)
1062 if (trp
->tr_tmo_func
== 0)
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
;
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
;
1076 trp
->tr_tmo_func
= 0;
1080 atp_trp_clock_locked(arg
)
1092 struct atp_trans
*trp
;
1093 atp_tmo_func tr_tmo_func
;
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
);
1106 timeout(atp_trp_clock_locked
, (void *)arg
, (1<<5));
1110 atp_send_req(gref
, mioc
)
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
;
1125 atp
= (struct atp_state
*)((struct atp_state
*)gref
->info
)->atp_msgq
;
1126 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1128 if ((trp
= atp_trans_alloc(atp
)) == NULL
) {
1130 ((asp_scb_t
*)gref
->info
)->stat_msg
= mioc
;
1131 iocbp
->ioc_private
= (void *)gref
;
1132 timeout(atp_retry_req
, mioc
, 10);
1136 m2
= gbuf_cont(mioc
);
1137 if ((bds
= gbuf_dupb(m2
)) == NULL
) {
1138 atp_trans_free(trp
);
1141 gbuf_rinc(m2
,atpBDSsize
);
1142 gbuf_wset(bds
,atpBDSsize
);
1143 iocbp
->ioc_count
-= atpBDSsize
;
1144 gbuf_cont(m2
) = NULL
;
1146 old
= iocbp
->ioc_cmd
;
1147 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
1148 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1151 * The at_snd_req library routine multiplies seconds by 100.
1152 * We need to divide by 100 in order to obtain the timer.
1154 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1156 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1157 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1159 trp
->tr_retry
= sdb
->def_retries
;
1160 trp
->tr_timeout
= timer
;
1162 trp
->tr_tid
= atp_tid(atp
);
1166 * Now fill in the header (and remember the bits
1169 athp
= AT_ATP_HDR(m2
);
1170 athp
->cmd
= ATP_CMD_TREQ
;
1171 UAS_ASSIGN_HTON(athp
->tid
, trp
->tr_tid
);
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
);
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
;
1196 * Put us in the transaction waiting queue
1198 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1201 * Send the message and set the timer
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 */
1207 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1209 trace_mbufs(D_M_ATP_LOW
, " s", m
);
1212 } /* atp_send_req */
1214 void atp_retry_req(arg
)
1217 gbuf_t
*m
= (gbuf_t
*)arg
;
1222 gref
= (gref_t
*)((ioc_t
*)gbuf_rptr(m
))->ioc_private
;
1224 ((asp_scb_t
*)gref
->info
)->stat_msg
= 0;
1225 atp_send_req(gref
, m
);
1230 void atp_send_rsp(gref
, m
, wait
)
1235 register struct atp_state
*atp
;
1236 register struct atp_rcb
*rcbp
;
1237 register at_atp_t
*athp
;
1238 register at_ddp_t
*ddp
;
1242 atp
= (struct atp_state
*)gref
->info
;
1244 atp
= (struct atp_state
*)atp
->atp_msgq
;
1245 ddp
= AT_DDP_HDR(m
);
1246 athp
= AT_ATP_HDR(m
);
1249 * search for the corresponding rcb
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
) )
1260 * If it has already been sent then drop the request
1262 if ((rcbp
&& (rcbp
->rc_state
!= RCB_NOTIFIED
)) ||
1263 (rcbp
== NULL
&& athp
->xo
) ) {
1268 if (rcbp
== NULL
) { /* a response is being sent for an ALO transaction */
1269 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
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;
1280 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
1281 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
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
;
1289 xcnt
= get_bds_entries(m
);
1290 s
= atp_unpack_bdsp(atp
, m
, rcbp
, xcnt
, wait
);
1292 atp_send_replies(atp
, rcbp
);
1293 } /* atp_send_rsp */
1295 int asp_pack_bdsp(trp
, xm
)
1296 register struct atp_trans
*trp
;
1299 register struct atpBDS
*bdsp
;
1300 register gbuf_t
*m
, *m2
;
1302 gbuf_t
*m_prev
= 0, *m_head
= 0;
1304 dPrintf(D_M_ATP
, D_L_INFO
, ("asp_pack_bdsp: socket=%d\n",
1305 trp
->tr_queue
->atp_socket_no
));
1307 if ((m2
= trp
->tr_bdsp
) == NULL
)
1309 trp
->tr_bdsp
= NULL
;
1310 bdsp
= (struct atpBDS
*)gbuf_rptr(m2
);
1312 for (i
= 0; (i
< ATP_TRESP_MAX
&&
1313 bdsp
< (struct atpBDS
*)(gbuf_wptr(m2
))); i
++) {
1314 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
1317 /* discard ddp hdr on first packet */
1318 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
1321 UAL_UAL(bdsp
->bdsUserData
, (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
1322 gbuf_rinc(m
, ATP_HDR_SIZE
);
1324 if (UAL_VALUE(bdsp
->bdsBuffAddr
)) {
1327 /* user expects data back */
1332 gbuf_cont(m_prev
) = m
;
1334 tmp
= (short)gbuf_len(m
);
1335 while (gbuf_cont(m
)) {
1337 tmp
+= (short)(gbuf_len(m
));
1341 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
1343 trp
->tr_rcv
[i
] = NULL
;
1348 * report the number of packets
1350 UAS_ASSIGN(((struct atpBDS
*)gbuf_rptr(m2
))->bdsBuffSz
, i
);
1352 if (trp
->tr_xmt
) /* an ioctl block is still held? */
1353 gbuf_cont(trp
->tr_xmt
) = m2
;
1362 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
1363 gbuf_msgsize(*xm
)));
1369 * The following routines are direct entries from system
1370 * calls to allow fast sending and recving of ATP data.
1374 _ATPsndreq(fd
, buf
, len
, nowait
, err
, proc
)
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
];
1395 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
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
));
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
+
1415 while ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_MED
)) == 0) {
1417 /* the vaue of 10n terms of hz is 100ms */
1419 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1421 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpmioc", &ts
);
1429 gbuf_wset(mioc
,sizeof(ioc_t
));
1431 while ((m2
= gbuf_alloc(len
, PRI_MED
)) == 0) {
1433 /* the vaue of 10n terms of hz is 100ms */
1435 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1437 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpm2", &ts
);
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)) {
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
);
1461 * The at_snd_req library routine multiplies seconds by 100.
1462 * We need to divide by 100 in order to obtain the timer.
1464 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1466 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1467 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1470 * allocate and set up the transaction record
1472 while ((trp
= atp_trans_alloc(atp
)) == 0) {
1474 /* the vaue of 10n terms of hz is 100ms */
1476 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1478 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atptrp", &ts
);
1486 trp
->tr_retry
= sdb
->def_retries
;
1487 trp
->tr_timeout
= timer
;
1488 trp
->tr_bdsp
= NULL
;
1489 trp
->tr_tid
= atp_tid(atp
);
1493 * remember the IOCTL packet so we can ack it
1499 * Now fill in the header (and remember the bits
1502 athp
= AT_ATP_HDR(m2
);
1503 athp
->cmd
= ATP_CMD_TREQ
;
1504 UAS_ASSIGN_HTON(athp
->tid
, trp
->tr_tid
);
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
;
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
;
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
;
1527 * Put us in the transaction waiting queue
1529 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1532 * Send the message and set the timer
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 */
1538 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1548 * wait for the transaction to complete
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);
1555 trp
->tr_rsp_wait
= 0;
1561 trp
->tr_rsp_wait
= 0;
1564 if (trp
->tr_state
== TRANS_FAILED
|| trp
->tr_state
== TRANS_ABORTING
) {
1566 * transaction timed out, return error
1575 * copy out the recv data
1577 if ((*err
= atp_pack_bdsp(trp
, (struct atpBDS
*)bds
)) != 0) {
1584 * copyout the result info
1586 if ((*err
= copyout((caddr_t
)bds
, CAST_USER_ADDR_T(buf
), atpBDSsize
)) != 0) {
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.
1607 _ATPsndrsp(fd
, respbuff
, resplen
, datalen
, err
, proc
)
1609 unsigned char *respbuff
;
1620 struct atp_state
*atp
;
1621 struct atpBDS
*bdsp
;
1622 int bds_cnt
, count
, len
;
1625 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
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
));
1639 * allocate buffer and copy in the response info
1641 if (resplen
< 0 || resplen
> TOTAL_ATP_HDR_SIZE
+ sizeof(struct atpBDS
)*ATP_TRESP_MAX
) {
1646 if ((m
= gbuf_alloc_wait(resplen
, TRUE
)) == 0) {
1651 if ((*err
= copyin(CAST_USER_ADDR_T(respbuff
), (caddr_t
)gbuf_rptr(m
), resplen
)) != 0) {
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
);
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.
1665 bds_cnt
= get_bds_entries(m
); /* count of # entries */
1666 /* check correctness of parameters */
1667 if (bds_cnt
> ATP_TRESP_MAX
) {
1674 for (size
= 0, count
= 0; count
< bds_cnt
; count
++) {
1675 if (UAS_VALUE(bdsp
[count
].bdsBuffSz
) > ATP_DATA_SIZE
) {
1681 size
+= UAS_VALUE(bdsp
[count
].bdsBuffSz
);
1683 if (size
> datalen
) {
1690 /* get the first mbuf */
1691 if ((mdata
= gbuf_alloc_wait((space
= (size
> MCLBYTES
? MCLBYTES
: size
)), TRUE
)) == 0) {
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) {
1711 mdata
= gbuf_cont(mdata
);
1712 MCLGET(mdata
, M_WAIT
);
1713 if (!(mdata
->m_flags
& M_EXT
)) {
1718 dataptr
= mtod(mdata
, caddr_t
);
1722 if ((*err
= copyin(CAST_USER_ADDR_T(bufaddr
), dataptr
, len
)) != 0) {
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 */
1734 atp_send_rsp(gref
, m
, TRUE
);
1740 _ATPgetreq(fd
, buf
, buflen
, err
, proc
)
1748 register struct atp_state
*atp
;
1749 register struct atp_rcb
*rcbp
;
1750 register gbuf_t
*m
, *m_head
;
1753 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
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
));
1765 if (buflen
< DDP_X_HDR_SIZE
+ ATP_HDR_SIZE
) {
1771 if ((rcbp
= atp
->atp_attached
.head
) != NULL
) {
1773 * Got one, move it to the active response Q
1775 m_head
= rcbp
->rc_ioctl
;
1776 rcbp
->rc_ioctl
= NULL
;
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
);
1783 /* detach rcbp from attached queue,
1784 * and free any outstanding resources
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
), CAST_USER_ADDR_T(&buf
[size
]), len
);
1797 if ((buflen
-= len
) == 0)
1811 _ATPgetrsp(fd
, bdsp
, err
, proc
)
1813 struct atpBDS
*bdsp
;
1818 register struct atp_state
*atp
;
1819 register struct atp_trans
*trp
;
1821 char bds
[atpBDSsize
];
1823 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
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
));
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
));
1840 switch (trp
->tr_state
) {
1842 if ((*err
= copyin(CAST_USER_ADDR_T(bdsp
),
1843 (caddr_t
)bds
, sizeof(bds
))) != 0) {
1848 if ((*err
= atp_pack_bdsp(trp
, (struct atpBDS
*)bds
)) != 0) {
1853 tid
= (int)trp
->tr_tid
;
1855 if ((*err
= copyout((caddr_t
)bds
, CAST_USER_ADDR_T(bdsp
), sizeof(bds
))) != 0) {
1864 * transaction timed out, return error
1882 atp_drop_req(gref
, m
)
1886 struct atp_state
*atp
;
1887 struct atp_rcb
*rcbp
;
1891 atp
= (struct atp_state
*)gref
->info
;
1893 atp
= (struct atp_state
*)atp
->atp_msgq
;
1894 ddp
= AT_DDP_HDR(m
);
1895 athp
= AT_ATP_HDR(m
);
1898 * search for the corresponding rcb
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
) )