2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1996-1998 Apple Computer, Inc.
27 * All Rights Reserved.
30 /* Modified for MP, 1996 by Tuyen Nguyen
31 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
35 #include <sys/errno.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <machine/spl.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
42 #include <sys/filedesc.h>
43 #include <sys/fcntl.h>
45 #include <sys/ioctl.h>
46 #include <sys/malloc.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
52 #include <netat/sysglue.h>
53 #include <netat/appletalk.h>
54 #include <netat/ddp.h>
55 #include <netat/at_pcb.h>
56 #include <netat/atp.h>
57 #include <netat/at_var.h>
58 #include <netat/asp.h>
59 #include <netat/at_pat.h>
60 #include <netat/debug.h>
62 static int loop_cnt
; /* for debugging loops */
63 #define CHK_LOOP(str) { \
64 if (loop_cnt++ > 100) { \
70 static void atp_pack_bdsp(struct atp_trans
*, struct atpBDS
*);
71 static int atp_unpack_bdsp(struct atp_state
*, gbuf_t
*, struct atp_rcb
*,
73 void atp_retry_req(), atp_trp_clock(), asp_clock(), asp_clock_funnel(), atp_trp_clock_funnel();;
75 extern struct atp_rcb_qhead atp_need_rel
;
76 extern int atp_inited
;
77 extern struct atp_state
*atp_used_list
;
78 extern asp_scb_t
*scb_free_list
;
79 extern atlock_t atpgen_lock
;
80 extern atlock_t atpall_lock
;
81 extern atlock_t atptmo_lock
;
83 extern gbuf_t
*scb_resource_m
;
84 extern gbuf_t
*atp_resource_m
;
85 extern gref_t
*atp_inputQ
[];
86 extern int atp_pidM
[];
87 extern at_ifaddr_t
*ifID_home
;
89 static struct atp_trans
*trp_tmo_list
;
90 struct atp_trans
*trp_tmo_rcb
;
92 /* first bds entry gives number of bds entries in total (hack) */
93 #define get_bds_entries(m) \
94 ((gbuf_len(m) > TOTAL_ATP_HDR_SIZE)? \
95 (UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz)): 0)
97 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
102 trp_tmo_rcb
= atp_trans_alloc(0);
103 atp_timout(atp_rcb_timer
, trp_tmo_rcb
, 10 * HZ
);
104 atp_trp_clock((void *)&atp_inited
);
105 asp_clock((void *)&atp_inited
);
110 untimeout(asp_clock_funnel
, (void *)&atp_inited
);
111 untimeout(atp_trp_clock_funnel
, (void *)&atp_inited
);
112 atp_untimout(atp_rcb_timer
, trp_tmo_rcb
);
116 /* allocated in asp_scb_alloc(), which is called
118 if (scb_resource_m
) {
119 gbuf_freem(scb_resource_m
);
123 /* allocated in atp_trans_alloc() */
124 if (atp_resource_m
) {
125 gbuf_freem(atp_resource_m
);
127 atp_trans_free_list
= 0;
133 * write queue put routine .... filter out other than IOCTLs
134 * Version 1.8 of atp_write.c on 89/02/09 17:53:26
139 register gref_t
*gref
;
142 register ioc_t
*iocbp
;
144 struct atp_state
*atp
;
145 struct atp_trans
*trp
;
146 struct atp_rcb
*rcbp
;
149 atp
= (struct atp_state
*)gref
->info
;
151 atp
= (struct atp_state
*)atp
->atp_msgq
;
153 switch(gbuf_type(m
)) {
157 dPrintf(D_M_ATP
, D_L_WARNING
,
158 ("atp_wput: atp_msgq discarded\n"));
164 /* Need to ensure that all copyin/copyout calls are made at
165 * put routine time which should be in the user context. (true when
166 * we are the stream head). The service routine can be called on an
167 * unpredictable context and copyin/copyout calls will get wrong results
168 * or even panic the kernel.
170 iocbp
= (ioc_t
*)gbuf_rptr(m
);
172 switch (iocbp
->ioc_cmd
) {
173 case AT_ATP_BIND_REQ
:
174 if (gbuf_cont(m
) == NULL
) {
175 iocbp
->ioc_rval
= -1;
176 atp_iocnak(atp
, m
, EINVAL
);
179 skt
= *(at_socket
*)gbuf_rptr(gbuf_cont(m
));
180 if ((skt
= (at_socket
)atp_bind(gref
, (unsigned int)skt
, 0)) == 0)
181 atp_iocnak(atp
, m
, EINVAL
);
183 *(at_socket
*)gbuf_rptr(gbuf_cont(m
)) = skt
;
186 atp_dequeue_atp(atp
);
190 case AT_ATP_GET_CHANID
:
191 if (gbuf_cont(m
) == NULL
) {
192 iocbp
->ioc_rval
= -1;
193 atp_iocnak(atp
, m
, EINVAL
);
196 *(gref_t
**)gbuf_rptr(gbuf_cont(m
)) = gref
;
200 /* not the close and not the tickle(?) */
201 case AT_ATP_ISSUE_REQUEST_DEF
:
202 case AT_ATP_ISSUE_REQUEST_DEF_NOTE
: {
203 gbuf_t
*bds
, *tmp
, *m2
;
204 struct atp_rcb
*rcbp
;
208 if ((tmp
= gbuf_cont(m
)) != 0) {
209 if ((bds
= gbuf_dupb(tmp
)) == NULL
) {
210 atp_iocnak(atp
, m
, ENOBUFS
);
213 gbuf_rinc(tmp
,atpBDSsize
);
214 gbuf_wset(bds
,atpBDSsize
);
215 iocbp
->ioc_count
-= atpBDSsize
;
216 gbuf_cont(tmp
) = bds
;
220 * send a response to a transaction
223 if (iocbp
->ioc_count
< TOTAL_ATP_HDR_SIZE
) {
224 atp_iocnak(atp
, m
, EINVAL
);
229 * remove the response from the message
233 iocbp
->ioc_count
= 0;
234 ddp
= AT_DDP_HDR(m2
);
235 athp
= AT_ATP_HDR(m2
);
237 gbuf_cont(m2
) = atp
->atp_msgq
;
241 ATDISABLE(s
, atp
->atp_lock
);
243 * search for the corresponding rcb
245 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
246 if (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
) &&
247 rcbp
->rc_socket
.node
== ddp
->dst_node
&&
248 rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
) &&
249 rcbp
->rc_socket
.socket
== ddp
->dst_socket
)
252 ATENABLE(s
, atp
->atp_lock
);
255 * If it has already been sent then return an error
257 if ((rcbp
&& rcbp
->rc_state
!= RCB_NOTIFIED
) ||
258 (rcbp
== NULL
&& athp
->xo
)) {
259 atp_iocnak(atp
, m
, ENOENT
);
263 if (rcbp
== NULL
) { /* a response for an ALO transaction */
264 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
265 atp_iocnak(atp
, m
, ENOBUFS
);
270 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
271 rcbp
->rc_socket
.node
= ddp
->dst_node
;
272 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
273 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
274 rcbp
->rc_bitmap
= 0xff;
276 ATDISABLE(s
, atp
->atp_lock
);
277 rcbp
->rc_state
= RCB_SENDING
;
278 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
279 ATENABLE(s
, atp
->atp_lock
);
281 xcnt
= get_bds_entries(m2
);
282 if ((i
= atp_unpack_bdsp(atp
, m2
, rcbp
, xcnt
, FALSE
))) {
285 atp_iocnak(atp
, m
, i
);
288 atp_send_replies(atp
, rcbp
);
291 * send the ack back to the responder
297 case AT_ATP_GET_POLL
: {
299 gbuf_freem(gbuf_cont(m
));
301 iocbp
->ioc_count
= 0;
305 * search for a waiting request
307 ATDISABLE(s
, atp
->atp_lock
);
308 if ((rcbp
= atp
->atp_attached
.head
)) {
310 * Got one, move it to the active response Q
312 gbuf_cont(m
) = rcbp
->rc_ioctl
;
313 rcbp
->rc_ioctl
= NULL
;
315 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
316 rcbp
->rc_state
= RCB_NOTIFIED
;
317 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
319 /* detach rcbp from attached queue,
320 * and free any outstanding resources
324 ATENABLE(s
, atp
->atp_lock
);
328 * None available - can out
330 ATENABLE(s
, atp
->atp_lock
);
331 atp_iocnak(atp
, m
, EAGAIN
);
336 case AT_ATP_CANCEL_REQUEST
: {
338 * Cancel a pending request
340 if (iocbp
->ioc_count
!= sizeof(int)) {
341 atp_iocnak(atp
, m
, EINVAL
);
344 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
345 gbuf_freem(gbuf_cont(m
));
347 ATDISABLE(s
, atp
->atp_lock
);
348 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
349 if (trp
->tr_tid
== i
)
353 ATENABLE(s
, atp
->atp_lock
);
354 atp_iocnak(atp
, m
, ENOENT
);
356 ATENABLE(s
, atp
->atp_lock
);
365 if (atalk_peek(gref
, &event
) == -1)
366 atp_iocnak(atp
, m
, EAGAIN
);
368 *gbuf_rptr(gbuf_cont(m
)) = event
;
374 case DDP_IOC_GET_CFG
:
375 #ifdef APPLETALK_DEBUG
376 kprintf("atp_wput: DDP_IOC_GET_CFG\n");
378 if (gbuf_cont(m
) == 0) {
379 atp_iocnak(atp
, m
, EINVAL
);
383 /* *** was ddp_get_cfg() *** */
385 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(m
));
386 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
387 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
388 cfgp
->inet
.socket
= atp
->atp_socket_no
;
389 cfgp
->ddptype
= DDP_ATP
;
391 cfgp
->inet
.net
= atp
->atp_gref
->laddr
.s_net
;
392 cfgp
->inet
.node
= atp
->atp_gref
->laddr
.s_node
;
393 cfgp
->inet
.socket
= atp
->atp_gref
->lport
;
394 cfgp
->ddptype
= atp
->atp_gref
->ddptype
;
397 gbuf_wset(gbuf_cont(m
), sizeof(ddp_addr_t
));
403 * Otherwise pass it on, if possible
405 iocbp
->ioc_private
= (void *)gref
;
417 gbuf_t
*atp_build_release(trp
)
418 register struct atp_trans
*trp
;
421 register at_ddp_t
*ddp
;
422 register at_atp_t
*athp
;
425 * Now try and allocate enough space to send the message
426 * if none is available the caller will schedule
427 * a timeout so we can retry for more space soon
429 if ((m
= (gbuf_t
*)gbuf_alloc(AT_WR_OFFSET
+ATP_HDR_SIZE
, PRI_HI
)) != NULL
) {
430 gbuf_rinc(m
,AT_WR_OFFSET
);
431 gbuf_wset(m
,TOTAL_ATP_HDR_SIZE
);
434 UAS_ASSIGN(ddp
->checksum
, 0);
435 ddp
->dst_socket
= trp
->tr_socket
.socket
;
436 ddp
->dst_node
= trp
->tr_socket
.node
;
437 NET_ASSIGN(ddp
->dst_net
, trp
->tr_socket
.net
);
438 ddp
->src_node
= trp
->tr_local_node
;
439 NET_NET(ddp
->src_net
, trp
->tr_local_net
);
442 * clear the cmd/xo/eom/sts/unused fields
444 athp
= AT_ATP_HDR(m
);
445 ATP_CLEAR_CONTROL(athp
);
446 athp
->cmd
= ATP_CMD_TREL
;
447 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
453 void atp_send_replies(atp
, rcbp
)
454 register struct atp_state
*atp
;
455 register struct atp_rcb
*rcbp
;
456 { register gbuf_t
*m
;
459 unsigned char *m0_rptr
= NULL
, *m0_wptr
= NULL
;
460 register at_atp_t
*athp
;
461 register struct atpBDS
*bdsp
;
462 register gbuf_t
*m2
, *m1
, *m0
, *m3
;
464 gbuf_t
*mprev
, *mlist
= 0;
465 at_socket src_socket
= (at_socket
)atp
->atp_socket_no
;
466 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
468 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
471 ATDISABLE(s
, atp
->atp_lock
);
472 if (rcbp
->rc_queue
!= atp
) {
473 ATENABLE(s
, atp
->atp_lock
);
476 if (rcbp
->rc_not_sent_bitmap
== 0)
477 goto nothing_to_send
;
479 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
, ("atp_send_replies\n"));
481 * Do this for each message that hasn't been sent
483 cnt
= rcbp
->rc_pktcnt
;
484 for (i
= 0; i
< cnt
; i
++) {
486 if (rcbp
->rc_snd
[i
]) {
488 gbuf_alloc(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,PRI_MED
))
490 for (cnt
= 0; cnt
< i
; cnt
++)
492 gbuf_freeb(rc_xmt
[cnt
]);
493 goto nothing_to_send
;
501 m0_rptr
= gbuf_rptr(m0
);
502 m0_wptr
= gbuf_wptr(m0
);
504 if (gbuf_len(m
) > TOTAL_ATP_HDR_SIZE
)
505 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
509 for (i
= 0; i
< cnt
; i
++) {
510 if (rcbp
->rc_snd
[i
] == 0) {
511 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)))
516 gbuf_rinc(m2
,AT_WR_OFFSET
);
517 gbuf_wset(m2
,TOTAL_ATP_HDR_SIZE
);
518 *(struct ddp_atp
*)(gbuf_rptr(m2
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
519 athp
= AT_ATP_HDR(m2
);
520 ATP_CLEAR_CONTROL(athp
);
521 athp
->cmd
= ATP_CMD_TRESP
;
524 athp
->eom
= 1; /* for the last fragment */
526 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
529 if (len
= UAS_VALUE(bdsp
->bdsBuffSz
)) { /* copy in data */
530 if (m0
&& gbuf_len(m0
)) {
531 if ((m1
= gbuf_dupb(m0
)) == NULL
) {
532 for (i
= 0; i
< cnt
; i
++)
534 gbuf_freem(rc_xmt
[i
]);
535 gbuf_rptr(m0
) = m0_rptr
;
536 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
537 goto nothing_to_send
;
541 if ((len
= gbuf_len(m0
)) < 0) {
544 if (!append_copy((struct mbuf
*)m1
,
545 (struct mbuf
*)gbuf_cont(m0
), FALSE
)) {
546 for (i
= 0; i
< cnt
; i
++)
548 gbuf_freem(rc_xmt
[i
]);
549 gbuf_rptr(m0
) = m0_rptr
;
550 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
551 goto nothing_to_send
;
557 /* temp fix for page boundary problem - bug# 2703163 */
558 lastPage
= (caddr_t
)((int)(gbuf_wptr(m1
) - 1) & ~PAGE_MASK
); /* 4k page of last byte */
559 if (lastPage
!= (caddr_t
)((int)(gbuf_rptr(m1
)) & ~PAGE_MASK
)) { /* 1st byte and last on same page ? */
560 if ((m3
= gbuf_dupb(m1
)) == NULL
) {
561 for (i
= 0; i
< cnt
; i
++)
563 gbuf_freem(rc_xmt
[i
]);
564 (gbuf_rptr(m0
)) = m0_rptr
;
565 gbuf_wset(m0
, (m0_wptr
- m0_rptr
));
566 goto nothing_to_send
;
568 (gbuf_rptr(m3
)) = lastPage
; /* new mbuf starts at beginning of page */
569 gbuf_wset(m3
, (gbuf_wptr(m1
) - lastPage
)); /* len = remaining data crossing over page boundary */
570 gbuf_wset(m1
, (lastPage
- (gbuf_rptr(m1
)))); /* adjust len of m1 */
571 (gbuf_cont(m1
)) = m3
;
577 AT_DDP_HDR(m2
)->src_socket
= src_socket
;
578 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
,
579 ("atp_send_replies: %d, socket=%d, size=%d\n",
580 i
, atp
->atp_socket_no
, gbuf_msgsize(gbuf_cont(m2
))));
583 gbuf_next(mprev
) = m2
;
589 rcbp
->rc_not_sent_bitmap
&= ~atp_mask
[i
];
590 if (rcbp
->rc_not_sent_bitmap
== 0)
594 * on to the next frag
599 gbuf_rptr(m0
) = m0_rptr
;
600 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
604 ATENABLE(s
, atp
->atp_lock
);
606 ATDISABLE(s
, atp
->atp_lock
);
611 * If all replies from this reply block have been sent then
612 * remove it from the queue and mark it so
614 if (rcbp
->rc_queue
!= atp
) {
615 ATENABLE(s
, atp
->atp_lock
);
618 rcbp
->rc_rep_waiting
= 0;
621 * If we are doing execute once re-set the rcb timeout
622 * each time we send back any part of the response. Note
623 * that this timer is started when an initial request is
624 * received. Each response reprimes the timer. Duplicate
625 * requests do not reprime the timer.
627 * We have sent all of a response so free the
630 if (rcbp
->rc_xo
&& rcbp
->rc_state
!= RCB_RELEASED
) {
631 ATDISABLE(s_gen
, atpgen_lock
);
632 if (rcbp
->rc_timestamp
== 0) {
633 rcbp
->rc_timestamp
= time
.tv_sec
;
634 if (rcbp
->rc_timestamp
== 0)
635 rcbp
->rc_timestamp
= 1;
636 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
638 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
639 ATENABLE(s_gen
, atpgen_lock
);
642 ATENABLE(s
, atp
->atp_lock
);
643 } /* atp_send_replies */
647 atp_pack_bdsp(trp
, bdsp
)
648 register struct atp_trans
*trp
;
649 register struct atpBDS
*bdsp
;
651 register gbuf_t
*m
= NULL
;
652 register int i
, datsize
= 0;
653 struct atpBDS
*bdsbase
= bdsp
;
655 dPrintf(D_M_ATP
, D_L_INFO
, ("atp_pack_bdsp: socket=%d\n",
656 trp
->tr_queue
->atp_socket_no
));
658 for (i
= 0; i
< ATP_TRESP_MAX
; i
++, bdsp
++) {
659 short bufsize
= UAS_VALUE(bdsp
->bdsBuffSz
);
660 long bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
);
662 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
665 /* discard ddp hdr on first packet */
667 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
669 /* this field may contain control information even when
670 no data is present */
671 UAL_UAL(bdsp
->bdsUserData
,
672 (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
673 gbuf_rinc(m
, ATP_HDR_SIZE
);
675 if ((bufsize
!= 0) && (bufaddr
!= 0)) {
676 /* user expects data back */
678 register char *buf
= (char *)bufaddr
;
681 short len
= (short)(gbuf_len(m
));
685 copyout((caddr_t
)gbuf_rptr(m
),
694 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
697 gbuf_freem(trp
->tr_rcv
[i
]);
698 trp
->tr_rcv
[i
] = NULL
;
701 /* report the number of packets */
702 UAS_ASSIGN(((struct atpBDS
*)bdsbase
)->bdsBuffSz
, i
);
704 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
706 } /* atp_pack_bdsp */
710 atp_unpack_bdsp(atp
, m
, rcbp
, cnt
, wait
)
711 struct atp_state
*atp
;
712 gbuf_t
*m
; /* ddp, atp and bdsp gbuf_t */
713 register struct atp_rcb
*rcbp
;
714 register int cnt
, wait
;
716 register struct atpBDS
*bdsp
;
717 register gbuf_t
*m2
, *m1
, *m0
, *m3
;
719 register at_atp_t
*athp
;
720 register int i
, len
, s_gen
;
721 at_socket src_socket
;
723 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
725 gbuf_t
*mprev
, *mlist
= 0;
726 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
727 unsigned char *m0_rptr
, *m0_wptr
;
730 * get the user data structure pointer
732 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
735 * Guard against bogus count argument.
737 if ((unsigned) cnt
> ATP_TRESP_MAX
) {
738 dPrintf(D_M_ATP
, D_L_ERROR
,
739 ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt
));
743 if ((src_socket
= (at_socket
)atp
->atp_socket_no
) == 0xFF) {
744 /* comparison was to -1, however src_socket is a u_char */
751 rcbp
->rc_pktcnt
= cnt
;
752 rcbp
->rc_state
= RCB_SENDING
;
753 rcbp
->rc_not_sent_bitmap
= 0;
757 * special case this to
758 * improve AFP write transactions to the server
761 if ((m2
= gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,
764 gbuf_rinc(m2
,AT_WR_OFFSET
);
765 gbuf_wset(m2
,TOTAL_ATP_HDR_SIZE
);
766 *(struct ddp_atp
*)(gbuf_rptr(m2
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
767 athp
= AT_ATP_HDR(m2
);
768 ATP_CLEAR_CONTROL(athp
);
769 athp
->cmd
= ATP_CMD_TRESP
;
771 athp
->eom
= 1; /* there's only 1 fragment */
773 /* *** why only if cnt > 0? *** */
775 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
777 if (!append_copy((struct mbuf
*)m2
,
778 (struct mbuf
*)m0
, wait
)) {
783 * send the message and mark it as sent
785 AT_DDP_HDR(m2
)->src_socket
= src_socket
;
786 dPrintf(D_M_ATP_LOW
, D_L_INFO
,
787 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
788 0,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(m2
)),cnt
));
793 for (i
= 0; i
< cnt
; i
++) {
794 /* all hdrs, packet data and dst addr storage */
796 gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,
798 for (cnt
= 0; cnt
< i
; cnt
++)
800 gbuf_freeb(rc_xmt
[cnt
]);
805 m0_rptr
= gbuf_rptr(m0
);
806 m0_wptr
= gbuf_wptr(m0
);
809 for (i
= 0; i
< cnt
; i
++) {
811 gbuf_rinc(m2
,AT_WR_OFFSET
);
812 gbuf_wset(m2
,TOTAL_ATP_HDR_SIZE
);
813 *(struct ddp_atp
*)(gbuf_rptr(m2
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
814 athp
= AT_ATP_HDR(m2
);
815 ATP_CLEAR_CONTROL(athp
);
816 athp
->cmd
= ATP_CMD_TRESP
;
819 athp
->eom
= 1; /* for the last fragment */
820 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
822 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
))) { /* copy in data */
823 if (m0
&& gbuf_len(m0
)) {
824 if ((m1
= gbuf_dupb_wait(m0
, wait
)) == NULL
) {
825 for (i
= 0; i
< cnt
; i
++)
827 gbuf_freem(rc_xmt
[i
]);
828 gbuf_rptr(m0
) = m0_rptr
;
829 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
832 gbuf_wset(m1
,len
); /* *** m1 is first len bytes of m0? *** */
834 if ((len
= gbuf_len(m0
)) < 0) {
837 if (!append_copy((struct mbuf
*)m1
,
838 (struct mbuf
*)gbuf_cont(m0
), wait
)) {
839 for (i
= 0; i
< cnt
; i
++)
841 gbuf_freem(rc_xmt
[i
]);
842 gbuf_rptr(m0
) = m0_rptr
;
843 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
850 /* temp fix for page boundary problem - bug# 2703163 */
851 lastPage
= (caddr_t
)((int)(gbuf_wptr(m1
) - 1) & ~PAGE_MASK
); /* 4k page of last byte */
852 if (lastPage
!= (caddr_t
)((int)(gbuf_rptr(m1
)) & ~PAGE_MASK
)) { /* 1st byte and last on same page ? */
853 if ((m3
= gbuf_dupb_wait(m1
, wait
)) == NULL
) {
854 for (i
= 0; i
< cnt
; i
++)
856 gbuf_freem(rc_xmt
[i
]);
857 (gbuf_rptr(m0
)) = m0_rptr
;
858 gbuf_wset(m0
, (m0_wptr
- m0_rptr
));
861 (gbuf_rptr(m3
)) = lastPage
; /* new mbuf starts at beginning of page */
862 gbuf_wset(m3
, (gbuf_wptr(m1
) - lastPage
)); /* len = remaining data crossing over page boundary */
863 gbuf_wset(m1
, (lastPage
- (gbuf_rptr(m1
)))); /* adjust len of m1 */
864 (gbuf_cont(m1
)) = m3
;
870 AT_DDP_HDR(m2
)->src_socket
= src_socket
;
871 dPrintf(D_M_ATP_LOW
,D_L_INFO
,
872 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
873 i
,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(m2
)),cnt
));
875 gbuf_next(mprev
) = m2
;
880 * on to the next frag
885 gbuf_rptr(m0
) = m0_rptr
;
886 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
893 ATDISABLE(s_gen
, atpgen_lock
);
894 if (rcbp
->rc_timestamp
== 0) {
895 if ((rcbp
->rc_timestamp
= time
.tv_sec
) == 0)
896 rcbp
->rc_timestamp
= 1;
897 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
899 ATENABLE(s_gen
, atpgen_lock
);
904 } /* atp_unpack_bdsp */
906 #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6)
907 #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
908 static unsigned int sNext
= 0;
910 int atp_bind(gref
, sVal
, flag
)
915 extern unsigned char asp_inpC
[];
916 extern asp_scb_t
*asp_scbQ
[];
917 unsigned char inpC
, sNextUsed
= 0;
918 unsigned int sMin
, sMax
, sSav
;
919 struct atp_state
*atp
;
922 atp
= (struct atp_state
*)gref
->info
;
924 atp
= (struct atp_state
*)atp
->atp_msgq
;
926 sMax
= ATP_SOCKET_LAST
;
927 sMin
= ATP_SOCKET_FIRST
;
928 ATDISABLE(s
, atpgen_lock
);
929 if (flag
&& (*flag
== 3)) {
938 ((sVal
> sMax
) || (sVal
< 2) || (sVal
== 6) ||
939 (ddp_socket_inuse(sVal
, DDP_ATP
) &&
940 (atp_inputQ
[sVal
] != (gref_t
*)1)))) {
941 ATENABLE(s
, atpgen_lock
);
948 for (sVal
=sMin
; sVal
<= sMax
; sVal
++) {
949 if (!ddp_socket_inuse(sVal
, DDP_ATP
) ||
950 atp_inputQ
[sVal
] == (gref_t
*)1)
952 else if (flag
&& (*flag
== 3) && asp_scbQ
[sVal
]) {
953 if ((asp_scbQ
[sVal
]->dflag
== *flag
)
954 && (asp_inpC
[sVal
] < inpC
) ) {
955 inpC
= asp_inpC
[sVal
];
961 if (flag
&& (*flag
== 3)) {
965 sMin
= ATP_SOCKET_FIRST
+40;
969 *flag
= (unsigned char)sSav
;
971 ATENABLE(s
, atpgen_lock
);
975 atp
->atp_socket_no
= (short)sVal
;
976 atp_inputQ
[sVal
] = gref
;
978 atp_pidM
[sVal
] = atp
->atp_pid
;
979 else if (*flag
== 3) {
981 if (sNext
> ATP_SOCKET_LAST
)
985 ATENABLE(s
, atpgen_lock
);
989 void atp_req_ind(atp
, mioc
)
990 register struct atp_state
*atp
;
991 register gbuf_t
*mioc
;
993 register struct atp_rcb
*rcbp
;
996 if ((rcbp
= atp
->atp_attached
.head
) != 0) {
997 gbuf_cont(mioc
) = rcbp
->rc_ioctl
;
998 rcbp
->rc_ioctl
= NULL
;
999 ATDISABLE(s
, atp
->atp_lock
);
1001 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
1002 rcbp
->rc_state
= RCB_NOTIFIED
;
1003 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1006 ATENABLE(s
, atp
->atp_lock
);
1007 if (gbuf_cont(mioc
))
1008 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
1010 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1011 asp_ack_reply(atp
->atp_gref
, mioc
);
1016 void atp_rsp_ind(trp
, mioc
)
1017 register struct atp_trans
*trp
;
1018 register gbuf_t
*mioc
;
1020 register struct atp_state
*atp
= trp
->tr_queue
;
1026 switch (trp
->tr_state
) {
1028 if (asp_pack_bdsp(trp
, &xm
) < 0)
1030 gbuf_cont(mioc
) = trp
->tr_xmt
;
1045 dPrintf(D_M_ATP
, D_L_ERROR
,
1046 ("atp_rsp_ind: TRANSACTION error\n"));
1047 atp_iocnak(atp
, mioc
, err
);
1049 gbuf_cont(gbuf_cont(mioc
)) = xm
;
1050 atp_iocack(atp
, mioc
);
1055 void atp_cancel_req(gref
, tid
)
1060 struct atp_state
*atp
;
1061 struct atp_trans
*trp
;
1063 atp
= (struct atp_state
*)gref
->info
;
1065 atp
= (struct atp_state
*)atp
->atp_msgq
;
1067 ATDISABLE(s
, atp
->atp_lock
);
1068 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1069 if (trp
->tr_tid
== tid
)
1072 ATENABLE(s
, atp
->atp_lock
);
1078 * remove atp from the use list
1081 atp_dequeue_atp(atp
)
1082 struct atp_state
*atp
;
1086 ATDISABLE(s
, atpall_lock
);
1087 if (atp
== atp_used_list
) {
1088 if ((atp_used_list
= atp
->atp_trans_waiting
) != 0)
1089 atp
->atp_trans_waiting
->atp_rcb_waiting
= 0;
1090 } else if (atp
->atp_rcb_waiting
) {
1091 if ((atp
->atp_rcb_waiting
->atp_trans_waiting
1092 = atp
->atp_trans_waiting
) != 0)
1093 atp
->atp_trans_waiting
->atp_rcb_waiting
= atp
->atp_rcb_waiting
;
1096 atp
->atp_trans_waiting
= 0;
1097 atp
->atp_rcb_waiting
= 0;
1098 ATENABLE(s
, atpall_lock
);
1102 atp_timout(func
, trp
, ticks
)
1104 struct atp_trans
*trp
;
1109 struct atp_trans
*curr_trp
, *prev_trp
;
1111 ATDISABLE(s
, atptmo_lock
);
1112 if (trp
->tr_tmo_func
) {
1113 ATENABLE(s
, atptmo_lock
);
1117 trp
->tr_tmo_func
= func
;
1118 trp
->tr_tmo_delta
= 1+(ticks
>>5);
1120 if (trp_tmo_list
== 0) {
1121 trp
->tr_tmo_next
= trp
->tr_tmo_prev
= 0;
1123 ATENABLE(s
, atptmo_lock
);
1128 curr_trp
= trp_tmo_list
;
1132 sum
+= curr_trp
->tr_tmo_delta
;
1133 if (sum
> trp
->tr_tmo_delta
) {
1134 sum
-= curr_trp
->tr_tmo_delta
;
1135 trp
->tr_tmo_delta
-= sum
;
1136 curr_trp
->tr_tmo_delta
-= trp
->tr_tmo_delta
;
1139 prev_trp
= curr_trp
;
1140 if ((curr_trp
= curr_trp
->tr_tmo_next
) == 0) {
1141 trp
->tr_tmo_delta
-= sum
;
1147 trp
->tr_tmo_prev
= prev_trp
;
1148 if ((trp
->tr_tmo_next
= prev_trp
->tr_tmo_next
) != 0)
1149 prev_trp
->tr_tmo_next
->tr_tmo_prev
= trp
;
1150 prev_trp
->tr_tmo_next
= trp
;
1152 trp
->tr_tmo_prev
= 0;
1153 trp
->tr_tmo_next
= trp_tmo_list
;
1154 trp_tmo_list
->tr_tmo_prev
= trp
;
1157 ATENABLE(s
, atptmo_lock
);
1161 atp_untimout(func
, trp
)
1163 struct atp_trans
*trp
;
1167 ATDISABLE(s
, atptmo_lock
);
1168 if (trp
->tr_tmo_func
== 0) {
1169 ATENABLE(s
, atptmo_lock
);
1173 if (trp_tmo_list
== trp
) {
1174 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0) {
1175 trp_tmo_list
->tr_tmo_prev
= 0;
1176 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1179 if ((trp
->tr_tmo_prev
->tr_tmo_next
= trp
->tr_tmo_next
) != 0) {
1180 trp
->tr_tmo_next
->tr_tmo_prev
= trp
->tr_tmo_prev
;
1181 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1184 trp
->tr_tmo_func
= 0;
1185 ATENABLE(s
, atptmo_lock
);
1189 atp_trp_clock_funnel(arg
)
1192 thread_funnel_set(network_flock
, TRUE
);
1194 thread_funnel_set(network_flock
, FALSE
);
1202 struct atp_trans
*trp
;
1203 void (*tr_tmo_func
)();
1205 ATDISABLE(s
, atptmo_lock
);
1207 trp_tmo_list
->tr_tmo_delta
--;
1208 while (((trp
= trp_tmo_list
) != 0) && (trp_tmo_list
->tr_tmo_delta
== 0)) {
1209 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0)
1210 trp_tmo_list
->tr_tmo_prev
= 0;
1211 if ((tr_tmo_func
= trp
->tr_tmo_func
) != 0) {
1212 trp
->tr_tmo_func
= 0;
1213 ATENABLE(s
, atptmo_lock
);
1214 (*tr_tmo_func
)(trp
);
1215 ATDISABLE(s
, atptmo_lock
);
1218 ATENABLE(s
, atptmo_lock
);
1220 timeout(atp_trp_clock_funnel
, (void *)arg
, (1<<5));
1224 atp_send_req(gref
, mioc
)
1228 register struct atp_state
*atp
;
1229 register struct atp_trans
*trp
;
1230 register ioc_t
*iocbp
;
1231 register at_atp_t
*athp
;
1232 register at_ddp_t
*ddp
;
1233 gbuf_t
*m
, *m2
, *bds
;
1234 struct atp_set_default
*sdb
;
1238 atp
= (struct atp_state
*)((struct atp_state
*)gref
->info
)->atp_msgq
;
1239 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1241 if ((trp
= atp_trans_alloc(atp
)) == NULL
) {
1243 ((asp_scb_t
*)gref
->info
)->stat_msg
= mioc
;
1244 iocbp
->ioc_private
= (void *)gref
;
1245 timeout(atp_retry_req
, mioc
, 10);
1249 m2
= gbuf_cont(mioc
);
1250 if ((bds
= gbuf_dupb(m2
)) == NULL
) {
1251 atp_trans_free(trp
);
1254 gbuf_rinc(m2
,atpBDSsize
);
1255 gbuf_wset(bds
,atpBDSsize
);
1256 iocbp
->ioc_count
-= atpBDSsize
;
1257 gbuf_cont(m2
) = NULL
;
1259 old
= iocbp
->ioc_cmd
;
1260 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
1261 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1264 * The at_snd_req library routine multiplies seconds by 100.
1265 * We need to divide by 100 in order to obtain the timer.
1267 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1269 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1270 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1272 trp
->tr_retry
= sdb
->def_retries
;
1273 trp
->tr_timeout
= timer
;
1275 trp
->tr_tid
= atp_tid(atp
);
1279 * Now fill in the header (and remember the bits
1282 athp
= AT_ATP_HDR(m2
);
1283 athp
->cmd
= ATP_CMD_TREQ
;
1284 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1287 trp
->tr_xo
= athp
->xo
;
1288 trp
->tr_bitmap
= athp
->bitmap
;
1289 ddp
= AT_DDP_HDR(m2
);
1290 ddp
->type
= DDP_ATP
;
1291 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1292 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1293 trp
->tr_socket
.node
= ddp
->dst_node
;
1294 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1295 trp
->tr_local_socket
= atp
->atp_socket_no
;
1296 trp
->tr_local_node
= ddp
->src_node
;
1297 NET_NET(trp
->tr_local_net
, ddp
->src_net
);
1300 /* save the local information in the gref */
1301 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1302 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1303 atp
->atp_gref
->lport
= ddp
->src_node
;
1304 atp
->atp_gref
->ddptype
= DDP_ATP
;
1308 * Put us in the transaction waiting queue
1310 ATDISABLE(s
, atp
->atp_lock
);
1311 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1312 ATENABLE(s
, atp
->atp_lock
);
1315 * Send the message and set the timer
1317 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1318 if (!trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1319 atp_x_done(trp
); /* no reason to tie up resources */
1321 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1323 trace_mbufs(D_M_ATP_LOW
, " s", m
);
1326 } /* atp_send_req */
1328 void atp_retry_req(m
)
1332 boolean_t funnel_state
;
1334 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1336 gref
= (gref_t
*)((ioc_t
*)gbuf_rptr(m
))->ioc_private
;
1338 ((asp_scb_t
*)gref
->info
)->stat_msg
= 0;
1339 atp_send_req(gref
, m
);
1341 (void) thread_funnel_set(network_flock
, FALSE
);
1344 void atp_send_rsp(gref
, m
, wait
)
1349 register struct atp_state
*atp
;
1350 register struct atp_rcb
*rcbp
;
1351 register at_atp_t
*athp
;
1352 register at_ddp_t
*ddp
;
1355 atp
= (struct atp_state
*)gref
->info
;
1357 atp
= (struct atp_state
*)atp
->atp_msgq
;
1358 ddp
= AT_DDP_HDR(m
);
1359 athp
= AT_ATP_HDR(m
);
1362 * search for the corresponding rcb
1364 ATDISABLE(s
, atp
->atp_lock
);
1365 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1366 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1367 (rcbp
->rc_socket
.node
== ddp
->dst_node
) &&
1368 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
)) &&
1369 (rcbp
->rc_socket
.socket
== ddp
->dst_socket
) )
1374 * If it has already been sent then drop the request
1376 if ((rcbp
&& (rcbp
->rc_state
!= RCB_NOTIFIED
)) ||
1377 (rcbp
== NULL
&& athp
->xo
) ) {
1378 ATENABLE(s
, atp
->atp_lock
);
1382 ATENABLE(s
, atp
->atp_lock
);
1384 if (rcbp
== NULL
) { /* a response is being sent for an ALO transaction */
1385 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
1390 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
1391 rcbp
->rc_socket
.node
= ddp
->dst_node
;
1392 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
1393 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
1394 rcbp
->rc_bitmap
= 0xff;
1396 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
1397 ATDISABLE(s
, atp
->atp_lock
);
1398 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1399 ATENABLE(s
, atp
->atp_lock
);
1401 else if (ddp
->src_node
== 0) {
1402 NET_NET(ddp
->src_net
, rcbp
->rc_local_net
);
1403 ddp
->src_node
= rcbp
->rc_local_node
;
1406 xcnt
= get_bds_entries(m
);
1407 s
= atp_unpack_bdsp(atp
, m
, rcbp
, xcnt
, wait
);
1409 atp_send_replies(atp
, rcbp
);
1410 } /* atp_send_rsp */
1412 int asp_pack_bdsp(trp
, xm
)
1413 register struct atp_trans
*trp
;
1416 register struct atpBDS
*bdsp
;
1417 register gbuf_t
*m
, *m2
;
1419 gbuf_t
*m_prev
, *m_head
= 0;
1421 dPrintf(D_M_ATP
, D_L_INFO
, ("asp_pack_bdsp: socket=%d\n",
1422 trp
->tr_queue
->atp_socket_no
));
1424 if ((m2
= trp
->tr_bdsp
) == NULL
)
1426 trp
->tr_bdsp
= NULL
;
1427 bdsp
= (struct atpBDS
*)gbuf_rptr(m2
);
1429 for (i
= 0; (i
< ATP_TRESP_MAX
&&
1430 bdsp
< (struct atpBDS
*)(gbuf_wptr(m2
))); i
++) {
1431 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
1434 /* discard ddp hdr on first packet */
1435 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
1438 UAL_UAL(bdsp
->bdsUserData
, (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
1439 gbuf_rinc(m
, ATP_HDR_SIZE
);
1441 if (UAL_VALUE(bdsp
->bdsBuffAddr
)) {
1444 /* user expects data back */
1449 gbuf_cont(m_prev
) = m
;
1451 tmp
= (short)gbuf_len(m
);
1452 while (gbuf_cont(m
)) {
1454 tmp
+= (short)(gbuf_len(m
));
1458 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
1460 trp
->tr_rcv
[i
] = NULL
;
1465 * report the number of packets
1467 UAS_ASSIGN(((struct atpBDS
*)gbuf_rptr(m2
))->bdsBuffSz
, i
);
1469 if (trp
->tr_xmt
) /* an ioctl block is still held? */
1470 gbuf_cont(trp
->tr_xmt
) = m2
;
1479 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
1480 gbuf_msgsize(*xm
)));
1486 * The following routines are direct entries from system
1487 * calls to allow fast sending and recving of ATP data.
1491 _ATPsndreq(fd
, buf
, len
, nowait
, err
, proc
)
1503 register struct atp_state
*atp
;
1504 register struct atp_trans
*trp
;
1505 register ioc_t
*iocbp
;
1506 register at_atp_t
*athp
;
1507 register at_ddp_t
*ddp
;
1508 struct atp_set_default
*sdb
;
1509 gbuf_t
*m2
, *m
, *mioc
;
1510 char bds
[atpBDSsize
];
1512 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 0)
1515 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1516 || (atp
->atp_flags
& ATP_CLOSING
)) {
1517 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
1518 (u_int
) gref
, gref
->pid
));
1524 while ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_MED
)) == 0) {
1525 ATDISABLE(s
, atp
->atp_delay_lock
);
1526 rc
= tsleep(&atp
->atp_delay_event
, PSOCK
| PCATCH
, "atpmioc", 10);
1527 ATENABLE(s
, atp
->atp_delay_lock
);
1534 gbuf_wset(mioc
,sizeof(ioc_t
));
1536 while ((m2
= gbuf_alloc(len
, PRI_MED
)) == 0) {
1537 ATDISABLE(s
, atp
->atp_delay_lock
);
1538 rc
= tsleep(&atp
->atp_delay_event
, PSOCK
| PCATCH
, "atpm2", 10);
1539 ATENABLE(s
, atp
->atp_delay_lock
);
1547 gbuf_cont(mioc
) = m2
;
1548 if (((*err
= copyin((caddr_t
)buf
, (caddr_t
)bds
, atpBDSsize
)) != 0)
1549 || ((*err
= copyin((caddr_t
)&buf
[atpBDSsize
],
1550 (caddr_t
)gbuf_rptr(m2
), len
)) != 0)) {
1554 gbuf_set_type(mioc
, MSG_IOCTL
);
1555 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1556 iocbp
->ioc_count
= len
;
1557 iocbp
->ioc_cmd
= nowait
? AT_ATP_ISSUE_REQUEST_NOTE
: AT_ATP_ISSUE_REQUEST
;
1558 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1561 * The at_snd_req library routine multiplies seconds by 100.
1562 * We need to divide by 100 in order to obtain the timer.
1564 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1566 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1567 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1570 * allocate and set up the transaction record
1572 while ((trp
= atp_trans_alloc(atp
)) == 0) {
1573 ATDISABLE(s
, atp
->atp_delay_lock
);
1574 rc
= tsleep(&atp
->atp_delay_event
, PSOCK
| PCATCH
, "atptrp", 10);
1575 ATENABLE(s
, atp
->atp_delay_lock
);
1582 trp
->tr_retry
= sdb
->def_retries
;
1583 trp
->tr_timeout
= timer
;
1584 trp
->tr_bdsp
= NULL
;
1585 trp
->tr_tid
= atp_tid(atp
);
1589 * remember the IOCTL packet so we can ack it
1595 * Now fill in the header (and remember the bits
1598 athp
= AT_ATP_HDR(m2
);
1599 athp
->cmd
= ATP_CMD_TREQ
;
1600 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1603 trp
->tr_xo
= athp
->xo
;
1604 trp
->tr_bitmap
= athp
->bitmap
;
1605 ddp
= AT_DDP_HDR(m2
);
1606 ddp
->type
= DDP_ATP
;
1607 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1609 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1610 trp
->tr_socket
.node
= ddp
->dst_node
;
1611 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1612 trp
->tr_local_socket
= atp
->atp_socket_no
;
1615 /* save the local information in the gref */
1616 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1617 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1618 atp
->atp_gref
->lport
= ddp
->src_node
;
1619 atp
->atp_gref
->ddptype
= DDP_ATP
;
1623 * Put us in the transaction waiting queue
1625 ATDISABLE(s
, atp
->atp_lock
);
1626 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1627 ATENABLE(s
, atp
->atp_lock
);
1630 * Send the message and set the timer
1632 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1633 if ( !trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1634 atp_x_done(trp
); /* no reason to tie up resources */
1636 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1644 * wait for the transaction to complete
1646 ATDISABLE(s
, trp
->tr_lock
);
1647 while ((trp
->tr_state
!= TRANS_DONE
) && (trp
->tr_state
!= TRANS_FAILED
) &&
1648 (trp
->tr_state
!= TRANS_ABORTING
)) {
1649 trp
->tr_rsp_wait
= 1;
1650 rc
= tsleep(&trp
->tr_event
, PSOCK
| PCATCH
, "atpsndreq", 0);
1652 trp
->tr_rsp_wait
= 0;
1653 ATENABLE(s
, trp
->tr_lock
);
1658 trp
->tr_rsp_wait
= 0;
1659 ATENABLE(s
, trp
->tr_lock
);
1662 if (trp
->tr_state
== TRANS_FAILED
|| trp
->tr_state
== TRANS_ABORTING
) {
1664 * transaction timed out, return error
1672 * copy out the recv data
1674 atp_pack_bdsp(trp
, bds
);
1677 * copyout the result info
1679 copyout((caddr_t
)bds
, (caddr_t
)buf
, atpBDSsize
);
1687 _ATPsndrsp(fd
, respbuff
, resplen
, datalen
, err
, proc
)
1689 unsigned char *respbuff
;
1701 register struct atp_state
*atp
;
1702 register struct atpBDS
*bdsp
;
1705 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 0)
1708 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1709 || (atp
->atp_flags
& ATP_CLOSING
)) {
1710 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
1711 (u_int
) gref
, gref
->pid
));
1718 * allocate buffer and copy in the response info
1720 if ((m
= gbuf_alloc_wait(resplen
, TRUE
)) == 0) {
1724 if ((*err
= copyin((caddr_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
);
1731 if ((resplen
== TOTAL_ATP_HDR_SIZE
) || ((len
= UAS_VALUE(bdsp
->bdsDataSz
)) == 1))
1734 len
= 16 * sizeof(gbuf_t
);
1737 * allocate buffer and copy in the response data
1739 if ((mdata
= gbuf_alloc_wait(datalen
+len
, TRUE
)) == 0) {
1744 gbuf_cont(m
) = mdata
;
1745 for (size
=0; bdsp
< (struct atpBDS
*)gbuf_wptr(m
); bdsp
++) {
1746 if ((bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
)) != 0) {
1747 len
= UAS_VALUE(bdsp
->bdsBuffSz
);
1748 buf
= (char *)bufaddr
;
1749 if ((*err
= copyin((caddr_t
)buf
,
1750 (caddr_t
)&gbuf_rptr(mdata
)[size
], len
)) != 0) {
1757 gbuf_wset(mdata
,size
);
1759 atp_send_rsp(gref
, m
, TRUE
);
1764 _ATPgetreq(fd
, buf
, buflen
, err
, proc
)
1772 register struct atp_state
*atp
;
1773 register struct atp_rcb
*rcbp
;
1774 register gbuf_t
*m
, *m_head
;
1777 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 0)
1780 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1781 || (atp
->atp_flags
& ATP_CLOSING
)) {
1782 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
1783 (u_int
) gref
, gref
->pid
));
1788 ATDISABLE(s
, atp
->atp_lock
);
1789 if ((rcbp
= atp
->atp_attached
.head
) != NULL
) {
1791 * Got one, move it to the active response Q
1793 m_head
= rcbp
->rc_ioctl
;
1794 rcbp
->rc_ioctl
= NULL
;
1797 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
1798 rcbp
->rc_state
= RCB_NOTIFIED
;
1799 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1801 /* detach rcbp from attached queue,
1802 * and free any outstanding resources
1806 ATENABLE(s
, atp
->atp_lock
);
1809 * copyout the request data, including the protocol header
1811 for (size
=0, m
=m_head
; m
; m
= gbuf_cont(m
)) {
1812 if ((len
= gbuf_len(m
)) > buflen
)
1814 copyout((caddr_t
)gbuf_rptr(m
), (caddr_t
)&buf
[size
], len
);
1816 if ((buflen
-= len
) == 0)
1823 ATENABLE(s
, atp
->atp_lock
);
1829 _ATPgetrsp(fd
, bdsp
, err
, proc
)
1831 struct atpBDS
*bdsp
;
1836 register struct atp_state
*atp
;
1837 register struct atp_trans
*trp
;
1839 char bds
[atpBDSsize
];
1841 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 0)
1844 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1845 || (atp
->atp_flags
& ATP_CLOSING
)) {
1846 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
1847 (u_int
) gref
, gref
->pid
));
1852 ATDISABLE(s
, atp
->atp_lock
);
1853 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1854 dPrintf(D_M_ATP
, D_L_INFO
,
1855 ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
1856 (u_int
) atp
, (u_int
) trp
, trp
->tr_state
));
1858 switch (trp
->tr_state
) {
1860 ATENABLE(s
, atp
->atp_lock
);
1861 if ((*err
= copyin((caddr_t
)bdsp
,
1862 (caddr_t
)bds
, sizeof(bds
))) != 0)
1864 atp_pack_bdsp(trp
, bds
);
1865 tid
= (int)trp
->tr_tid
;
1867 copyout((caddr_t
)bds
, (caddr_t
)bdsp
, sizeof(bds
));
1872 * transaction timed out, return error
1874 ATENABLE(s
, atp
->atp_lock
);
1883 ATENABLE(s
, atp
->atp_lock
);
1890 atp_drop_req(gref
, m
)
1895 struct atp_state
*atp
;
1896 struct atp_rcb
*rcbp
;
1900 atp
= (struct atp_state
*)gref
->info
;
1902 atp
= (struct atp_state
*)atp
->atp_msgq
;
1903 ddp
= AT_DDP_HDR(m
);
1904 athp
= AT_ATP_HDR(m
);
1907 * search for the corresponding rcb
1909 ATDISABLE(s
, atp
->atp_lock
);
1910 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1911 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1912 (rcbp
->rc_socket
.node
== ddp
->src_node
) &&
1913 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->src_net
)) &&
1914 (rcbp
->rc_socket
.socket
== ddp
->src_socket
) )
1923 ATENABLE(s
, atp
->atp_lock
);