2 * Copyright (c) 2006 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
;
85 extern atlock_t atpgen_lock
;
86 extern atlock_t atpall_lock
;
87 extern atlock_t atptmo_lock
;
89 extern gbuf_t
*scb_resource_m
;
90 extern gbuf_t
*atp_resource_m
;
91 extern gref_t
*atp_inputQ
[];
92 extern int atp_pidM
[];
93 extern at_ifaddr_t
*ifID_home
;
94 extern lck_mtx_t
* atalk_mutex
;
96 static struct atp_trans
*trp_tmo_list
;
97 struct atp_trans
*trp_tmo_rcb
;
99 /* first bds entry gives number of bds entries in total (hack) */
100 #define get_bds_entries(m) \
101 ((gbuf_len(m) > TOTAL_ATP_HDR_SIZE)? \
102 (UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz)): 0)
104 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
109 trp_tmo_rcb
= atp_trans_alloc(0);
110 atp_timout(atp_rcb_timer
, trp_tmo_rcb
, 10 * HZ
);
111 atp_trp_clock((void *)&atp_inited
);
112 asp_clock((void *)&atp_inited
);
117 untimeout(asp_clock_locked
, (void *)&atp_inited
);
118 untimeout(atp_trp_clock_locked
, (void *)&atp_inited
);
119 atp_untimout(atp_rcb_timer
, trp_tmo_rcb
);
123 /* allocated in asp_scb_alloc(), which is called
125 if (scb_resource_m
) {
126 gbuf_freem(scb_resource_m
);
130 /* allocated in atp_trans_alloc() */
131 if (atp_resource_m
) {
132 gbuf_freem(atp_resource_m
);
134 atp_trans_free_list
= 0;
140 * write queue put routine .... filter out other than IOCTLs
141 * Version 1.8 of atp_write.c on 89/02/09 17:53:26
146 register gref_t
*gref
;
149 register ioc_t
*iocbp
;
151 struct atp_state
*atp
;
152 struct atp_trans
*trp
;
153 struct atp_rcb
*rcbp
;
156 atp
= (struct atp_state
*)gref
->info
;
158 atp
= (struct atp_state
*)atp
->atp_msgq
;
160 switch(gbuf_type(m
)) {
164 dPrintf(D_M_ATP
, D_L_WARNING
,
165 ("atp_wput: atp_msgq discarded\n"));
171 /* Need to ensure that all copyin/copyout calls are made at
172 * put routine time which should be in the user context. (true when
173 * we are the stream head). The service routine can be called on an
174 * unpredictable context and copyin/copyout calls will get wrong results
175 * or even panic the kernel.
177 iocbp
= (ioc_t
*)gbuf_rptr(m
);
179 switch (iocbp
->ioc_cmd
) {
180 case AT_ATP_BIND_REQ
:
181 if (gbuf_cont(m
) == NULL
) {
182 iocbp
->ioc_rval
= -1;
183 atp_iocnak(atp
, m
, EINVAL
);
186 skt
= *(at_socket
*)gbuf_rptr(gbuf_cont(m
));
187 if ((skt
= (at_socket
)atp_bind(gref
, (unsigned int)skt
, 0)) == 0)
188 atp_iocnak(atp
, m
, EINVAL
);
190 *(at_socket
*)gbuf_rptr(gbuf_cont(m
)) = skt
;
193 atp_dequeue_atp(atp
);
197 case AT_ATP_GET_CHANID
:
198 if (gbuf_cont(m
) == NULL
) {
199 iocbp
->ioc_rval
= -1;
200 atp_iocnak(atp
, m
, EINVAL
);
203 *(gref_t
**)gbuf_rptr(gbuf_cont(m
)) = gref
;
207 /* not the close and not the tickle(?) */
208 case AT_ATP_ISSUE_REQUEST_DEF
:
209 case AT_ATP_ISSUE_REQUEST_DEF_NOTE
: {
210 gbuf_t
*bds
, *tmp
, *m2
;
211 struct atp_rcb
*rcbp
;
215 if ((tmp
= gbuf_cont(m
)) != 0) {
216 if ((bds
= gbuf_dupb(tmp
)) == NULL
) {
217 atp_iocnak(atp
, m
, ENOBUFS
);
220 gbuf_rinc(tmp
,atpBDSsize
);
221 gbuf_wset(bds
,atpBDSsize
);
222 iocbp
->ioc_count
-= atpBDSsize
;
223 gbuf_cont(tmp
) = bds
;
227 * send a response to a transaction
230 if (iocbp
->ioc_count
< TOTAL_ATP_HDR_SIZE
) {
231 atp_iocnak(atp
, m
, EINVAL
);
236 * remove the response from the message
240 iocbp
->ioc_count
= 0;
241 ddp
= AT_DDP_HDR(m2
);
242 athp
= AT_ATP_HDR(m2
);
244 gbuf_cont(m2
) = atp
->atp_msgq
;
248 ATDISABLE(s
, atp
->atp_lock
);
250 * search for the corresponding rcb
252 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
253 if (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
) &&
254 rcbp
->rc_socket
.node
== ddp
->dst_node
&&
255 rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
) &&
256 rcbp
->rc_socket
.socket
== ddp
->dst_socket
)
259 ATENABLE(s
, atp
->atp_lock
);
262 * If it has already been sent then return an error
264 if ((rcbp
&& rcbp
->rc_state
!= RCB_NOTIFIED
) ||
265 (rcbp
== NULL
&& athp
->xo
)) {
266 atp_iocnak(atp
, m
, ENOENT
);
270 if (rcbp
== NULL
) { /* a response for an ALO transaction */
271 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
272 atp_iocnak(atp
, m
, ENOBUFS
);
277 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
278 rcbp
->rc_socket
.node
= ddp
->dst_node
;
279 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
280 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
281 rcbp
->rc_bitmap
= 0xff;
283 ATDISABLE(s
, atp
->atp_lock
);
284 rcbp
->rc_state
= RCB_SENDING
;
285 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
286 ATENABLE(s
, atp
->atp_lock
);
288 xcnt
= get_bds_entries(m2
);
289 if ((i
= atp_unpack_bdsp(atp
, m2
, rcbp
, xcnt
, FALSE
))) {
292 atp_iocnak(atp
, m
, i
);
295 atp_send_replies(atp
, rcbp
);
298 * send the ack back to the responder
304 case AT_ATP_GET_POLL
: {
306 gbuf_freem(gbuf_cont(m
));
308 iocbp
->ioc_count
= 0;
312 * search for a waiting request
314 ATDISABLE(s
, atp
->atp_lock
);
315 if ((rcbp
= atp
->atp_attached
.head
)) {
317 * Got one, move it to the active response Q
319 gbuf_cont(m
) = rcbp
->rc_ioctl
;
320 rcbp
->rc_ioctl
= NULL
;
322 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
323 rcbp
->rc_state
= RCB_NOTIFIED
;
324 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
326 /* detach rcbp from attached queue,
327 * and free any outstanding resources
331 ATENABLE(s
, atp
->atp_lock
);
335 * None available - can out
337 ATENABLE(s
, atp
->atp_lock
);
338 atp_iocnak(atp
, m
, EAGAIN
);
343 case AT_ATP_CANCEL_REQUEST
: {
345 * Cancel a pending request
347 if (iocbp
->ioc_count
!= sizeof(int)) {
348 atp_iocnak(atp
, m
, EINVAL
);
351 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
352 gbuf_freem(gbuf_cont(m
));
354 ATDISABLE(s
, atp
->atp_lock
);
355 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
356 if (trp
->tr_tid
== i
)
360 ATENABLE(s
, atp
->atp_lock
);
361 atp_iocnak(atp
, m
, ENOENT
);
363 ATENABLE(s
, atp
->atp_lock
);
372 if (atalk_peek(gref
, &event
) == -1)
373 atp_iocnak(atp
, m
, EAGAIN
);
375 *gbuf_rptr(gbuf_cont(m
)) = event
;
381 case DDP_IOC_GET_CFG
:
382 #ifdef APPLETALK_DEBUG
383 kprintf("atp_wput: DDP_IOC_GET_CFG\n");
385 if (gbuf_cont(m
) == 0) {
386 atp_iocnak(atp
, m
, EINVAL
);
390 /* *** was ddp_get_cfg() *** */
392 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(m
));
393 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
394 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
395 cfgp
->inet
.socket
= atp
->atp_socket_no
;
396 cfgp
->ddptype
= DDP_ATP
;
398 cfgp
->inet
.net
= atp
->atp_gref
->laddr
.s_net
;
399 cfgp
->inet
.node
= atp
->atp_gref
->laddr
.s_node
;
400 cfgp
->inet
.socket
= atp
->atp_gref
->lport
;
401 cfgp
->ddptype
= atp
->atp_gref
->ddptype
;
404 gbuf_wset(gbuf_cont(m
), sizeof(ddp_addr_t
));
410 * Otherwise pass it on, if possible
412 iocbp
->ioc_private
= (void *)gref
;
424 gbuf_t
*atp_build_release(trp
)
425 register struct atp_trans
*trp
;
428 register at_ddp_t
*ddp
;
429 register at_atp_t
*athp
;
432 * Now try and allocate enough space to send the message
433 * if none is available the caller will schedule
434 * a timeout so we can retry for more space soon
436 if ((m
= (gbuf_t
*)gbuf_alloc(AT_WR_OFFSET
+ATP_HDR_SIZE
, PRI_HI
)) != NULL
) {
437 gbuf_rinc(m
,AT_WR_OFFSET
);
438 gbuf_wset(m
,TOTAL_ATP_HDR_SIZE
);
441 UAS_ASSIGN(ddp
->checksum
, 0);
442 ddp
->dst_socket
= trp
->tr_socket
.socket
;
443 ddp
->dst_node
= trp
->tr_socket
.node
;
444 NET_ASSIGN(ddp
->dst_net
, trp
->tr_socket
.net
);
445 ddp
->src_node
= trp
->tr_local_node
;
446 NET_NET(ddp
->src_net
, trp
->tr_local_net
);
449 * clear the cmd/xo/eom/sts/unused fields
451 athp
= AT_ATP_HDR(m
);
452 ATP_CLEAR_CONTROL(athp
);
453 athp
->cmd
= ATP_CMD_TREL
;
454 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
460 void atp_send_replies(atp
, rcbp
)
461 register struct atp_state
*atp
;
462 register struct atp_rcb
*rcbp
;
463 { register gbuf_t
*m
;
465 int s_gen
, s
, cnt
, err
, offset
, space
;
466 unsigned char *m0_rptr
= NULL
, *m0_wptr
= NULL
;
467 register at_atp_t
*athp
;
468 register struct atpBDS
*bdsp
;
469 register gbuf_t
*m2
, *m1
, *m0
, *mhdr
;
471 gbuf_t
*mprev
, *mlist
= 0;
472 at_socket src_socket
= (at_socket
)atp
->atp_socket_no
;
473 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
475 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
477 struct timeval timenow
;
479 ATDISABLE(s
, atp
->atp_lock
);
480 if (rcbp
->rc_queue
!= atp
) {
481 ATENABLE(s
, atp
->atp_lock
);
484 if (rcbp
->rc_not_sent_bitmap
== 0)
485 goto nothing_to_send
;
487 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
, ("atp_send_replies\n"));
489 * Do this for each message that hasn't been sent
491 cnt
= rcbp
->rc_pktcnt
;
492 for (i
= 0; i
< cnt
; i
++) {
494 if (rcbp
->rc_snd
[i
]) {
496 gbuf_alloc(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,PRI_MED
))
498 for (cnt
= 0; cnt
< i
; cnt
++)
500 gbuf_freeb(rc_xmt
[cnt
]);
501 goto nothing_to_send
;
508 if (gbuf_len(m
) > TOTAL_ATP_HDR_SIZE
)
509 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
514 space
= gbuf_msgsize(m0
);
517 for (i
= 0; i
< cnt
; i
++) {
518 if (rcbp
->rc_snd
[i
] == 0) {
519 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
))) {
525 /* setup header fields */
526 gbuf_rinc(mhdr
,AT_WR_OFFSET
);
527 gbuf_wset(mhdr
,TOTAL_ATP_HDR_SIZE
);
528 *(struct ddp_atp
*)(gbuf_rptr(mhdr
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
529 athp
= AT_ATP_HDR(mhdr
);
530 ATP_CLEAR_CONTROL(athp
);
531 athp
->cmd
= ATP_CMD_TRESP
;
534 athp
->eom
= 1; /* for the last fragment */
536 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
537 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)) && m0
!= 0 && space
> 0) {
538 if ((m1
= m_copym(m0
, offset
, len
, M_DONTWAIT
)) == 0) {
539 for (i
= 0; i
< cnt
; i
++)
541 gbuf_freem(rc_xmt
[i
]);
542 goto nothing_to_send
;
546 gbuf_cont(mhdr
) = m1
;
550 AT_DDP_HDR(mhdr
)->src_socket
= src_socket
;
551 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
,
552 ("atp_send_replies: %d, socket=%d, size=%d\n",
553 i
, atp
->atp_socket_no
, gbuf_msgsize(gbuf_cont(m2
))));
556 gbuf_next(mprev
) = mhdr
;
562 rcbp
->rc_not_sent_bitmap
&= ~atp_mask
[i
];
563 if (rcbp
->rc_not_sent_bitmap
== 0)
567 * on to the next frag
572 ATENABLE(s
, atp
->atp_lock
);
574 ATDISABLE(s
, atp
->atp_lock
);
579 * If all replies from this reply block have been sent then
580 * remove it from the queue and mark it so
582 if (rcbp
->rc_queue
!= atp
) {
583 ATENABLE(s
, atp
->atp_lock
);
586 rcbp
->rc_rep_waiting
= 0;
589 * If we are doing execute once re-set the rcb timeout
590 * each time we send back any part of the response. Note
591 * that this timer is started when an initial request is
592 * received. Each response reprimes the timer. Duplicate
593 * requests do not reprime the timer.
595 * We have sent all of a response so free the
598 if (rcbp
->rc_xo
&& rcbp
->rc_state
!= RCB_RELEASED
) {
599 getmicrouptime(&timenow
);
600 ATDISABLE(s_gen
, atpgen_lock
);
601 if (rcbp
->rc_timestamp
== 0) {
602 rcbp
->rc_timestamp
= timenow
.tv_sec
;
603 if (rcbp
->rc_timestamp
== 0)
604 rcbp
->rc_timestamp
= 1;
605 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
607 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
608 ATENABLE(s_gen
, atpgen_lock
);
611 ATENABLE(s
, atp
->atp_lock
);
612 } /* atp_send_replies */
616 atp_pack_bdsp(trp
, bdsp
)
617 register struct atp_trans
*trp
;
618 register struct atpBDS
*bdsp
;
620 register gbuf_t
*m
= NULL
;
621 register int i
, datsize
= 0;
622 struct atpBDS
*bdsbase
= bdsp
;
625 dPrintf(D_M_ATP
, D_L_INFO
, ("atp_pack_bdsp: socket=%d\n",
626 trp
->tr_queue
->atp_socket_no
));
628 for (i
= 0; i
< ATP_TRESP_MAX
; i
++, bdsp
++) {
629 unsigned short bufsize
= UAS_VALUE(bdsp
->bdsBuffSz
);
630 long bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
);
632 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
635 /* discard ddp hdr on first packet */
637 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
639 /* this field may contain control information even when
640 no data is present */
641 UAL_UAL(bdsp
->bdsUserData
,
642 (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
643 gbuf_rinc(m
, ATP_HDR_SIZE
);
645 if ((bufsize
!= 0) && (bufaddr
!= 0)) {
646 /* user expects data back */
648 register char *buf
= (char *)bufaddr
;
651 unsigned short len
= (unsigned short)(gbuf_len(m
));
655 if ((error
= copyout((caddr_t
)gbuf_rptr(m
),
656 CAST_USER_ADDR_T(&buf
[tmp
]),
666 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
669 gbuf_freem(trp
->tr_rcv
[i
]);
670 trp
->tr_rcv
[i
] = NULL
;
673 /* report the number of packets */
674 UAS_ASSIGN(((struct atpBDS
*)bdsbase
)->bdsBuffSz
, i
);
676 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
680 } /* atp_pack_bdsp */
683 /* create an mbuf chain with mbuf packet headers for each ATP response packet
684 * to be sent. m contains the DDP hdr, ATP hdr, and and array of atpBDS structs.
685 * chained to m is an mbuf that contians the actual data pointed to by the atpBDS
689 atp_unpack_bdsp(atp
, m
, rcbp
, cnt
, wait
)
690 struct atp_state
*atp
;
691 gbuf_t
*m
; /* ddp, atp and bdsp gbuf_t */
692 register struct atp_rcb
*rcbp
;
693 register int cnt
, wait
;
695 register struct atpBDS
*bdsp
;
696 register gbuf_t
*m2
, *m1
, *m0
, *mhdr
;
700 at_socket src_socket
;
703 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
705 gbuf_t
*mprev
, *mlist
= 0;
706 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
707 unsigned char *m0_rptr
, *m0_wptr
;
708 int err
, offset
, space
;
709 struct timeval timenow
;
712 * get the user data structure pointer
714 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
717 * Guard against bogus count argument.
719 if ((unsigned) cnt
> ATP_TRESP_MAX
) {
720 dPrintf(D_M_ATP
, D_L_ERROR
,
721 ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt
));
725 if ((src_socket
= (at_socket
)atp
->atp_socket_no
) == 0xFF) {
726 /* comparison was to -1, however src_socket is a u_char */
733 rcbp
->rc_pktcnt
= cnt
;
734 rcbp
->rc_state
= RCB_SENDING
;
735 rcbp
->rc_not_sent_bitmap
= 0;
739 * special case this to
740 * improve AFP write transactions to the server
743 if ((m2
= gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,
746 gbuf_rinc(m2
,AT_WR_OFFSET
);
747 gbuf_wset(m2
,TOTAL_ATP_HDR_SIZE
);
748 *(struct ddp_atp
*)(gbuf_rptr(m2
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
749 athp
= AT_ATP_HDR(m2
);
750 ATP_CLEAR_CONTROL(athp
);
751 athp
->cmd
= ATP_CMD_TRESP
;
753 athp
->eom
= 1; /* there's only 1 fragment */
755 /* *** why only if cnt > 0? *** */
757 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
759 if (!append_copy((struct mbuf
*)m2
,
760 (struct mbuf
*)m0
, wait
)) {
765 * send the message and mark it as sent
767 AT_DDP_HDR(m2
)->src_socket
= src_socket
;
768 dPrintf(D_M_ATP_LOW
, D_L_INFO
,
769 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
770 0,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(m2
)),cnt
));
775 /* create an array of mbuf packet headers for the packets to be sent
776 * to contain the atp and ddp headers with room at the front for the
779 for (i
= 0; i
< cnt
; i
++) {
780 /* all hdrs, packet data and dst addr storage */
782 gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
, wait
)) == NULL
) {
783 for (cnt
= 0; cnt
< i
; cnt
++)
785 gbuf_freeb(rc_xmt
[cnt
]);
790 /* run through the atpBDS structs and create an mbuf for the data
791 * portion of each packet to be sent. these get chained to the mbufs
792 * containing the ATP and DDP headers. this code assumes that no ATP
793 * packet is contained in more than 2 mbufs (e.i crosses mbuf boundary
794 * no more than one time).
798 space
= gbuf_msgsize(m0
);
799 for (i
= 0; i
< cnt
; i
++) { /* for each hdr mbuf */
801 /* setup header fields */
802 gbuf_rinc(mhdr
,AT_WR_OFFSET
);
803 gbuf_wset(mhdr
,TOTAL_ATP_HDR_SIZE
);
804 *(struct ddp_atp
*)(gbuf_rptr(mhdr
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
805 athp
= AT_ATP_HDR(mhdr
);
806 ATP_CLEAR_CONTROL(athp
);
807 athp
->cmd
= ATP_CMD_TRESP
;
810 athp
->eom
= 1; /* for the last fragment */
811 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
813 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)) != 0 && m0
!= 0 && space
> 0) {
814 if ((m1
= m_copym(m0
, offset
, len
, wait
)) == 0) {
815 for (i
= 0; i
< cnt
; i
++)
817 gbuf_freem(rc_xmt
[i
]);
820 gbuf_cont(mhdr
) = m1
;
825 AT_DDP_HDR(mhdr
)->src_socket
= src_socket
;
826 dPrintf(D_M_ATP_LOW
,D_L_INFO
,
827 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
828 i
,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(mhdr
)),cnt
));
830 gbuf_next(mprev
) = mhdr
;
835 * on to the next frag
844 getmicrouptime(&timenow
);
845 ATDISABLE(s_gen
, atpgen_lock
);
846 if (rcbp
->rc_timestamp
== 0) {
847 if ((rcbp
->rc_timestamp
= timenow
.tv_sec
) == 0)
848 rcbp
->rc_timestamp
= 1;
849 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
851 ATENABLE(s_gen
, atpgen_lock
);
857 } /* atp_unpack_bdsp */
859 #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6)
860 #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
861 static unsigned int sNext
= 0;
863 int atp_bind(gref
, sVal
, flag
)
868 extern unsigned char asp_inpC
[];
869 extern asp_scb_t
*asp_scbQ
[];
870 unsigned char inpC
, sNextUsed
= 0;
871 unsigned int sMin
, sMax
, sSav
;
872 struct atp_state
*atp
;
875 atp
= (struct atp_state
*)gref
->info
;
877 atp
= (struct atp_state
*)atp
->atp_msgq
;
879 sMax
= ATP_SOCKET_LAST
;
880 sMin
= ATP_SOCKET_FIRST
;
881 ATDISABLE(s
, atpgen_lock
);
882 if (flag
&& (*flag
== 3)) {
891 ((sVal
> sMax
) || (sVal
< 2) || (sVal
== 6) ||
892 (ddp_socket_inuse(sVal
, DDP_ATP
) &&
893 (atp_inputQ
[sVal
] != (gref_t
*)1)))) {
894 ATENABLE(s
, atpgen_lock
);
901 for (sVal
=sMin
; sVal
<= sMax
; sVal
++) {
902 if (!ddp_socket_inuse(sVal
, DDP_ATP
) ||
903 atp_inputQ
[sVal
] == (gref_t
*)1)
905 else if (flag
&& (*flag
== 3) && asp_scbQ
[sVal
]) {
906 if ((asp_scbQ
[sVal
]->dflag
== *flag
)
907 && (asp_inpC
[sVal
] < inpC
) ) {
908 inpC
= asp_inpC
[sVal
];
914 if (flag
&& (*flag
== 3)) {
918 sMin
= ATP_SOCKET_FIRST
+40;
922 *flag
= (unsigned char)sSav
;
924 ATENABLE(s
, atpgen_lock
);
928 atp
->atp_socket_no
= (short)sVal
;
929 atp_inputQ
[sVal
] = gref
;
931 atp_pidM
[sVal
] = atp
->atp_pid
;
932 else if (*flag
== 3) {
934 if (sNext
> ATP_SOCKET_LAST
)
938 ATENABLE(s
, atpgen_lock
);
942 void atp_req_ind(atp
, mioc
)
943 register struct atp_state
*atp
;
944 register gbuf_t
*mioc
;
946 register struct atp_rcb
*rcbp
;
949 if ((rcbp
= atp
->atp_attached
.head
) != 0) {
950 gbuf_cont(mioc
) = rcbp
->rc_ioctl
;
951 rcbp
->rc_ioctl
= NULL
;
952 ATDISABLE(s
, atp
->atp_lock
);
954 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
955 rcbp
->rc_state
= RCB_NOTIFIED
;
956 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
959 ATENABLE(s
, atp
->atp_lock
);
961 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
963 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
964 asp_ack_reply(atp
->atp_gref
, mioc
);
969 void atp_rsp_ind(trp
, mioc
)
970 register struct atp_trans
*trp
;
971 register gbuf_t
*mioc
;
973 register struct atp_state
*atp
= trp
->tr_queue
;
979 switch (trp
->tr_state
) {
981 if (asp_pack_bdsp(trp
, &xm
) < 0)
983 gbuf_cont(mioc
) = trp
->tr_xmt
;
998 dPrintf(D_M_ATP
, D_L_ERROR
,
999 ("atp_rsp_ind: TRANSACTION error\n"));
1000 atp_iocnak(atp
, mioc
, err
);
1002 gbuf_cont(gbuf_cont(mioc
)) = xm
;
1003 atp_iocack(atp
, mioc
);
1008 void atp_cancel_req(gref
, tid
)
1013 struct atp_state
*atp
;
1014 struct atp_trans
*trp
;
1016 atp
= (struct atp_state
*)gref
->info
;
1018 atp
= (struct atp_state
*)atp
->atp_msgq
;
1020 ATDISABLE(s
, atp
->atp_lock
);
1021 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1022 if (trp
->tr_tid
== tid
)
1025 ATENABLE(s
, atp
->atp_lock
);
1031 * remove atp from the use list
1034 atp_dequeue_atp(atp
)
1035 struct atp_state
*atp
;
1039 ATDISABLE(s
, atpall_lock
);
1040 if (atp
== atp_used_list
) {
1041 if ((atp_used_list
= atp
->atp_trans_waiting
) != 0)
1042 atp
->atp_trans_waiting
->atp_rcb_waiting
= 0;
1043 } else if (atp
->atp_rcb_waiting
) {
1044 if ((atp
->atp_rcb_waiting
->atp_trans_waiting
1045 = atp
->atp_trans_waiting
) != 0)
1046 atp
->atp_trans_waiting
->atp_rcb_waiting
= atp
->atp_rcb_waiting
;
1049 atp
->atp_trans_waiting
= 0;
1050 atp
->atp_rcb_waiting
= 0;
1051 ATENABLE(s
, atpall_lock
);
1055 atp_timout(func
, trp
, ticks
)
1057 struct atp_trans
*trp
;
1062 struct atp_trans
*curr_trp
, *prev_trp
;
1064 ATDISABLE(s
, atptmo_lock
);
1065 if (trp
->tr_tmo_func
) {
1066 ATENABLE(s
, atptmo_lock
);
1070 trp
->tr_tmo_func
= func
;
1071 trp
->tr_tmo_delta
= 1+(ticks
>>5);
1073 if (trp_tmo_list
== 0) {
1074 trp
->tr_tmo_next
= trp
->tr_tmo_prev
= 0;
1076 ATENABLE(s
, atptmo_lock
);
1081 curr_trp
= trp_tmo_list
;
1085 sum
+= curr_trp
->tr_tmo_delta
;
1086 if (sum
> trp
->tr_tmo_delta
) {
1087 sum
-= curr_trp
->tr_tmo_delta
;
1088 trp
->tr_tmo_delta
-= sum
;
1089 curr_trp
->tr_tmo_delta
-= trp
->tr_tmo_delta
;
1092 prev_trp
= curr_trp
;
1093 if ((curr_trp
= curr_trp
->tr_tmo_next
) == 0) {
1094 trp
->tr_tmo_delta
-= sum
;
1100 trp
->tr_tmo_prev
= prev_trp
;
1101 if ((trp
->tr_tmo_next
= prev_trp
->tr_tmo_next
) != 0)
1102 prev_trp
->tr_tmo_next
->tr_tmo_prev
= trp
;
1103 prev_trp
->tr_tmo_next
= trp
;
1105 trp
->tr_tmo_prev
= 0;
1106 trp
->tr_tmo_next
= trp_tmo_list
;
1107 trp_tmo_list
->tr_tmo_prev
= trp
;
1110 ATENABLE(s
, atptmo_lock
);
1114 atp_untimout(func
, trp
)
1116 struct atp_trans
*trp
;
1120 ATDISABLE(s
, atptmo_lock
);
1121 if (trp
->tr_tmo_func
== 0) {
1122 ATENABLE(s
, atptmo_lock
);
1126 if (trp_tmo_list
== trp
) {
1127 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0) {
1128 trp_tmo_list
->tr_tmo_prev
= 0;
1129 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1132 if ((trp
->tr_tmo_prev
->tr_tmo_next
= trp
->tr_tmo_next
) != 0) {
1133 trp
->tr_tmo_next
->tr_tmo_prev
= trp
->tr_tmo_prev
;
1134 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1137 trp
->tr_tmo_func
= 0;
1138 ATENABLE(s
, atptmo_lock
);
1142 atp_trp_clock_locked(arg
)
1155 struct atp_trans
*trp
;
1156 void (*tr_tmo_func
)();
1158 ATDISABLE(s
, atptmo_lock
);
1160 trp_tmo_list
->tr_tmo_delta
--;
1161 while (((trp
= trp_tmo_list
) != 0) && (trp_tmo_list
->tr_tmo_delta
== 0)) {
1162 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0)
1163 trp_tmo_list
->tr_tmo_prev
= 0;
1164 if ((tr_tmo_func
= trp
->tr_tmo_func
) != 0) {
1165 trp
->tr_tmo_func
= 0;
1166 ATENABLE(s
, atptmo_lock
);
1167 (*tr_tmo_func
)(trp
);
1168 ATDISABLE(s
, atptmo_lock
);
1171 ATENABLE(s
, atptmo_lock
);
1173 timeout(atp_trp_clock_locked
, (void *)arg
, (1<<5));
1177 atp_send_req(gref
, mioc
)
1181 register struct atp_state
*atp
;
1182 register struct atp_trans
*trp
;
1183 register ioc_t
*iocbp
;
1184 register at_atp_t
*athp
;
1185 register at_ddp_t
*ddp
;
1186 gbuf_t
*m
, *m2
, *bds
;
1187 struct atp_set_default
*sdb
;
1191 atp
= (struct atp_state
*)((struct atp_state
*)gref
->info
)->atp_msgq
;
1192 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1194 if ((trp
= atp_trans_alloc(atp
)) == NULL
) {
1196 ((asp_scb_t
*)gref
->info
)->stat_msg
= mioc
;
1197 iocbp
->ioc_private
= (void *)gref
;
1198 timeout(atp_retry_req
, mioc
, 10);
1202 m2
= gbuf_cont(mioc
);
1203 if ((bds
= gbuf_dupb(m2
)) == NULL
) {
1204 atp_trans_free(trp
);
1207 gbuf_rinc(m2
,atpBDSsize
);
1208 gbuf_wset(bds
,atpBDSsize
);
1209 iocbp
->ioc_count
-= atpBDSsize
;
1210 gbuf_cont(m2
) = NULL
;
1212 old
= iocbp
->ioc_cmd
;
1213 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
1214 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1217 * The at_snd_req library routine multiplies seconds by 100.
1218 * We need to divide by 100 in order to obtain the timer.
1220 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1222 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1223 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1225 trp
->tr_retry
= sdb
->def_retries
;
1226 trp
->tr_timeout
= timer
;
1228 trp
->tr_tid
= atp_tid(atp
);
1232 * Now fill in the header (and remember the bits
1235 athp
= AT_ATP_HDR(m2
);
1236 athp
->cmd
= ATP_CMD_TREQ
;
1237 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1240 trp
->tr_xo
= athp
->xo
;
1241 trp
->tr_bitmap
= athp
->bitmap
;
1242 ddp
= AT_DDP_HDR(m2
);
1243 ddp
->type
= DDP_ATP
;
1244 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1245 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1246 trp
->tr_socket
.node
= ddp
->dst_node
;
1247 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1248 trp
->tr_local_socket
= atp
->atp_socket_no
;
1249 trp
->tr_local_node
= ddp
->src_node
;
1250 NET_NET(trp
->tr_local_net
, ddp
->src_net
);
1253 /* save the local information in the gref */
1254 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1255 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1256 atp
->atp_gref
->lport
= ddp
->src_node
;
1257 atp
->atp_gref
->ddptype
= DDP_ATP
;
1261 * Put us in the transaction waiting queue
1263 ATDISABLE(s
, atp
->atp_lock
);
1264 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1265 ATENABLE(s
, atp
->atp_lock
);
1268 * Send the message and set the timer
1270 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1271 if (!trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1272 atp_x_done(trp
); /* no reason to tie up resources */
1274 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1276 trace_mbufs(D_M_ATP_LOW
, " s", m
);
1279 } /* atp_send_req */
1281 void atp_retry_req(arg
)
1284 gbuf_t
*m
= (gbuf_t
*)arg
;
1289 gref
= (gref_t
*)((ioc_t
*)gbuf_rptr(m
))->ioc_private
;
1291 ((asp_scb_t
*)gref
->info
)->stat_msg
= 0;
1292 atp_send_req(gref
, m
);
1297 void atp_send_rsp(gref
, m
, wait
)
1302 register struct atp_state
*atp
;
1303 register struct atp_rcb
*rcbp
;
1304 register at_atp_t
*athp
;
1305 register at_ddp_t
*ddp
;
1308 atp
= (struct atp_state
*)gref
->info
;
1310 atp
= (struct atp_state
*)atp
->atp_msgq
;
1311 ddp
= AT_DDP_HDR(m
);
1312 athp
= AT_ATP_HDR(m
);
1315 * search for the corresponding rcb
1317 ATDISABLE(s
, atp
->atp_lock
);
1318 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1319 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1320 (rcbp
->rc_socket
.node
== ddp
->dst_node
) &&
1321 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
)) &&
1322 (rcbp
->rc_socket
.socket
== ddp
->dst_socket
) )
1327 * If it has already been sent then drop the request
1329 if ((rcbp
&& (rcbp
->rc_state
!= RCB_NOTIFIED
)) ||
1330 (rcbp
== NULL
&& athp
->xo
) ) {
1331 ATENABLE(s
, atp
->atp_lock
);
1335 ATENABLE(s
, atp
->atp_lock
);
1337 if (rcbp
== NULL
) { /* a response is being sent for an ALO transaction */
1338 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
1343 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
1344 rcbp
->rc_socket
.node
= ddp
->dst_node
;
1345 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
1346 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
1347 rcbp
->rc_bitmap
= 0xff;
1349 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
1350 ATDISABLE(s
, atp
->atp_lock
);
1351 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1352 ATENABLE(s
, atp
->atp_lock
);
1354 else if (ddp
->src_node
== 0) {
1355 NET_NET(ddp
->src_net
, rcbp
->rc_local_net
);
1356 ddp
->src_node
= rcbp
->rc_local_node
;
1359 xcnt
= get_bds_entries(m
);
1360 s
= atp_unpack_bdsp(atp
, m
, rcbp
, xcnt
, wait
);
1362 atp_send_replies(atp
, rcbp
);
1363 } /* atp_send_rsp */
1365 int asp_pack_bdsp(trp
, xm
)
1366 register struct atp_trans
*trp
;
1369 register struct atpBDS
*bdsp
;
1370 register gbuf_t
*m
, *m2
;
1372 gbuf_t
*m_prev
, *m_head
= 0;
1374 dPrintf(D_M_ATP
, D_L_INFO
, ("asp_pack_bdsp: socket=%d\n",
1375 trp
->tr_queue
->atp_socket_no
));
1377 if ((m2
= trp
->tr_bdsp
) == NULL
)
1379 trp
->tr_bdsp
= NULL
;
1380 bdsp
= (struct atpBDS
*)gbuf_rptr(m2
);
1382 for (i
= 0; (i
< ATP_TRESP_MAX
&&
1383 bdsp
< (struct atpBDS
*)(gbuf_wptr(m2
))); i
++) {
1384 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
1387 /* discard ddp hdr on first packet */
1388 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
1391 UAL_UAL(bdsp
->bdsUserData
, (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
1392 gbuf_rinc(m
, ATP_HDR_SIZE
);
1394 if (UAL_VALUE(bdsp
->bdsBuffAddr
)) {
1397 /* user expects data back */
1402 gbuf_cont(m_prev
) = m
;
1404 tmp
= (short)gbuf_len(m
);
1405 while (gbuf_cont(m
)) {
1407 tmp
+= (short)(gbuf_len(m
));
1411 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
1413 trp
->tr_rcv
[i
] = NULL
;
1418 * report the number of packets
1420 UAS_ASSIGN(((struct atpBDS
*)gbuf_rptr(m2
))->bdsBuffSz
, i
);
1422 if (trp
->tr_xmt
) /* an ioctl block is still held? */
1423 gbuf_cont(trp
->tr_xmt
) = m2
;
1432 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
1433 gbuf_msgsize(*xm
)));
1439 * The following routines are direct entries from system
1440 * calls to allow fast sending and recving of ATP data.
1444 _ATPsndreq(fd
, buf
, len
, nowait
, err
, proc
)
1456 register struct atp_state
*atp
;
1457 register struct atp_trans
*trp
;
1458 register ioc_t
*iocbp
;
1459 register at_atp_t
*athp
;
1460 register at_ddp_t
*ddp
;
1461 struct atp_set_default
*sdb
;
1462 gbuf_t
*m2
, *m
, *mioc
;
1463 char bds
[atpBDSsize
];
1465 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1468 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1469 || (atp
->atp_flags
& ATP_CLOSING
)) {
1470 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
1471 (u_int
) gref
, gref
->pid
));
1478 while ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_MED
)) == 0) {
1480 /* the vaue of 10n terms of hz is 100ms */
1482 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1484 ATDISABLE(s
, atp
->atp_delay_lock
);
1485 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpmioc", &ts
);
1486 ATENABLE(s
, atp
->atp_delay_lock
);
1494 gbuf_wset(mioc
,sizeof(ioc_t
));
1496 while ((m2
= gbuf_alloc(len
, PRI_MED
)) == 0) {
1498 /* the vaue of 10n terms of hz is 100ms */
1500 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1502 ATDISABLE(s
, atp
->atp_delay_lock
);
1503 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpm2", &ts
);
1504 ATENABLE(s
, atp
->atp_delay_lock
);
1513 gbuf_cont(mioc
) = m2
;
1514 if (((*err
= copyin(CAST_USER_ADDR_T(buf
), (caddr_t
)bds
, atpBDSsize
)) != 0)
1515 || ((*err
= copyin(CAST_USER_ADDR_T(&buf
[atpBDSsize
]),
1516 (caddr_t
)gbuf_rptr(m2
), len
)) != 0)) {
1521 gbuf_set_type(mioc
, MSG_IOCTL
);
1522 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1523 iocbp
->ioc_count
= len
;
1524 iocbp
->ioc_cmd
= nowait
? AT_ATP_ISSUE_REQUEST_NOTE
: AT_ATP_ISSUE_REQUEST
;
1525 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1528 * The at_snd_req library routine multiplies seconds by 100.
1529 * We need to divide by 100 in order to obtain the timer.
1531 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1533 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1534 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1537 * allocate and set up the transaction record
1539 while ((trp
= atp_trans_alloc(atp
)) == 0) {
1541 /* the vaue of 10n terms of hz is 100ms */
1543 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1545 ATDISABLE(s
, atp
->atp_delay_lock
);
1546 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atptrp", &ts
);
1547 ATENABLE(s
, atp
->atp_delay_lock
);
1555 trp
->tr_retry
= sdb
->def_retries
;
1556 trp
->tr_timeout
= timer
;
1557 trp
->tr_bdsp
= NULL
;
1558 trp
->tr_tid
= atp_tid(atp
);
1562 * remember the IOCTL packet so we can ack it
1568 * Now fill in the header (and remember the bits
1571 athp
= AT_ATP_HDR(m2
);
1572 athp
->cmd
= ATP_CMD_TREQ
;
1573 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1576 trp
->tr_xo
= athp
->xo
;
1577 trp
->tr_bitmap
= athp
->bitmap
;
1578 ddp
= AT_DDP_HDR(m2
);
1579 ddp
->type
= DDP_ATP
;
1580 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1582 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1583 trp
->tr_socket
.node
= ddp
->dst_node
;
1584 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1585 trp
->tr_local_socket
= atp
->atp_socket_no
;
1588 /* save the local information in the gref */
1589 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1590 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1591 atp
->atp_gref
->lport
= ddp
->src_node
;
1592 atp
->atp_gref
->ddptype
= DDP_ATP
;
1596 * Put us in the transaction waiting queue
1598 ATDISABLE(s
, atp
->atp_lock
);
1599 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1600 ATENABLE(s
, atp
->atp_lock
);
1603 * Send the message and set the timer
1605 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1606 if ( !trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1607 atp_x_done(trp
); /* no reason to tie up resources */
1609 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1619 * wait for the transaction to complete
1621 ATDISABLE(s
, trp
->tr_lock
);
1622 while ((trp
->tr_state
!= TRANS_DONE
) && (trp
->tr_state
!= TRANS_FAILED
) &&
1623 (trp
->tr_state
!= TRANS_ABORTING
)) {
1624 trp
->tr_rsp_wait
= 1;
1625 rc
= msleep(&trp
->tr_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpsndreq", 0);
1627 trp
->tr_rsp_wait
= 0;
1628 ATENABLE(s
, trp
->tr_lock
);
1634 trp
->tr_rsp_wait
= 0;
1635 ATENABLE(s
, trp
->tr_lock
);
1638 if (trp
->tr_state
== TRANS_FAILED
|| trp
->tr_state
== TRANS_ABORTING
) {
1640 * transaction timed out, return error
1649 * copy out the recv data
1651 if ((*err
= atp_pack_bdsp(trp
, (struct atpBDS
*)bds
)) != 0) {
1658 * copyout the result info
1660 if ((*err
= copyout((caddr_t
)bds
, CAST_USER_ADDR_T(buf
), atpBDSsize
)) != 0) {
1673 /* entry point for ATP send response. respbuf contains a DDP hdr,
1674 * ATP hdr, and atpBDS array. The bdsDataSz field of the first atpBDS
1675 * struct contains the number of atpBDS structs in the array. resplen
1676 * contains the len of the data in respbuf and datalen contains the
1677 * len of the data buffer holding the response packets which the atpBDS
1678 * struct entries point to.
1681 _ATPsndrsp(fd
, respbuff
, resplen
, datalen
, err
, proc
)
1683 unsigned char *respbuff
;
1695 struct atp_state
*atp
;
1696 struct atpBDS
*bdsp
;
1699 int bds_cnt
, count
, len
;
1702 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1705 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1706 || (atp
->atp_flags
& ATP_CLOSING
)) {
1707 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
1708 (u_int
) gref
, gref
->pid
));
1716 * allocate buffer and copy in the response info
1718 if ((m
= gbuf_alloc_wait(resplen
, TRUE
)) == 0) {
1723 if ((*err
= copyin(CAST_USER_ADDR_T(respbuff
), (caddr_t
)gbuf_rptr(m
), resplen
)) != 0) {
1728 gbuf_wset(m
,resplen
);
1729 ((at_ddp_t
*)gbuf_rptr(m
))->src_node
= 0;
1730 bdsp
= (struct atpBDS
*)(gbuf_rptr(m
) + TOTAL_ATP_HDR_SIZE
);
1733 * allocate buffers and copy in the response data.
1734 * note that only the size field of the atpBDS field
1735 * is used internally in the kernel.
1737 bds_cnt
= get_bds_entries(m
); /* count of # entries */
1738 /* check correctness of parameters */
1739 if (bds_cnt
> ATP_TRESP_MAX
) {
1746 for (size
= 0, count
= 0; count
< bds_cnt
; count
++) {
1747 size
+= UAS_VALUE(bdsp
[count
].bdsBuffSz
);
1749 if (size
> datalen
) {
1756 /* get the first mbuf */
1757 if ((mdata
= gbuf_alloc_wait((space
= (size
> MCLBYTES
? MCLBYTES
: size
)), TRUE
)) == 0) {
1763 gbuf_cont(m
) = mdata
;
1764 dataptr
= mtod(mdata
, caddr_t
);
1765 for (count
= 0; count
< bds_cnt
; bdsp
++, count
++) {
1766 if ((bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
)) != 0 &&
1767 (len
= UAS_VALUE(bdsp
->bdsBuffSz
)) != 0) {
1768 if (len
> space
) { /* enough room ? */
1769 gbuf_wset(mdata
, dataptr
- mtod(mdata
, caddr_t
)); /* set len of last mbuf */
1770 /* allocate the next mbuf */
1771 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
1777 mdata
= gbuf_cont(mdata
);
1778 MCLGET(mdata
, M_WAIT
);
1779 if (!(mdata
->m_flags
& M_EXT
)) {
1784 dataptr
= mtod(mdata
, caddr_t
);
1788 if ((*err
= copyin(CAST_USER_ADDR_T(bufaddr
), dataptr
, len
)) != 0) {
1797 gbuf_wset(mdata
, dataptr
- mtod(mdata
, caddr_t
)); /* set len of last mbuf */
1798 gbuf_cont(m
)->m_pkthdr
.len
= size
; /* set packet hdr len */
1800 atp_send_rsp(gref
, m
, TRUE
);
1806 _ATPgetreq(fd
, buf
, buflen
, err
, proc
)
1814 register struct atp_state
*atp
;
1815 register struct atp_rcb
*rcbp
;
1816 register gbuf_t
*m
, *m_head
;
1819 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1822 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1823 || (atp
->atp_flags
& ATP_CLOSING
)) {
1824 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
1825 (u_int
) gref
, gref
->pid
));
1831 ATDISABLE(s
, atp
->atp_lock
);
1832 if ((rcbp
= atp
->atp_attached
.head
) != NULL
) {
1834 * Got one, move it to the active response Q
1836 m_head
= rcbp
->rc_ioctl
;
1837 rcbp
->rc_ioctl
= NULL
;
1840 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
1841 rcbp
->rc_state
= RCB_NOTIFIED
;
1842 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1844 /* detach rcbp from attached queue,
1845 * and free any outstanding resources
1849 ATENABLE(s
, atp
->atp_lock
);
1852 * copyout the request data, including the protocol header
1854 for (size
=0, m
=m_head
; m
; m
= gbuf_cont(m
)) {
1855 if ((len
= gbuf_len(m
)) > buflen
)
1857 copyout((caddr_t
)gbuf_rptr(m
), CAST_USER_ADDR_T(&buf
[size
]), len
);
1859 if ((buflen
-= len
) == 0)
1867 ATENABLE(s
, atp
->atp_lock
);
1874 _ATPgetrsp(fd
, bdsp
, err
, proc
)
1876 struct atpBDS
*bdsp
;
1881 register struct atp_state
*atp
;
1882 register struct atp_trans
*trp
;
1884 char bds
[atpBDSsize
];
1886 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1889 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1890 || (atp
->atp_flags
& ATP_CLOSING
)) {
1891 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
1892 (u_int
) gref
, gref
->pid
));
1898 ATDISABLE(s
, atp
->atp_lock
);
1899 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1900 dPrintf(D_M_ATP
, D_L_INFO
,
1901 ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
1902 (u_int
) atp
, (u_int
) trp
, trp
->tr_state
));
1904 switch (trp
->tr_state
) {
1906 ATENABLE(s
, atp
->atp_lock
);
1907 if ((*err
= copyin(CAST_USER_ADDR_T(bdsp
),
1908 (caddr_t
)bds
, sizeof(bds
))) != 0) {
1913 if ((*err
= atp_pack_bdsp(trp
, (struct atpBDS
*)bds
)) != 0) {
1918 tid
= (int)trp
->tr_tid
;
1920 if ((*err
= copyout((caddr_t
)bds
, CAST_USER_ADDR_T(bdsp
), sizeof(bds
))) != 0) {
1929 * transaction timed out, return error
1931 ATENABLE(s
, atp
->atp_lock
);
1941 ATENABLE(s
, atp
->atp_lock
);
1949 atp_drop_req(gref
, m
)
1954 struct atp_state
*atp
;
1955 struct atp_rcb
*rcbp
;
1959 atp
= (struct atp_state
*)gref
->info
;
1961 atp
= (struct atp_state
*)atp
->atp_msgq
;
1962 ddp
= AT_DDP_HDR(m
);
1963 athp
= AT_ATP_HDR(m
);
1966 * search for the corresponding rcb
1968 ATDISABLE(s
, atp
->atp_lock
);
1969 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1970 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1971 (rcbp
->rc_socket
.node
== ddp
->src_node
) &&
1972 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->src_net
)) &&
1973 (rcbp
->rc_socket
.socket
== ddp
->src_socket
) )
1982 ATENABLE(s
, atp
->atp_lock
);