2 * Copyright (c) 2000 Apple Computer, 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 * Copyright (c) 1996-1998 Apple Computer, Inc.
30 * All Rights Reserved.
33 /* Modified for MP, 1996 by Tuyen Nguyen
34 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
38 #include <sys/errno.h>
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <machine/spl.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
45 #include <sys/filedesc.h>
46 #include <sys/fcntl.h>
47 #include <kern/locks.h>
49 #include <sys/ioctl.h>
50 #include <sys/malloc.h>
51 #include <sys/socket.h>
52 #include <sys/socketvar.h>
56 #include <netat/sysglue.h>
57 #include <netat/appletalk.h>
58 #include <netat/ddp.h>
59 #include <netat/at_pcb.h>
60 #include <netat/atp.h>
61 #include <netat/at_var.h>
62 #include <netat/asp.h>
63 #include <netat/at_pat.h>
64 #include <netat/debug.h>
66 static int loop_cnt
; /* for debugging loops */
67 #define CHK_LOOP(str) { \
68 if (loop_cnt++ > 100) { \
74 static int atp_pack_bdsp(struct atp_trans
*, struct atpBDS
*);
75 static int atp_unpack_bdsp(struct atp_state
*, gbuf_t
*, struct atp_rcb
*,
77 void atp_trp_clock(), asp_clock(), asp_clock_locked(), atp_trp_clock_locked();;
79 extern struct atp_rcb_qhead atp_need_rel
;
80 extern int atp_inited
;
81 extern struct atp_state
*atp_used_list
;
82 extern asp_scb_t
*scb_free_list
;
83 extern atlock_t atpgen_lock
;
84 extern atlock_t atpall_lock
;
85 extern atlock_t atptmo_lock
;
87 extern gbuf_t
*scb_resource_m
;
88 extern gbuf_t
*atp_resource_m
;
89 extern gref_t
*atp_inputQ
[];
90 extern int atp_pidM
[];
91 extern at_ifaddr_t
*ifID_home
;
92 extern lck_mtx_t
* atalk_mutex
;
94 static struct atp_trans
*trp_tmo_list
;
95 struct atp_trans
*trp_tmo_rcb
;
97 /* first bds entry gives number of bds entries in total (hack) */
98 #define get_bds_entries(m) \
99 ((gbuf_len(m) > TOTAL_ATP_HDR_SIZE)? \
100 (UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz)): 0)
102 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
107 trp_tmo_rcb
= atp_trans_alloc(0);
108 atp_timout(atp_rcb_timer
, trp_tmo_rcb
, 10 * HZ
);
109 atp_trp_clock((void *)&atp_inited
);
110 asp_clock((void *)&atp_inited
);
115 untimeout(asp_clock_locked
, (void *)&atp_inited
);
116 untimeout(atp_trp_clock_locked
, (void *)&atp_inited
);
117 atp_untimout(atp_rcb_timer
, trp_tmo_rcb
);
121 /* allocated in asp_scb_alloc(), which is called
123 if (scb_resource_m
) {
124 gbuf_freem(scb_resource_m
);
128 /* allocated in atp_trans_alloc() */
129 if (atp_resource_m
) {
130 gbuf_freem(atp_resource_m
);
132 atp_trans_free_list
= 0;
138 * write queue put routine .... filter out other than IOCTLs
139 * Version 1.8 of atp_write.c on 89/02/09 17:53:26
144 register gref_t
*gref
;
147 register ioc_t
*iocbp
;
149 struct atp_state
*atp
;
150 struct atp_trans
*trp
;
151 struct atp_rcb
*rcbp
;
154 atp
= (struct atp_state
*)gref
->info
;
156 atp
= (struct atp_state
*)atp
->atp_msgq
;
158 switch(gbuf_type(m
)) {
162 dPrintf(D_M_ATP
, D_L_WARNING
,
163 ("atp_wput: atp_msgq discarded\n"));
169 /* Need to ensure that all copyin/copyout calls are made at
170 * put routine time which should be in the user context. (true when
171 * we are the stream head). The service routine can be called on an
172 * unpredictable context and copyin/copyout calls will get wrong results
173 * or even panic the kernel.
175 iocbp
= (ioc_t
*)gbuf_rptr(m
);
177 switch (iocbp
->ioc_cmd
) {
178 case AT_ATP_BIND_REQ
:
179 if (gbuf_cont(m
) == NULL
) {
180 iocbp
->ioc_rval
= -1;
181 atp_iocnak(atp
, m
, EINVAL
);
184 skt
= *(at_socket
*)gbuf_rptr(gbuf_cont(m
));
185 if ((skt
= (at_socket
)atp_bind(gref
, (unsigned int)skt
, 0)) == 0)
186 atp_iocnak(atp
, m
, EINVAL
);
188 *(at_socket
*)gbuf_rptr(gbuf_cont(m
)) = skt
;
191 atp_dequeue_atp(atp
);
195 case AT_ATP_GET_CHANID
:
196 if (gbuf_cont(m
) == NULL
) {
197 iocbp
->ioc_rval
= -1;
198 atp_iocnak(atp
, m
, EINVAL
);
201 *(gref_t
**)gbuf_rptr(gbuf_cont(m
)) = gref
;
205 /* not the close and not the tickle(?) */
206 case AT_ATP_ISSUE_REQUEST_DEF
:
207 case AT_ATP_ISSUE_REQUEST_DEF_NOTE
: {
208 gbuf_t
*bds
, *tmp
, *m2
;
209 struct atp_rcb
*rcbp
;
213 if ((tmp
= gbuf_cont(m
)) != 0) {
214 if ((bds
= gbuf_dupb(tmp
)) == NULL
) {
215 atp_iocnak(atp
, m
, ENOBUFS
);
218 gbuf_rinc(tmp
,atpBDSsize
);
219 gbuf_wset(bds
,atpBDSsize
);
220 iocbp
->ioc_count
-= atpBDSsize
;
221 gbuf_cont(tmp
) = bds
;
225 * send a response to a transaction
228 if (iocbp
->ioc_count
< TOTAL_ATP_HDR_SIZE
) {
229 atp_iocnak(atp
, m
, EINVAL
);
234 * remove the response from the message
238 iocbp
->ioc_count
= 0;
239 ddp
= AT_DDP_HDR(m2
);
240 athp
= AT_ATP_HDR(m2
);
242 gbuf_cont(m2
) = atp
->atp_msgq
;
246 ATDISABLE(s
, atp
->atp_lock
);
248 * search for the corresponding rcb
250 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
251 if (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
) &&
252 rcbp
->rc_socket
.node
== ddp
->dst_node
&&
253 rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
) &&
254 rcbp
->rc_socket
.socket
== ddp
->dst_socket
)
257 ATENABLE(s
, atp
->atp_lock
);
260 * If it has already been sent then return an error
262 if ((rcbp
&& rcbp
->rc_state
!= RCB_NOTIFIED
) ||
263 (rcbp
== NULL
&& athp
->xo
)) {
264 atp_iocnak(atp
, m
, ENOENT
);
268 if (rcbp
== NULL
) { /* a response for an ALO transaction */
269 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
270 atp_iocnak(atp
, m
, ENOBUFS
);
275 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
276 rcbp
->rc_socket
.node
= ddp
->dst_node
;
277 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
278 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
279 rcbp
->rc_bitmap
= 0xff;
281 ATDISABLE(s
, atp
->atp_lock
);
282 rcbp
->rc_state
= RCB_SENDING
;
283 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
284 ATENABLE(s
, atp
->atp_lock
);
286 xcnt
= get_bds_entries(m2
);
287 if ((i
= atp_unpack_bdsp(atp
, m2
, rcbp
, xcnt
, FALSE
))) {
290 atp_iocnak(atp
, m
, i
);
293 atp_send_replies(atp
, rcbp
);
296 * send the ack back to the responder
302 case AT_ATP_GET_POLL
: {
304 gbuf_freem(gbuf_cont(m
));
306 iocbp
->ioc_count
= 0;
310 * search for a waiting request
312 ATDISABLE(s
, atp
->atp_lock
);
313 if ((rcbp
= atp
->atp_attached
.head
)) {
315 * Got one, move it to the active response Q
317 gbuf_cont(m
) = rcbp
->rc_ioctl
;
318 rcbp
->rc_ioctl
= NULL
;
320 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
321 rcbp
->rc_state
= RCB_NOTIFIED
;
322 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
324 /* detach rcbp from attached queue,
325 * and free any outstanding resources
329 ATENABLE(s
, atp
->atp_lock
);
333 * None available - can out
335 ATENABLE(s
, atp
->atp_lock
);
336 atp_iocnak(atp
, m
, EAGAIN
);
341 case AT_ATP_CANCEL_REQUEST
: {
343 * Cancel a pending request
345 if (iocbp
->ioc_count
!= sizeof(int)) {
346 atp_iocnak(atp
, m
, EINVAL
);
349 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
350 gbuf_freem(gbuf_cont(m
));
352 ATDISABLE(s
, atp
->atp_lock
);
353 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
354 if (trp
->tr_tid
== i
)
358 ATENABLE(s
, atp
->atp_lock
);
359 atp_iocnak(atp
, m
, ENOENT
);
361 ATENABLE(s
, atp
->atp_lock
);
370 if (atalk_peek(gref
, &event
) == -1)
371 atp_iocnak(atp
, m
, EAGAIN
);
373 *gbuf_rptr(gbuf_cont(m
)) = event
;
379 case DDP_IOC_GET_CFG
:
380 #ifdef APPLETALK_DEBUG
381 kprintf("atp_wput: DDP_IOC_GET_CFG\n");
383 if (gbuf_cont(m
) == 0) {
384 atp_iocnak(atp
, m
, EINVAL
);
388 /* *** was ddp_get_cfg() *** */
390 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(m
));
391 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
392 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
393 cfgp
->inet
.socket
= atp
->atp_socket_no
;
394 cfgp
->ddptype
= DDP_ATP
;
396 cfgp
->inet
.net
= atp
->atp_gref
->laddr
.s_net
;
397 cfgp
->inet
.node
= atp
->atp_gref
->laddr
.s_node
;
398 cfgp
->inet
.socket
= atp
->atp_gref
->lport
;
399 cfgp
->ddptype
= atp
->atp_gref
->ddptype
;
402 gbuf_wset(gbuf_cont(m
), sizeof(ddp_addr_t
));
408 * Otherwise pass it on, if possible
410 iocbp
->ioc_private
= (void *)gref
;
422 gbuf_t
*atp_build_release(trp
)
423 register struct atp_trans
*trp
;
426 register at_ddp_t
*ddp
;
427 register at_atp_t
*athp
;
430 * Now try and allocate enough space to send the message
431 * if none is available the caller will schedule
432 * a timeout so we can retry for more space soon
434 if ((m
= (gbuf_t
*)gbuf_alloc(AT_WR_OFFSET
+ATP_HDR_SIZE
, PRI_HI
)) != NULL
) {
435 gbuf_rinc(m
,AT_WR_OFFSET
);
436 gbuf_wset(m
,TOTAL_ATP_HDR_SIZE
);
439 UAS_ASSIGN(ddp
->checksum
, 0);
440 ddp
->dst_socket
= trp
->tr_socket
.socket
;
441 ddp
->dst_node
= trp
->tr_socket
.node
;
442 NET_ASSIGN(ddp
->dst_net
, trp
->tr_socket
.net
);
443 ddp
->src_node
= trp
->tr_local_node
;
444 NET_NET(ddp
->src_net
, trp
->tr_local_net
);
447 * clear the cmd/xo/eom/sts/unused fields
449 athp
= AT_ATP_HDR(m
);
450 ATP_CLEAR_CONTROL(athp
);
451 athp
->cmd
= ATP_CMD_TREL
;
452 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
458 void atp_send_replies(atp
, rcbp
)
459 register struct atp_state
*atp
;
460 register struct atp_rcb
*rcbp
;
461 { register gbuf_t
*m
;
463 int s_gen
, s
, cnt
, err
, offset
, space
;
464 unsigned char *m0_rptr
= NULL
, *m0_wptr
= NULL
;
465 register at_atp_t
*athp
;
466 register struct atpBDS
*bdsp
;
467 register gbuf_t
*m2
, *m1
, *m0
, *mhdr
;
469 gbuf_t
*mprev
, *mlist
= 0;
470 at_socket src_socket
= (at_socket
)atp
->atp_socket_no
;
471 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
473 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
475 struct timeval timenow
;
477 ATDISABLE(s
, atp
->atp_lock
);
478 if (rcbp
->rc_queue
!= atp
) {
479 ATENABLE(s
, atp
->atp_lock
);
482 if (rcbp
->rc_not_sent_bitmap
== 0)
483 goto nothing_to_send
;
485 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
, ("atp_send_replies\n"));
487 * Do this for each message that hasn't been sent
489 cnt
= rcbp
->rc_pktcnt
;
490 for (i
= 0; i
< cnt
; i
++) {
492 if (rcbp
->rc_snd
[i
]) {
494 gbuf_alloc(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,PRI_MED
))
496 for (cnt
= 0; cnt
< i
; cnt
++)
498 gbuf_freeb(rc_xmt
[cnt
]);
499 goto nothing_to_send
;
506 if (gbuf_len(m
) > TOTAL_ATP_HDR_SIZE
)
507 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
512 space
= gbuf_msgsize(m0
);
515 for (i
= 0; i
< cnt
; i
++) {
516 if (rcbp
->rc_snd
[i
] == 0) {
517 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
))) {
523 /* setup header fields */
524 gbuf_rinc(mhdr
,AT_WR_OFFSET
);
525 gbuf_wset(mhdr
,TOTAL_ATP_HDR_SIZE
);
526 *(struct ddp_atp
*)(gbuf_rptr(mhdr
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
527 athp
= AT_ATP_HDR(mhdr
);
528 ATP_CLEAR_CONTROL(athp
);
529 athp
->cmd
= ATP_CMD_TRESP
;
532 athp
->eom
= 1; /* for the last fragment */
534 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
535 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)) && m0
!= 0 && space
> 0) {
536 if ((m1
= m_copym(m0
, offset
, len
, M_DONTWAIT
)) == 0) {
537 for (i
= 0; i
< cnt
; i
++)
539 gbuf_freem(rc_xmt
[i
]);
540 goto nothing_to_send
;
544 gbuf_cont(mhdr
) = m1
;
548 AT_DDP_HDR(mhdr
)->src_socket
= src_socket
;
549 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
,
550 ("atp_send_replies: %d, socket=%d, size=%d\n",
551 i
, atp
->atp_socket_no
, gbuf_msgsize(gbuf_cont(m2
))));
554 gbuf_next(mprev
) = mhdr
;
560 rcbp
->rc_not_sent_bitmap
&= ~atp_mask
[i
];
561 if (rcbp
->rc_not_sent_bitmap
== 0)
565 * on to the next frag
570 ATENABLE(s
, atp
->atp_lock
);
572 ATDISABLE(s
, atp
->atp_lock
);
577 * If all replies from this reply block have been sent then
578 * remove it from the queue and mark it so
580 if (rcbp
->rc_queue
!= atp
) {
581 ATENABLE(s
, atp
->atp_lock
);
584 rcbp
->rc_rep_waiting
= 0;
587 * If we are doing execute once re-set the rcb timeout
588 * each time we send back any part of the response. Note
589 * that this timer is started when an initial request is
590 * received. Each response reprimes the timer. Duplicate
591 * requests do not reprime the timer.
593 * We have sent all of a response so free the
596 if (rcbp
->rc_xo
&& rcbp
->rc_state
!= RCB_RELEASED
) {
597 getmicrouptime(&timenow
);
598 ATDISABLE(s_gen
, atpgen_lock
);
599 if (rcbp
->rc_timestamp
== 0) {
600 rcbp
->rc_timestamp
= timenow
.tv_sec
;
601 if (rcbp
->rc_timestamp
== 0)
602 rcbp
->rc_timestamp
= 1;
603 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
605 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
606 ATENABLE(s_gen
, atpgen_lock
);
609 ATENABLE(s
, atp
->atp_lock
);
610 } /* atp_send_replies */
614 atp_pack_bdsp(trp
, bdsp
)
615 register struct atp_trans
*trp
;
616 register struct atpBDS
*bdsp
;
618 register gbuf_t
*m
= NULL
;
619 register int i
, datsize
= 0;
620 struct atpBDS
*bdsbase
= bdsp
;
623 dPrintf(D_M_ATP
, D_L_INFO
, ("atp_pack_bdsp: socket=%d\n",
624 trp
->tr_queue
->atp_socket_no
));
626 for (i
= 0; i
< ATP_TRESP_MAX
; i
++, bdsp
++) {
627 unsigned short bufsize
= UAS_VALUE(bdsp
->bdsBuffSz
);
628 long bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
);
630 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
633 /* discard ddp hdr on first packet */
635 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
637 /* this field may contain control information even when
638 no data is present */
639 UAL_UAL(bdsp
->bdsUserData
,
640 (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
641 gbuf_rinc(m
, ATP_HDR_SIZE
);
643 if ((bufsize
!= 0) && (bufaddr
!= 0)) {
644 /* user expects data back */
646 register char *buf
= (char *)bufaddr
;
649 unsigned short len
= (unsigned short)(gbuf_len(m
));
653 if ((error
= copyout((caddr_t
)gbuf_rptr(m
),
654 CAST_USER_ADDR_T(&buf
[tmp
]),
664 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
667 gbuf_freem(trp
->tr_rcv
[i
]);
668 trp
->tr_rcv
[i
] = NULL
;
671 /* report the number of packets */
672 UAS_ASSIGN(((struct atpBDS
*)bdsbase
)->bdsBuffSz
, i
);
674 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
678 } /* atp_pack_bdsp */
681 /* create an mbuf chain with mbuf packet headers for each ATP response packet
682 * to be sent. m contains the DDP hdr, ATP hdr, and and array of atpBDS structs.
683 * chained to m is an mbuf that contians the actual data pointed to by the atpBDS
687 atp_unpack_bdsp(atp
, m
, rcbp
, cnt
, wait
)
688 struct atp_state
*atp
;
689 gbuf_t
*m
; /* ddp, atp and bdsp gbuf_t */
690 register struct atp_rcb
*rcbp
;
691 register int cnt
, wait
;
693 register struct atpBDS
*bdsp
;
694 register gbuf_t
*m2
, *m1
, *m0
, *mhdr
;
698 at_socket src_socket
;
701 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
703 gbuf_t
*mprev
, *mlist
= 0;
704 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
705 unsigned char *m0_rptr
, *m0_wptr
;
706 int err
, offset
, space
;
707 struct timeval timenow
;
710 * get the user data structure pointer
712 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
715 * Guard against bogus count argument.
717 if ((unsigned) cnt
> ATP_TRESP_MAX
) {
718 dPrintf(D_M_ATP
, D_L_ERROR
,
719 ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt
));
723 if ((src_socket
= (at_socket
)atp
->atp_socket_no
) == 0xFF) {
724 /* comparison was to -1, however src_socket is a u_char */
731 rcbp
->rc_pktcnt
= cnt
;
732 rcbp
->rc_state
= RCB_SENDING
;
733 rcbp
->rc_not_sent_bitmap
= 0;
737 * special case this to
738 * improve AFP write transactions to the server
741 if ((m2
= gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,
744 gbuf_rinc(m2
,AT_WR_OFFSET
);
745 gbuf_wset(m2
,TOTAL_ATP_HDR_SIZE
);
746 *(struct ddp_atp
*)(gbuf_rptr(m2
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
747 athp
= AT_ATP_HDR(m2
);
748 ATP_CLEAR_CONTROL(athp
);
749 athp
->cmd
= ATP_CMD_TRESP
;
751 athp
->eom
= 1; /* there's only 1 fragment */
753 /* *** why only if cnt > 0? *** */
755 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
757 if (!append_copy((struct mbuf
*)m2
,
758 (struct mbuf
*)m0
, wait
)) {
763 * send the message and mark it as sent
765 AT_DDP_HDR(m2
)->src_socket
= src_socket
;
766 dPrintf(D_M_ATP_LOW
, D_L_INFO
,
767 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
768 0,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(m2
)),cnt
));
773 /* create an array of mbuf packet headers for the packets to be sent
774 * to contain the atp and ddp headers with room at the front for the
777 for (i
= 0; i
< cnt
; i
++) {
778 /* all hdrs, packet data and dst addr storage */
780 gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
, wait
)) == NULL
) {
781 for (cnt
= 0; cnt
< i
; cnt
++)
783 gbuf_freeb(rc_xmt
[cnt
]);
788 /* run through the atpBDS structs and create an mbuf for the data
789 * portion of each packet to be sent. these get chained to the mbufs
790 * containing the ATP and DDP headers. this code assumes that no ATP
791 * packet is contained in more than 2 mbufs (e.i crosses mbuf boundary
792 * no more than one time).
796 space
= gbuf_msgsize(m0
);
797 for (i
= 0; i
< cnt
; i
++) { /* for each hdr mbuf */
799 /* setup header fields */
800 gbuf_rinc(mhdr
,AT_WR_OFFSET
);
801 gbuf_wset(mhdr
,TOTAL_ATP_HDR_SIZE
);
802 *(struct ddp_atp
*)(gbuf_rptr(mhdr
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
803 athp
= AT_ATP_HDR(mhdr
);
804 ATP_CLEAR_CONTROL(athp
);
805 athp
->cmd
= ATP_CMD_TRESP
;
808 athp
->eom
= 1; /* for the last fragment */
809 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
811 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)) != 0 && m0
!= 0 && space
> 0) {
812 if ((m1
= m_copym(m0
, offset
, len
, wait
)) == 0) {
813 for (i
= 0; i
< cnt
; i
++)
815 gbuf_freem(rc_xmt
[i
]);
818 gbuf_cont(mhdr
) = m1
;
823 AT_DDP_HDR(mhdr
)->src_socket
= src_socket
;
824 dPrintf(D_M_ATP_LOW
,D_L_INFO
,
825 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
826 i
,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(mhdr
)),cnt
));
828 gbuf_next(mprev
) = mhdr
;
833 * on to the next frag
842 getmicrouptime(&timenow
);
843 ATDISABLE(s_gen
, atpgen_lock
);
844 if (rcbp
->rc_timestamp
== 0) {
845 if ((rcbp
->rc_timestamp
= timenow
.tv_sec
) == 0)
846 rcbp
->rc_timestamp
= 1;
847 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
849 ATENABLE(s_gen
, atpgen_lock
);
855 } /* atp_unpack_bdsp */
857 #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6)
858 #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
859 static unsigned int sNext
= 0;
861 int atp_bind(gref
, sVal
, flag
)
866 extern unsigned char asp_inpC
[];
867 extern asp_scb_t
*asp_scbQ
[];
868 unsigned char inpC
, sNextUsed
= 0;
869 unsigned int sMin
, sMax
, sSav
;
870 struct atp_state
*atp
;
873 atp
= (struct atp_state
*)gref
->info
;
875 atp
= (struct atp_state
*)atp
->atp_msgq
;
877 sMax
= ATP_SOCKET_LAST
;
878 sMin
= ATP_SOCKET_FIRST
;
879 ATDISABLE(s
, atpgen_lock
);
880 if (flag
&& (*flag
== 3)) {
889 ((sVal
> sMax
) || (sVal
< 2) || (sVal
== 6) ||
890 (ddp_socket_inuse(sVal
, DDP_ATP
) &&
891 (atp_inputQ
[sVal
] != (gref_t
*)1)))) {
892 ATENABLE(s
, atpgen_lock
);
899 for (sVal
=sMin
; sVal
<= sMax
; sVal
++) {
900 if (!ddp_socket_inuse(sVal
, DDP_ATP
) ||
901 atp_inputQ
[sVal
] == (gref_t
*)1)
903 else if (flag
&& (*flag
== 3) && asp_scbQ
[sVal
]) {
904 if ((asp_scbQ
[sVal
]->dflag
== *flag
)
905 && (asp_inpC
[sVal
] < inpC
) ) {
906 inpC
= asp_inpC
[sVal
];
912 if (flag
&& (*flag
== 3)) {
916 sMin
= ATP_SOCKET_FIRST
+40;
920 *flag
= (unsigned char)sSav
;
922 ATENABLE(s
, atpgen_lock
);
926 atp
->atp_socket_no
= (short)sVal
;
927 atp_inputQ
[sVal
] = gref
;
929 atp_pidM
[sVal
] = atp
->atp_pid
;
930 else if (*flag
== 3) {
932 if (sNext
> ATP_SOCKET_LAST
)
936 ATENABLE(s
, atpgen_lock
);
940 void atp_req_ind(atp
, mioc
)
941 register struct atp_state
*atp
;
942 register gbuf_t
*mioc
;
944 register struct atp_rcb
*rcbp
;
947 if ((rcbp
= atp
->atp_attached
.head
) != 0) {
948 gbuf_cont(mioc
) = rcbp
->rc_ioctl
;
949 rcbp
->rc_ioctl
= NULL
;
950 ATDISABLE(s
, atp
->atp_lock
);
952 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
953 rcbp
->rc_state
= RCB_NOTIFIED
;
954 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
957 ATENABLE(s
, atp
->atp_lock
);
959 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
961 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
962 asp_ack_reply(atp
->atp_gref
, mioc
);
967 void atp_rsp_ind(trp
, mioc
)
968 register struct atp_trans
*trp
;
969 register gbuf_t
*mioc
;
971 register struct atp_state
*atp
= trp
->tr_queue
;
977 switch (trp
->tr_state
) {
979 if (asp_pack_bdsp(trp
, &xm
) < 0)
981 gbuf_cont(mioc
) = trp
->tr_xmt
;
996 dPrintf(D_M_ATP
, D_L_ERROR
,
997 ("atp_rsp_ind: TRANSACTION error\n"));
998 atp_iocnak(atp
, mioc
, err
);
1000 gbuf_cont(gbuf_cont(mioc
)) = xm
;
1001 atp_iocack(atp
, mioc
);
1006 void atp_cancel_req(gref
, tid
)
1011 struct atp_state
*atp
;
1012 struct atp_trans
*trp
;
1014 atp
= (struct atp_state
*)gref
->info
;
1016 atp
= (struct atp_state
*)atp
->atp_msgq
;
1018 ATDISABLE(s
, atp
->atp_lock
);
1019 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1020 if (trp
->tr_tid
== tid
)
1023 ATENABLE(s
, atp
->atp_lock
);
1029 * remove atp from the use list
1032 atp_dequeue_atp(atp
)
1033 struct atp_state
*atp
;
1037 ATDISABLE(s
, atpall_lock
);
1038 if (atp
== atp_used_list
) {
1039 if ((atp_used_list
= atp
->atp_trans_waiting
) != 0)
1040 atp
->atp_trans_waiting
->atp_rcb_waiting
= 0;
1041 } else if (atp
->atp_rcb_waiting
) {
1042 if ((atp
->atp_rcb_waiting
->atp_trans_waiting
1043 = atp
->atp_trans_waiting
) != 0)
1044 atp
->atp_trans_waiting
->atp_rcb_waiting
= atp
->atp_rcb_waiting
;
1047 atp
->atp_trans_waiting
= 0;
1048 atp
->atp_rcb_waiting
= 0;
1049 ATENABLE(s
, atpall_lock
);
1053 atp_timout(func
, trp
, ticks
)
1055 struct atp_trans
*trp
;
1060 struct atp_trans
*curr_trp
, *prev_trp
;
1062 ATDISABLE(s
, atptmo_lock
);
1063 if (trp
->tr_tmo_func
) {
1064 ATENABLE(s
, atptmo_lock
);
1068 trp
->tr_tmo_func
= func
;
1069 trp
->tr_tmo_delta
= 1+(ticks
>>5);
1071 if (trp_tmo_list
== 0) {
1072 trp
->tr_tmo_next
= trp
->tr_tmo_prev
= 0;
1074 ATENABLE(s
, atptmo_lock
);
1079 curr_trp
= trp_tmo_list
;
1083 sum
+= curr_trp
->tr_tmo_delta
;
1084 if (sum
> trp
->tr_tmo_delta
) {
1085 sum
-= curr_trp
->tr_tmo_delta
;
1086 trp
->tr_tmo_delta
-= sum
;
1087 curr_trp
->tr_tmo_delta
-= trp
->tr_tmo_delta
;
1090 prev_trp
= curr_trp
;
1091 if ((curr_trp
= curr_trp
->tr_tmo_next
) == 0) {
1092 trp
->tr_tmo_delta
-= sum
;
1098 trp
->tr_tmo_prev
= prev_trp
;
1099 if ((trp
->tr_tmo_next
= prev_trp
->tr_tmo_next
) != 0)
1100 prev_trp
->tr_tmo_next
->tr_tmo_prev
= trp
;
1101 prev_trp
->tr_tmo_next
= trp
;
1103 trp
->tr_tmo_prev
= 0;
1104 trp
->tr_tmo_next
= trp_tmo_list
;
1105 trp_tmo_list
->tr_tmo_prev
= trp
;
1108 ATENABLE(s
, atptmo_lock
);
1112 atp_untimout(func
, trp
)
1114 struct atp_trans
*trp
;
1118 ATDISABLE(s
, atptmo_lock
);
1119 if (trp
->tr_tmo_func
== 0) {
1120 ATENABLE(s
, atptmo_lock
);
1124 if (trp_tmo_list
== trp
) {
1125 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0) {
1126 trp_tmo_list
->tr_tmo_prev
= 0;
1127 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1130 if ((trp
->tr_tmo_prev
->tr_tmo_next
= trp
->tr_tmo_next
) != 0) {
1131 trp
->tr_tmo_next
->tr_tmo_prev
= trp
->tr_tmo_prev
;
1132 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1135 trp
->tr_tmo_func
= 0;
1136 ATENABLE(s
, atptmo_lock
);
1140 atp_trp_clock_locked(arg
)
1153 struct atp_trans
*trp
;
1154 void (*tr_tmo_func
)();
1156 ATDISABLE(s
, atptmo_lock
);
1158 trp_tmo_list
->tr_tmo_delta
--;
1159 while (((trp
= trp_tmo_list
) != 0) && (trp_tmo_list
->tr_tmo_delta
== 0)) {
1160 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0)
1161 trp_tmo_list
->tr_tmo_prev
= 0;
1162 if ((tr_tmo_func
= trp
->tr_tmo_func
) != 0) {
1163 trp
->tr_tmo_func
= 0;
1164 ATENABLE(s
, atptmo_lock
);
1165 (*tr_tmo_func
)(trp
);
1166 ATDISABLE(s
, atptmo_lock
);
1169 ATENABLE(s
, atptmo_lock
);
1171 timeout(atp_trp_clock_locked
, (void *)arg
, (1<<5));
1175 atp_send_req(gref
, mioc
)
1179 register struct atp_state
*atp
;
1180 register struct atp_trans
*trp
;
1181 register ioc_t
*iocbp
;
1182 register at_atp_t
*athp
;
1183 register at_ddp_t
*ddp
;
1184 gbuf_t
*m
, *m2
, *bds
;
1185 struct atp_set_default
*sdb
;
1189 atp
= (struct atp_state
*)((struct atp_state
*)gref
->info
)->atp_msgq
;
1190 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1192 if ((trp
= atp_trans_alloc(atp
)) == NULL
) {
1194 ((asp_scb_t
*)gref
->info
)->stat_msg
= mioc
;
1195 iocbp
->ioc_private
= (void *)gref
;
1196 timeout(atp_retry_req
, mioc
, 10);
1200 m2
= gbuf_cont(mioc
);
1201 if ((bds
= gbuf_dupb(m2
)) == NULL
) {
1202 atp_trans_free(trp
);
1205 gbuf_rinc(m2
,atpBDSsize
);
1206 gbuf_wset(bds
,atpBDSsize
);
1207 iocbp
->ioc_count
-= atpBDSsize
;
1208 gbuf_cont(m2
) = NULL
;
1210 old
= iocbp
->ioc_cmd
;
1211 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
1212 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1215 * The at_snd_req library routine multiplies seconds by 100.
1216 * We need to divide by 100 in order to obtain the timer.
1218 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1220 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1221 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1223 trp
->tr_retry
= sdb
->def_retries
;
1224 trp
->tr_timeout
= timer
;
1226 trp
->tr_tid
= atp_tid(atp
);
1230 * Now fill in the header (and remember the bits
1233 athp
= AT_ATP_HDR(m2
);
1234 athp
->cmd
= ATP_CMD_TREQ
;
1235 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1238 trp
->tr_xo
= athp
->xo
;
1239 trp
->tr_bitmap
= athp
->bitmap
;
1240 ddp
= AT_DDP_HDR(m2
);
1241 ddp
->type
= DDP_ATP
;
1242 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1243 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1244 trp
->tr_socket
.node
= ddp
->dst_node
;
1245 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1246 trp
->tr_local_socket
= atp
->atp_socket_no
;
1247 trp
->tr_local_node
= ddp
->src_node
;
1248 NET_NET(trp
->tr_local_net
, ddp
->src_net
);
1251 /* save the local information in the gref */
1252 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1253 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1254 atp
->atp_gref
->lport
= ddp
->src_node
;
1255 atp
->atp_gref
->ddptype
= DDP_ATP
;
1259 * Put us in the transaction waiting queue
1261 ATDISABLE(s
, atp
->atp_lock
);
1262 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1263 ATENABLE(s
, atp
->atp_lock
);
1266 * Send the message and set the timer
1268 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1269 if (!trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1270 atp_x_done(trp
); /* no reason to tie up resources */
1272 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1274 trace_mbufs(D_M_ATP_LOW
, " s", m
);
1277 } /* atp_send_req */
1279 void atp_retry_req(arg
)
1282 gbuf_t
*m
= (gbuf_t
*)arg
;
1287 gref
= (gref_t
*)((ioc_t
*)gbuf_rptr(m
))->ioc_private
;
1289 ((asp_scb_t
*)gref
->info
)->stat_msg
= 0;
1290 atp_send_req(gref
, m
);
1295 void atp_send_rsp(gref
, m
, wait
)
1300 register struct atp_state
*atp
;
1301 register struct atp_rcb
*rcbp
;
1302 register at_atp_t
*athp
;
1303 register at_ddp_t
*ddp
;
1306 atp
= (struct atp_state
*)gref
->info
;
1308 atp
= (struct atp_state
*)atp
->atp_msgq
;
1309 ddp
= AT_DDP_HDR(m
);
1310 athp
= AT_ATP_HDR(m
);
1313 * search for the corresponding rcb
1315 ATDISABLE(s
, atp
->atp_lock
);
1316 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1317 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1318 (rcbp
->rc_socket
.node
== ddp
->dst_node
) &&
1319 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
)) &&
1320 (rcbp
->rc_socket
.socket
== ddp
->dst_socket
) )
1325 * If it has already been sent then drop the request
1327 if ((rcbp
&& (rcbp
->rc_state
!= RCB_NOTIFIED
)) ||
1328 (rcbp
== NULL
&& athp
->xo
) ) {
1329 ATENABLE(s
, atp
->atp_lock
);
1333 ATENABLE(s
, atp
->atp_lock
);
1335 if (rcbp
== NULL
) { /* a response is being sent for an ALO transaction */
1336 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
1341 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
1342 rcbp
->rc_socket
.node
= ddp
->dst_node
;
1343 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
1344 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
1345 rcbp
->rc_bitmap
= 0xff;
1347 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
1348 ATDISABLE(s
, atp
->atp_lock
);
1349 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1350 ATENABLE(s
, atp
->atp_lock
);
1352 else if (ddp
->src_node
== 0) {
1353 NET_NET(ddp
->src_net
, rcbp
->rc_local_net
);
1354 ddp
->src_node
= rcbp
->rc_local_node
;
1357 xcnt
= get_bds_entries(m
);
1358 s
= atp_unpack_bdsp(atp
, m
, rcbp
, xcnt
, wait
);
1360 atp_send_replies(atp
, rcbp
);
1361 } /* atp_send_rsp */
1363 int asp_pack_bdsp(trp
, xm
)
1364 register struct atp_trans
*trp
;
1367 register struct atpBDS
*bdsp
;
1368 register gbuf_t
*m
, *m2
;
1370 gbuf_t
*m_prev
, *m_head
= 0;
1372 dPrintf(D_M_ATP
, D_L_INFO
, ("asp_pack_bdsp: socket=%d\n",
1373 trp
->tr_queue
->atp_socket_no
));
1375 if ((m2
= trp
->tr_bdsp
) == NULL
)
1377 trp
->tr_bdsp
= NULL
;
1378 bdsp
= (struct atpBDS
*)gbuf_rptr(m2
);
1380 for (i
= 0; (i
< ATP_TRESP_MAX
&&
1381 bdsp
< (struct atpBDS
*)(gbuf_wptr(m2
))); i
++) {
1382 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
1385 /* discard ddp hdr on first packet */
1386 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
1389 UAL_UAL(bdsp
->bdsUserData
, (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
1390 gbuf_rinc(m
, ATP_HDR_SIZE
);
1392 if (UAL_VALUE(bdsp
->bdsBuffAddr
)) {
1395 /* user expects data back */
1400 gbuf_cont(m_prev
) = m
;
1402 tmp
= (short)gbuf_len(m
);
1403 while (gbuf_cont(m
)) {
1405 tmp
+= (short)(gbuf_len(m
));
1409 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
1411 trp
->tr_rcv
[i
] = NULL
;
1416 * report the number of packets
1418 UAS_ASSIGN(((struct atpBDS
*)gbuf_rptr(m2
))->bdsBuffSz
, i
);
1420 if (trp
->tr_xmt
) /* an ioctl block is still held? */
1421 gbuf_cont(trp
->tr_xmt
) = m2
;
1430 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
1431 gbuf_msgsize(*xm
)));
1437 * The following routines are direct entries from system
1438 * calls to allow fast sending and recving of ATP data.
1442 _ATPsndreq(fd
, buf
, len
, nowait
, err
, proc
)
1454 register struct atp_state
*atp
;
1455 register struct atp_trans
*trp
;
1456 register ioc_t
*iocbp
;
1457 register at_atp_t
*athp
;
1458 register at_ddp_t
*ddp
;
1459 struct atp_set_default
*sdb
;
1460 gbuf_t
*m2
, *m
, *mioc
;
1461 char bds
[atpBDSsize
];
1463 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1466 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1467 || (atp
->atp_flags
& ATP_CLOSING
)) {
1468 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
1469 (u_int
) gref
, gref
->pid
));
1475 if (len
< atpBDSsize
+ sizeof(struct atp_set_default
) + TOTAL_ATP_HDR_SIZE
||
1476 len
> atpBDSsize
+ sizeof(struct atp_set_default
) + TOTAL_ATP_HDR_SIZE
+
1483 while ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_MED
)) == 0) {
1485 /* the vaue of 10n terms of hz is 100ms */
1487 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1489 ATDISABLE(s
, atp
->atp_delay_lock
);
1490 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpmioc", &ts
);
1491 ATENABLE(s
, atp
->atp_delay_lock
);
1499 gbuf_wset(mioc
,sizeof(ioc_t
));
1501 while ((m2
= gbuf_alloc(len
, PRI_MED
)) == 0) {
1503 /* the vaue of 10n terms of hz is 100ms */
1505 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1507 ATDISABLE(s
, atp
->atp_delay_lock
);
1508 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpm2", &ts
);
1509 ATENABLE(s
, atp
->atp_delay_lock
);
1518 gbuf_cont(mioc
) = m2
;
1519 if (((*err
= copyin(CAST_USER_ADDR_T(buf
), (caddr_t
)bds
, atpBDSsize
)) != 0)
1520 || ((*err
= copyin(CAST_USER_ADDR_T(&buf
[atpBDSsize
]),
1521 (caddr_t
)gbuf_rptr(m2
), len
)) != 0)) {
1526 gbuf_set_type(mioc
, MSG_IOCTL
);
1527 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1528 iocbp
->ioc_count
= len
;
1529 iocbp
->ioc_cmd
= nowait
? AT_ATP_ISSUE_REQUEST_NOTE
: AT_ATP_ISSUE_REQUEST
;
1530 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1533 * The at_snd_req library routine multiplies seconds by 100.
1534 * We need to divide by 100 in order to obtain the timer.
1536 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1538 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1539 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1542 * allocate and set up the transaction record
1544 while ((trp
= atp_trans_alloc(atp
)) == 0) {
1546 /* the vaue of 10n terms of hz is 100ms */
1548 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1550 ATDISABLE(s
, atp
->atp_delay_lock
);
1551 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atptrp", &ts
);
1552 ATENABLE(s
, atp
->atp_delay_lock
);
1560 trp
->tr_retry
= sdb
->def_retries
;
1561 trp
->tr_timeout
= timer
;
1562 trp
->tr_bdsp
= NULL
;
1563 trp
->tr_tid
= atp_tid(atp
);
1567 * remember the IOCTL packet so we can ack it
1573 * Now fill in the header (and remember the bits
1576 athp
= AT_ATP_HDR(m2
);
1577 athp
->cmd
= ATP_CMD_TREQ
;
1578 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1581 trp
->tr_xo
= athp
->xo
;
1582 trp
->tr_bitmap
= athp
->bitmap
;
1583 ddp
= AT_DDP_HDR(m2
);
1584 ddp
->type
= DDP_ATP
;
1585 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1587 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1588 trp
->tr_socket
.node
= ddp
->dst_node
;
1589 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1590 trp
->tr_local_socket
= atp
->atp_socket_no
;
1593 /* save the local information in the gref */
1594 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1595 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1596 atp
->atp_gref
->lport
= ddp
->src_node
;
1597 atp
->atp_gref
->ddptype
= DDP_ATP
;
1601 * Put us in the transaction waiting queue
1603 ATDISABLE(s
, atp
->atp_lock
);
1604 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1605 ATENABLE(s
, atp
->atp_lock
);
1608 * Send the message and set the timer
1610 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1611 if ( !trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1612 atp_x_done(trp
); /* no reason to tie up resources */
1614 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1624 * wait for the transaction to complete
1626 ATDISABLE(s
, trp
->tr_lock
);
1627 while ((trp
->tr_state
!= TRANS_DONE
) && (trp
->tr_state
!= TRANS_FAILED
) &&
1628 (trp
->tr_state
!= TRANS_ABORTING
)) {
1629 trp
->tr_rsp_wait
= 1;
1630 rc
= msleep(&trp
->tr_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpsndreq", 0);
1632 trp
->tr_rsp_wait
= 0;
1633 ATENABLE(s
, trp
->tr_lock
);
1639 trp
->tr_rsp_wait
= 0;
1640 ATENABLE(s
, trp
->tr_lock
);
1643 if (trp
->tr_state
== TRANS_FAILED
|| trp
->tr_state
== TRANS_ABORTING
) {
1645 * transaction timed out, return error
1654 * copy out the recv data
1656 if ((*err
= atp_pack_bdsp(trp
, (struct atpBDS
*)bds
)) != 0) {
1663 * copyout the result info
1665 if ((*err
= copyout((caddr_t
)bds
, CAST_USER_ADDR_T(buf
), atpBDSsize
)) != 0) {
1678 /* entry point for ATP send response. respbuf contains a DDP hdr,
1679 * ATP hdr, and atpBDS array. The bdsDataSz field of the first atpBDS
1680 * struct contains the number of atpBDS structs in the array. resplen
1681 * contains the len of the data in respbuf and datalen contains the
1682 * len of the data buffer holding the response packets which the atpBDS
1683 * struct entries point to.
1686 _ATPsndrsp(fd
, respbuff
, resplen
, datalen
, err
, proc
)
1688 unsigned char *respbuff
;
1700 struct atp_state
*atp
;
1701 struct atpBDS
*bdsp
;
1704 int bds_cnt
, count
, len
;
1707 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1710 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1711 || (atp
->atp_flags
& ATP_CLOSING
)) {
1712 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
1713 (u_int
) gref
, gref
->pid
));
1721 * allocate buffer and copy in the response info
1723 if (resplen
< 0 || resplen
> TOTAL_ATP_HDR_SIZE
+ sizeof(struct atpBDS
)*ATP_TRESP_MAX
) {
1728 if ((m
= gbuf_alloc_wait(resplen
, TRUE
)) == 0) {
1733 if ((*err
= copyin(CAST_USER_ADDR_T(respbuff
), (caddr_t
)gbuf_rptr(m
), resplen
)) != 0) {
1738 gbuf_wset(m
,resplen
);
1739 ((at_ddp_t
*)gbuf_rptr(m
))->src_node
= 0;
1740 bdsp
= (struct atpBDS
*)(gbuf_rptr(m
) + TOTAL_ATP_HDR_SIZE
);
1743 * allocate buffers and copy in the response data.
1744 * note that only the size field of the atpBDS field
1745 * is used internally in the kernel.
1747 bds_cnt
= get_bds_entries(m
); /* count of # entries */
1748 /* check correctness of parameters */
1749 if (bds_cnt
> ATP_TRESP_MAX
) {
1756 for (size
= 0, count
= 0; count
< bds_cnt
; count
++) {
1757 if (UAS_VALUE(bdsp
[count
].bdsBuffSz
) > ATP_DATA_SIZE
) {
1763 size
+= UAS_VALUE(bdsp
[count
].bdsBuffSz
);
1765 if (size
> datalen
) {
1772 /* get the first mbuf */
1773 if ((mdata
= gbuf_alloc_wait((space
= (size
> MCLBYTES
? MCLBYTES
: size
)), TRUE
)) == 0) {
1779 gbuf_cont(m
) = mdata
;
1780 dataptr
= mtod(mdata
, caddr_t
);
1781 for (count
= 0; count
< bds_cnt
; bdsp
++, count
++) {
1782 if ((bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
)) != 0 &&
1783 (len
= UAS_VALUE(bdsp
->bdsBuffSz
)) != 0) {
1784 if (len
> space
) { /* enough room ? */
1785 gbuf_wset(mdata
, dataptr
- mtod(mdata
, caddr_t
)); /* set len of last mbuf */
1786 /* allocate the next mbuf */
1787 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
1793 mdata
= gbuf_cont(mdata
);
1794 MCLGET(mdata
, M_WAIT
);
1795 if (!(mdata
->m_flags
& M_EXT
)) {
1800 dataptr
= mtod(mdata
, caddr_t
);
1804 if ((*err
= copyin(CAST_USER_ADDR_T(bufaddr
), dataptr
, len
)) != 0) {
1813 gbuf_wset(mdata
, dataptr
- mtod(mdata
, caddr_t
)); /* set len of last mbuf */
1814 gbuf_cont(m
)->m_pkthdr
.len
= size
; /* set packet hdr len */
1816 atp_send_rsp(gref
, m
, TRUE
);
1822 _ATPgetreq(fd
, buf
, buflen
, err
, proc
)
1830 register struct atp_state
*atp
;
1831 register struct atp_rcb
*rcbp
;
1832 register gbuf_t
*m
, *m_head
;
1835 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1838 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1839 || (atp
->atp_flags
& ATP_CLOSING
)) {
1840 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
1841 (u_int
) gref
, gref
->pid
));
1847 if (buflen
< DDP_X_HDR_SIZE
+ ATP_HDR_SIZE
) {
1853 ATDISABLE(s
, atp
->atp_lock
);
1854 if ((rcbp
= atp
->atp_attached
.head
) != NULL
) {
1856 * Got one, move it to the active response Q
1858 m_head
= rcbp
->rc_ioctl
;
1859 rcbp
->rc_ioctl
= NULL
;
1862 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
1863 rcbp
->rc_state
= RCB_NOTIFIED
;
1864 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1866 /* detach rcbp from attached queue,
1867 * and free any outstanding resources
1871 ATENABLE(s
, atp
->atp_lock
);
1874 * copyout the request data, including the protocol header
1876 for (size
=0, m
=m_head
; m
; m
= gbuf_cont(m
)) {
1877 if ((len
= gbuf_len(m
)) > buflen
)
1879 copyout((caddr_t
)gbuf_rptr(m
), CAST_USER_ADDR_T(&buf
[size
]), len
);
1881 if ((buflen
-= len
) == 0)
1889 ATENABLE(s
, atp
->atp_lock
);
1896 _ATPgetrsp(fd
, bdsp
, err
, proc
)
1898 struct atpBDS
*bdsp
;
1903 register struct atp_state
*atp
;
1904 register struct atp_trans
*trp
;
1906 char bds
[atpBDSsize
];
1908 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1911 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1912 || (atp
->atp_flags
& ATP_CLOSING
)) {
1913 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
1914 (u_int
) gref
, gref
->pid
));
1920 ATDISABLE(s
, atp
->atp_lock
);
1921 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1922 dPrintf(D_M_ATP
, D_L_INFO
,
1923 ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
1924 (u_int
) atp
, (u_int
) trp
, trp
->tr_state
));
1926 switch (trp
->tr_state
) {
1928 ATENABLE(s
, atp
->atp_lock
);
1929 if ((*err
= copyin(CAST_USER_ADDR_T(bdsp
),
1930 (caddr_t
)bds
, sizeof(bds
))) != 0) {
1935 if ((*err
= atp_pack_bdsp(trp
, (struct atpBDS
*)bds
)) != 0) {
1940 tid
= (int)trp
->tr_tid
;
1942 if ((*err
= copyout((caddr_t
)bds
, CAST_USER_ADDR_T(bdsp
), sizeof(bds
))) != 0) {
1951 * transaction timed out, return error
1953 ATENABLE(s
, atp
->atp_lock
);
1963 ATENABLE(s
, atp
->atp_lock
);
1971 atp_drop_req(gref
, m
)
1976 struct atp_state
*atp
;
1977 struct atp_rcb
*rcbp
;
1981 atp
= (struct atp_state
*)gref
->info
;
1983 atp
= (struct atp_state
*)atp
->atp_msgq
;
1984 ddp
= AT_DDP_HDR(m
);
1985 athp
= AT_ATP_HDR(m
);
1988 * search for the corresponding rcb
1990 ATDISABLE(s
, atp
->atp_lock
);
1991 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1992 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1993 (rcbp
->rc_socket
.node
== ddp
->src_node
) &&
1994 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->src_net
)) &&
1995 (rcbp
->rc_socket
.socket
== ddp
->src_socket
) )
2004 ATENABLE(s
, atp
->atp_lock
);