2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1996-1998 Apple Computer, Inc.
24 * All Rights Reserved.
27 /* Modified for MP, 1996 by Tuyen Nguyen
28 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
32 #include <sys/errno.h>
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <machine/spl.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
39 #include <sys/filedesc.h>
40 #include <sys/fcntl.h>
42 #include <sys/ioctl.h>
43 #include <sys/malloc.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
49 #include <netat/sysglue.h>
50 #include <netat/appletalk.h>
51 #include <netat/ddp.h>
52 #include <netat/at_pcb.h>
53 #include <netat/atp.h>
54 #include <netat/at_var.h>
55 #include <netat/asp.h>
56 #include <netat/at_pat.h>
57 #include <netat/debug.h>
59 static int loop_cnt
; /* for debugging loops */
60 #define CHK_LOOP(str) { \
61 if (loop_cnt++ > 100) { \
67 static void atp_pack_bdsp(struct atp_trans
*, struct atpBDS
*);
68 static int atp_unpack_bdsp(struct atp_state
*, gbuf_t
*, struct atp_rcb
*,
70 void atp_retry_req(), atp_trp_clock(), asp_clock(), asp_clock_funnel(), atp_trp_clock_funnel();;
72 extern struct atp_rcb_qhead atp_need_rel
;
73 extern int atp_inited
;
74 extern struct atp_state
*atp_used_list
;
75 extern asp_scb_t
*scb_free_list
;
76 extern atlock_t atpgen_lock
;
77 extern atlock_t atpall_lock
;
78 extern atlock_t atptmo_lock
;
80 extern gbuf_t
*scb_resource_m
;
81 extern gbuf_t
*atp_resource_m
;
82 extern gref_t
*atp_inputQ
[];
83 extern int atp_pidM
[];
84 extern at_ifaddr_t
*ifID_home
;
86 static struct atp_trans
*trp_tmo_list
;
87 struct atp_trans
*trp_tmo_rcb
;
89 /* first bds entry gives number of bds entries in total (hack) */
90 #define get_bds_entries(m) \
91 ((gbuf_len(m) > TOTAL_ATP_HDR_SIZE)? \
92 (UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz)): 0)
94 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
99 trp_tmo_rcb
= atp_trans_alloc(0);
100 atp_timout(atp_rcb_timer
, trp_tmo_rcb
, 10 * HZ
);
101 atp_trp_clock((void *)&atp_inited
);
102 asp_clock((void *)&atp_inited
);
107 untimeout(asp_clock_funnel
, (void *)&atp_inited
);
108 untimeout(atp_trp_clock_funnel
, (void *)&atp_inited
);
109 atp_untimout(atp_rcb_timer
, trp_tmo_rcb
);
113 /* allocated in asp_scb_alloc(), which is called
115 if (scb_resource_m
) {
116 gbuf_freem(scb_resource_m
);
120 /* allocated in atp_trans_alloc() */
121 if (atp_resource_m
) {
122 gbuf_freem(atp_resource_m
);
124 atp_trans_free_list
= 0;
130 * write queue put routine .... filter out other than IOCTLs
131 * Version 1.8 of atp_write.c on 89/02/09 17:53:26
136 register gref_t
*gref
;
139 register ioc_t
*iocbp
;
141 struct atp_state
*atp
;
142 struct atp_trans
*trp
;
143 struct atp_rcb
*rcbp
;
146 atp
= (struct atp_state
*)gref
->info
;
148 atp
= (struct atp_state
*)atp
->atp_msgq
;
150 switch(gbuf_type(m
)) {
154 dPrintf(D_M_ATP
, D_L_WARNING
,
155 ("atp_wput: atp_msgq discarded\n"));
161 /* Need to ensure that all copyin/copyout calls are made at
162 * put routine time which should be in the user context. (true when
163 * we are the stream head). The service routine can be called on an
164 * unpredictable context and copyin/copyout calls will get wrong results
165 * or even panic the kernel.
167 iocbp
= (ioc_t
*)gbuf_rptr(m
);
169 switch (iocbp
->ioc_cmd
) {
170 case AT_ATP_BIND_REQ
:
171 if (gbuf_cont(m
) == NULL
) {
172 iocbp
->ioc_rval
= -1;
173 atp_iocnak(atp
, m
, EINVAL
);
176 skt
= *(at_socket
*)gbuf_rptr(gbuf_cont(m
));
177 if ((skt
= (at_socket
)atp_bind(gref
, (unsigned int)skt
, 0)) == 0)
178 atp_iocnak(atp
, m
, EINVAL
);
180 *(at_socket
*)gbuf_rptr(gbuf_cont(m
)) = skt
;
183 atp_dequeue_atp(atp
);
187 case AT_ATP_GET_CHANID
:
188 if (gbuf_cont(m
) == NULL
) {
189 iocbp
->ioc_rval
= -1;
190 atp_iocnak(atp
, m
, EINVAL
);
193 *(gref_t
**)gbuf_rptr(gbuf_cont(m
)) = gref
;
197 /* not the close and not the tickle(?) */
198 case AT_ATP_ISSUE_REQUEST_DEF
:
199 case AT_ATP_ISSUE_REQUEST_DEF_NOTE
: {
200 gbuf_t
*bds
, *tmp
, *m2
;
201 struct atp_rcb
*rcbp
;
205 if ((tmp
= gbuf_cont(m
)) != 0) {
206 if ((bds
= gbuf_dupb(tmp
)) == NULL
) {
207 atp_iocnak(atp
, m
, ENOBUFS
);
210 gbuf_rinc(tmp
,atpBDSsize
);
211 gbuf_wset(bds
,atpBDSsize
);
212 iocbp
->ioc_count
-= atpBDSsize
;
213 gbuf_cont(tmp
) = bds
;
217 * send a response to a transaction
220 if (iocbp
->ioc_count
< TOTAL_ATP_HDR_SIZE
) {
221 atp_iocnak(atp
, m
, EINVAL
);
226 * remove the response from the message
230 iocbp
->ioc_count
= 0;
231 ddp
= AT_DDP_HDR(m2
);
232 athp
= AT_ATP_HDR(m2
);
234 gbuf_cont(m2
) = atp
->atp_msgq
;
238 ATDISABLE(s
, atp
->atp_lock
);
240 * search for the corresponding rcb
242 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
243 if (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
) &&
244 rcbp
->rc_socket
.node
== ddp
->dst_node
&&
245 rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
) &&
246 rcbp
->rc_socket
.socket
== ddp
->dst_socket
)
249 ATENABLE(s
, atp
->atp_lock
);
252 * If it has already been sent then return an error
254 if ((rcbp
&& rcbp
->rc_state
!= RCB_NOTIFIED
) ||
255 (rcbp
== NULL
&& athp
->xo
)) {
256 atp_iocnak(atp
, m
, ENOENT
);
260 if (rcbp
== NULL
) { /* a response for an ALO transaction */
261 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
262 atp_iocnak(atp
, m
, ENOBUFS
);
267 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
268 rcbp
->rc_socket
.node
= ddp
->dst_node
;
269 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
270 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
271 rcbp
->rc_bitmap
= 0xff;
273 ATDISABLE(s
, atp
->atp_lock
);
274 rcbp
->rc_state
= RCB_SENDING
;
275 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
276 ATENABLE(s
, atp
->atp_lock
);
278 xcnt
= get_bds_entries(m2
);
279 if ((i
= atp_unpack_bdsp(atp
, m2
, rcbp
, xcnt
, FALSE
))) {
282 atp_iocnak(atp
, m
, i
);
285 atp_send_replies(atp
, rcbp
);
288 * send the ack back to the responder
294 case AT_ATP_GET_POLL
: {
296 gbuf_freem(gbuf_cont(m
));
298 iocbp
->ioc_count
= 0;
302 * search for a waiting request
304 ATDISABLE(s
, atp
->atp_lock
);
305 if ((rcbp
= atp
->atp_attached
.head
)) {
307 * Got one, move it to the active response Q
309 gbuf_cont(m
) = rcbp
->rc_ioctl
;
310 rcbp
->rc_ioctl
= NULL
;
312 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
313 rcbp
->rc_state
= RCB_NOTIFIED
;
314 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
316 /* detach rcbp from attached queue,
317 * and free any outstanding resources
321 ATENABLE(s
, atp
->atp_lock
);
325 * None available - can out
327 ATENABLE(s
, atp
->atp_lock
);
328 atp_iocnak(atp
, m
, EAGAIN
);
333 case AT_ATP_CANCEL_REQUEST
: {
335 * Cancel a pending request
337 if (iocbp
->ioc_count
!= sizeof(int)) {
338 atp_iocnak(atp
, m
, EINVAL
);
341 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
342 gbuf_freem(gbuf_cont(m
));
344 ATDISABLE(s
, atp
->atp_lock
);
345 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
346 if (trp
->tr_tid
== i
)
350 ATENABLE(s
, atp
->atp_lock
);
351 atp_iocnak(atp
, m
, ENOENT
);
353 ATENABLE(s
, atp
->atp_lock
);
362 if (atalk_peek(gref
, &event
) == -1)
363 atp_iocnak(atp
, m
, EAGAIN
);
365 *gbuf_rptr(gbuf_cont(m
)) = event
;
371 case DDP_IOC_GET_CFG
:
372 #ifdef APPLETALK_DEBUG
373 kprintf("atp_wput: DDP_IOC_GET_CFG\n");
375 if (gbuf_cont(m
) == 0) {
376 atp_iocnak(atp
, m
, EINVAL
);
380 /* *** was ddp_get_cfg() *** */
382 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(m
));
383 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
384 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
385 cfgp
->inet
.socket
= atp
->atp_socket_no
;
386 cfgp
->ddptype
= DDP_ATP
;
388 cfgp
->inet
.net
= atp
->atp_gref
->laddr
.s_net
;
389 cfgp
->inet
.node
= atp
->atp_gref
->laddr
.s_node
;
390 cfgp
->inet
.socket
= atp
->atp_gref
->lport
;
391 cfgp
->ddptype
= atp
->atp_gref
->ddptype
;
394 gbuf_wset(gbuf_cont(m
), sizeof(ddp_addr_t
));
400 * Otherwise pass it on, if possible
402 iocbp
->ioc_private
= (void *)gref
;
414 gbuf_t
*atp_build_release(trp
)
415 register struct atp_trans
*trp
;
418 register at_ddp_t
*ddp
;
419 register at_atp_t
*athp
;
422 * Now try and allocate enough space to send the message
423 * if none is available the caller will schedule
424 * a timeout so we can retry for more space soon
426 if ((m
= (gbuf_t
*)gbuf_alloc(AT_WR_OFFSET
+ATP_HDR_SIZE
, PRI_HI
)) != NULL
) {
427 gbuf_rinc(m
,AT_WR_OFFSET
);
428 gbuf_wset(m
,TOTAL_ATP_HDR_SIZE
);
431 UAS_ASSIGN(ddp
->checksum
, 0);
432 ddp
->dst_socket
= trp
->tr_socket
.socket
;
433 ddp
->dst_node
= trp
->tr_socket
.node
;
434 NET_ASSIGN(ddp
->dst_net
, trp
->tr_socket
.net
);
435 ddp
->src_node
= trp
->tr_local_node
;
436 NET_NET(ddp
->src_net
, trp
->tr_local_net
);
439 * clear the cmd/xo/eom/sts/unused fields
441 athp
= AT_ATP_HDR(m
);
442 ATP_CLEAR_CONTROL(athp
);
443 athp
->cmd
= ATP_CMD_TREL
;
444 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
450 void atp_send_replies(atp
, rcbp
)
451 register struct atp_state
*atp
;
452 register struct atp_rcb
*rcbp
;
453 { register gbuf_t
*m
;
456 unsigned char *m0_rptr
= NULL
, *m0_wptr
= NULL
;
457 register at_atp_t
*athp
;
458 register struct atpBDS
*bdsp
;
459 register gbuf_t
*m2
, *m1
, *m0
, *m3
;
461 gbuf_t
*mprev
, *mlist
= 0;
462 at_socket src_socket
= (at_socket
)atp
->atp_socket_no
;
463 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
465 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
468 ATDISABLE(s
, atp
->atp_lock
);
469 if (rcbp
->rc_queue
!= atp
) {
470 ATENABLE(s
, atp
->atp_lock
);
473 if (rcbp
->rc_not_sent_bitmap
== 0)
474 goto nothing_to_send
;
476 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
, ("atp_send_replies\n"));
478 * Do this for each message that hasn't been sent
480 cnt
= rcbp
->rc_pktcnt
;
481 for (i
= 0; i
< cnt
; i
++) {
483 if (rcbp
->rc_snd
[i
]) {
485 gbuf_alloc(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,PRI_MED
))
487 for (cnt
= 0; cnt
< i
; cnt
++)
489 gbuf_freeb(rc_xmt
[cnt
]);
490 goto nothing_to_send
;
498 m0_rptr
= gbuf_rptr(m0
);
499 m0_wptr
= gbuf_wptr(m0
);
501 if (gbuf_len(m
) > TOTAL_ATP_HDR_SIZE
)
502 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
506 for (i
= 0; i
< cnt
; i
++) {
507 if (rcbp
->rc_snd
[i
] == 0) {
508 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)))
513 gbuf_rinc(m2
,AT_WR_OFFSET
);
514 gbuf_wset(m2
,TOTAL_ATP_HDR_SIZE
);
515 *(struct ddp_atp
*)(gbuf_rptr(m2
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
516 athp
= AT_ATP_HDR(m2
);
517 ATP_CLEAR_CONTROL(athp
);
518 athp
->cmd
= ATP_CMD_TRESP
;
521 athp
->eom
= 1; /* for the last fragment */
523 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
526 if (len
= UAS_VALUE(bdsp
->bdsBuffSz
)) { /* copy in data */
527 if (m0
&& gbuf_len(m0
)) {
528 if ((m1
= gbuf_dupb(m0
)) == NULL
) {
529 for (i
= 0; i
< cnt
; i
++)
531 gbuf_freem(rc_xmt
[i
]);
532 gbuf_rptr(m0
) = m0_rptr
;
533 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
534 goto nothing_to_send
;
538 if ((len
= gbuf_len(m0
)) < 0) {
541 if (!append_copy((struct mbuf
*)m1
,
542 (struct mbuf
*)gbuf_cont(m0
), FALSE
)) {
543 for (i
= 0; i
< cnt
; i
++)
545 gbuf_freem(rc_xmt
[i
]);
546 gbuf_rptr(m0
) = m0_rptr
;
547 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
548 goto nothing_to_send
;
554 /* temp fix for page boundary problem - bug# 2703163 */
555 lastPage
= (caddr_t
)((int)(gbuf_wptr(m1
) - 1) & ~PAGE_MASK
); /* 4k page of last byte */
556 if (lastPage
!= (caddr_t
)((int)(gbuf_rptr(m1
)) & ~PAGE_MASK
)) { /* 1st byte and last on same page ? */
557 if ((m3
= gbuf_dupb(m1
)) == NULL
) {
558 for (i
= 0; i
< cnt
; i
++)
560 gbuf_freem(rc_xmt
[i
]);
561 (gbuf_rptr(m0
)) = m0_rptr
;
562 gbuf_wset(m0
, (m0_wptr
- m0_rptr
));
563 goto nothing_to_send
;
565 (gbuf_rptr(m3
)) = lastPage
; /* new mbuf starts at beginning of page */
566 gbuf_wset(m3
, (gbuf_wptr(m1
) - lastPage
)); /* len = remaining data crossing over page boundary */
567 gbuf_wset(m1
, (lastPage
- (gbuf_rptr(m1
)))); /* adjust len of m1 */
568 (gbuf_cont(m1
)) = m3
;
574 AT_DDP_HDR(m2
)->src_socket
= src_socket
;
575 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
,
576 ("atp_send_replies: %d, socket=%d, size=%d\n",
577 i
, atp
->atp_socket_no
, gbuf_msgsize(gbuf_cont(m2
))));
580 gbuf_next(mprev
) = m2
;
586 rcbp
->rc_not_sent_bitmap
&= ~atp_mask
[i
];
587 if (rcbp
->rc_not_sent_bitmap
== 0)
591 * on to the next frag
596 gbuf_rptr(m0
) = m0_rptr
;
597 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
601 ATENABLE(s
, atp
->atp_lock
);
603 ATDISABLE(s
, atp
->atp_lock
);
608 * If all replies from this reply block have been sent then
609 * remove it from the queue and mark it so
611 if (rcbp
->rc_queue
!= atp
) {
612 ATENABLE(s
, atp
->atp_lock
);
615 rcbp
->rc_rep_waiting
= 0;
618 * If we are doing execute once re-set the rcb timeout
619 * each time we send back any part of the response. Note
620 * that this timer is started when an initial request is
621 * received. Each response reprimes the timer. Duplicate
622 * requests do not reprime the timer.
624 * We have sent all of a response so free the
627 if (rcbp
->rc_xo
&& rcbp
->rc_state
!= RCB_RELEASED
) {
628 ATDISABLE(s_gen
, atpgen_lock
);
629 if (rcbp
->rc_timestamp
== 0) {
630 rcbp
->rc_timestamp
= time
.tv_sec
;
631 if (rcbp
->rc_timestamp
== 0)
632 rcbp
->rc_timestamp
= 1;
633 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
635 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
636 ATENABLE(s_gen
, atpgen_lock
);
639 ATENABLE(s
, atp
->atp_lock
);
640 } /* atp_send_replies */
644 atp_pack_bdsp(trp
, bdsp
)
645 register struct atp_trans
*trp
;
646 register struct atpBDS
*bdsp
;
648 register gbuf_t
*m
= NULL
;
649 register int i
, datsize
= 0;
650 struct atpBDS
*bdsbase
= bdsp
;
652 dPrintf(D_M_ATP
, D_L_INFO
, ("atp_pack_bdsp: socket=%d\n",
653 trp
->tr_queue
->atp_socket_no
));
655 for (i
= 0; i
< ATP_TRESP_MAX
; i
++, bdsp
++) {
656 short bufsize
= UAS_VALUE(bdsp
->bdsBuffSz
);
657 long bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
);
659 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
662 /* discard ddp hdr on first packet */
664 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
666 /* this field may contain control information even when
667 no data is present */
668 UAL_UAL(bdsp
->bdsUserData
,
669 (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
670 gbuf_rinc(m
, ATP_HDR_SIZE
);
672 if ((bufsize
!= 0) && (bufaddr
!= 0)) {
673 /* user expects data back */
675 register char *buf
= (char *)bufaddr
;
678 short len
= (short)(gbuf_len(m
));
682 copyout((caddr_t
)gbuf_rptr(m
),
691 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
694 gbuf_freem(trp
->tr_rcv
[i
]);
695 trp
->tr_rcv
[i
] = NULL
;
698 /* report the number of packets */
699 UAS_ASSIGN(((struct atpBDS
*)bdsbase
)->bdsBuffSz
, i
);
701 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
703 } /* atp_pack_bdsp */
707 atp_unpack_bdsp(atp
, m
, rcbp
, cnt
, wait
)
708 struct atp_state
*atp
;
709 gbuf_t
*m
; /* ddp, atp and bdsp gbuf_t */
710 register struct atp_rcb
*rcbp
;
711 register int cnt
, wait
;
713 register struct atpBDS
*bdsp
;
714 register gbuf_t
*m2
, *m1
, *m0
, *m3
;
716 register at_atp_t
*athp
;
717 register int i
, len
, s_gen
;
718 at_socket src_socket
;
720 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
722 gbuf_t
*mprev
, *mlist
= 0;
723 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
724 unsigned char *m0_rptr
, *m0_wptr
;
727 * get the user data structure pointer
729 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
732 * Guard against bogus count argument.
734 if ((unsigned) cnt
> ATP_TRESP_MAX
) {
735 dPrintf(D_M_ATP
, D_L_ERROR
,
736 ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt
));
740 if ((src_socket
= (at_socket
)atp
->atp_socket_no
) == 0xFF) {
741 /* comparison was to -1, however src_socket is a u_char */
748 rcbp
->rc_pktcnt
= cnt
;
749 rcbp
->rc_state
= RCB_SENDING
;
750 rcbp
->rc_not_sent_bitmap
= 0;
754 * special case this to
755 * improve AFP write transactions to the server
758 if ((m2
= gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,
761 gbuf_rinc(m2
,AT_WR_OFFSET
);
762 gbuf_wset(m2
,TOTAL_ATP_HDR_SIZE
);
763 *(struct ddp_atp
*)(gbuf_rptr(m2
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
764 athp
= AT_ATP_HDR(m2
);
765 ATP_CLEAR_CONTROL(athp
);
766 athp
->cmd
= ATP_CMD_TRESP
;
768 athp
->eom
= 1; /* there's only 1 fragment */
770 /* *** why only if cnt > 0? *** */
772 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
774 if (!append_copy((struct mbuf
*)m2
,
775 (struct mbuf
*)m0
, wait
)) {
780 * send the message and mark it as sent
782 AT_DDP_HDR(m2
)->src_socket
= src_socket
;
783 dPrintf(D_M_ATP_LOW
, D_L_INFO
,
784 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
785 0,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(m2
)),cnt
));
790 for (i
= 0; i
< cnt
; i
++) {
791 /* all hdrs, packet data and dst addr storage */
793 gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,
795 for (cnt
= 0; cnt
< i
; cnt
++)
797 gbuf_freeb(rc_xmt
[cnt
]);
802 m0_rptr
= gbuf_rptr(m0
);
803 m0_wptr
= gbuf_wptr(m0
);
806 for (i
= 0; i
< cnt
; i
++) {
808 gbuf_rinc(m2
,AT_WR_OFFSET
);
809 gbuf_wset(m2
,TOTAL_ATP_HDR_SIZE
);
810 *(struct ddp_atp
*)(gbuf_rptr(m2
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
811 athp
= AT_ATP_HDR(m2
);
812 ATP_CLEAR_CONTROL(athp
);
813 athp
->cmd
= ATP_CMD_TRESP
;
816 athp
->eom
= 1; /* for the last fragment */
817 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
819 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
))) { /* copy in data */
820 if (m0
&& gbuf_len(m0
)) {
821 if ((m1
= gbuf_dupb_wait(m0
, wait
)) == NULL
) {
822 for (i
= 0; i
< cnt
; i
++)
824 gbuf_freem(rc_xmt
[i
]);
825 gbuf_rptr(m0
) = m0_rptr
;
826 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
829 gbuf_wset(m1
,len
); /* *** m1 is first len bytes of m0? *** */
831 if ((len
= gbuf_len(m0
)) < 0) {
834 if (!append_copy((struct mbuf
*)m1
,
835 (struct mbuf
*)gbuf_cont(m0
), wait
)) {
836 for (i
= 0; i
< cnt
; i
++)
838 gbuf_freem(rc_xmt
[i
]);
839 gbuf_rptr(m0
) = m0_rptr
;
840 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
847 /* temp fix for page boundary problem - bug# 2703163 */
848 lastPage
= (caddr_t
)((int)(gbuf_wptr(m1
) - 1) & ~PAGE_MASK
); /* 4k page of last byte */
849 if (lastPage
!= (caddr_t
)((int)(gbuf_rptr(m1
)) & ~PAGE_MASK
)) { /* 1st byte and last on same page ? */
850 if ((m3
= gbuf_dupb_wait(m1
, wait
)) == NULL
) {
851 for (i
= 0; i
< cnt
; i
++)
853 gbuf_freem(rc_xmt
[i
]);
854 (gbuf_rptr(m0
)) = m0_rptr
;
855 gbuf_wset(m0
, (m0_wptr
- m0_rptr
));
858 (gbuf_rptr(m3
)) = lastPage
; /* new mbuf starts at beginning of page */
859 gbuf_wset(m3
, (gbuf_wptr(m1
) - lastPage
)); /* len = remaining data crossing over page boundary */
860 gbuf_wset(m1
, (lastPage
- (gbuf_rptr(m1
)))); /* adjust len of m1 */
861 (gbuf_cont(m1
)) = m3
;
867 AT_DDP_HDR(m2
)->src_socket
= src_socket
;
868 dPrintf(D_M_ATP_LOW
,D_L_INFO
,
869 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
870 i
,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(m2
)),cnt
));
872 gbuf_next(mprev
) = m2
;
877 * on to the next frag
882 gbuf_rptr(m0
) = m0_rptr
;
883 gbuf_wset(m0
,(m0_wptr
-m0_rptr
));
890 ATDISABLE(s_gen
, atpgen_lock
);
891 if (rcbp
->rc_timestamp
== 0) {
892 if ((rcbp
->rc_timestamp
= time
.tv_sec
) == 0)
893 rcbp
->rc_timestamp
= 1;
894 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
896 ATENABLE(s_gen
, atpgen_lock
);
901 } /* atp_unpack_bdsp */
903 #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6)
904 #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
905 static unsigned int sNext
= 0;
907 int atp_bind(gref
, sVal
, flag
)
912 extern unsigned char asp_inpC
[];
913 extern asp_scb_t
*asp_scbQ
[];
914 unsigned char inpC
, sNextUsed
= 0;
915 unsigned int sMin
, sMax
, sSav
;
916 struct atp_state
*atp
;
919 atp
= (struct atp_state
*)gref
->info
;
921 atp
= (struct atp_state
*)atp
->atp_msgq
;
923 sMax
= ATP_SOCKET_LAST
;
924 sMin
= ATP_SOCKET_FIRST
;
925 ATDISABLE(s
, atpgen_lock
);
926 if (flag
&& (*flag
== 3)) {
935 ((sVal
> sMax
) || (sVal
< 2) || (sVal
== 6) ||
936 (ddp_socket_inuse(sVal
, DDP_ATP
) &&
937 (atp_inputQ
[sVal
] != (gref_t
*)1)))) {
938 ATENABLE(s
, atpgen_lock
);
945 for (sVal
=sMin
; sVal
<= sMax
; sVal
++) {
946 if (!ddp_socket_inuse(sVal
, DDP_ATP
) ||
947 atp_inputQ
[sVal
] == (gref_t
*)1)
949 else if (flag
&& (*flag
== 3) && asp_scbQ
[sVal
]) {
950 if ((asp_scbQ
[sVal
]->dflag
== *flag
)
951 && (asp_inpC
[sVal
] < inpC
) ) {
952 inpC
= asp_inpC
[sVal
];
958 if (flag
&& (*flag
== 3)) {
962 sMin
= ATP_SOCKET_FIRST
+40;
966 *flag
= (unsigned char)sSav
;
968 ATENABLE(s
, atpgen_lock
);
972 atp
->atp_socket_no
= (short)sVal
;
973 atp_inputQ
[sVal
] = gref
;
975 atp_pidM
[sVal
] = atp
->atp_pid
;
976 else if (*flag
== 3) {
978 if (sNext
> ATP_SOCKET_LAST
)
982 ATENABLE(s
, atpgen_lock
);
986 void atp_req_ind(atp
, mioc
)
987 register struct atp_state
*atp
;
988 register gbuf_t
*mioc
;
990 register struct atp_rcb
*rcbp
;
993 if ((rcbp
= atp
->atp_attached
.head
) != 0) {
994 gbuf_cont(mioc
) = rcbp
->rc_ioctl
;
995 rcbp
->rc_ioctl
= NULL
;
996 ATDISABLE(s
, atp
->atp_lock
);
998 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
999 rcbp
->rc_state
= RCB_NOTIFIED
;
1000 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1003 ATENABLE(s
, atp
->atp_lock
);
1004 if (gbuf_cont(mioc
))
1005 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
1007 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1008 asp_ack_reply(atp
->atp_gref
, mioc
);
1013 void atp_rsp_ind(trp
, mioc
)
1014 register struct atp_trans
*trp
;
1015 register gbuf_t
*mioc
;
1017 register struct atp_state
*atp
= trp
->tr_queue
;
1023 switch (trp
->tr_state
) {
1025 if (asp_pack_bdsp(trp
, &xm
) < 0)
1027 gbuf_cont(mioc
) = trp
->tr_xmt
;
1042 dPrintf(D_M_ATP
, D_L_ERROR
,
1043 ("atp_rsp_ind: TRANSACTION error\n"));
1044 atp_iocnak(atp
, mioc
, err
);
1046 gbuf_cont(gbuf_cont(mioc
)) = xm
;
1047 atp_iocack(atp
, mioc
);
1052 void atp_cancel_req(gref
, tid
)
1057 struct atp_state
*atp
;
1058 struct atp_trans
*trp
;
1060 atp
= (struct atp_state
*)gref
->info
;
1062 atp
= (struct atp_state
*)atp
->atp_msgq
;
1064 ATDISABLE(s
, atp
->atp_lock
);
1065 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1066 if (trp
->tr_tid
== tid
)
1069 ATENABLE(s
, atp
->atp_lock
);
1075 * remove atp from the use list
1078 atp_dequeue_atp(atp
)
1079 struct atp_state
*atp
;
1083 ATDISABLE(s
, atpall_lock
);
1084 if (atp
== atp_used_list
) {
1085 if ((atp_used_list
= atp
->atp_trans_waiting
) != 0)
1086 atp
->atp_trans_waiting
->atp_rcb_waiting
= 0;
1087 } else if (atp
->atp_rcb_waiting
) {
1088 if ((atp
->atp_rcb_waiting
->atp_trans_waiting
1089 = atp
->atp_trans_waiting
) != 0)
1090 atp
->atp_trans_waiting
->atp_rcb_waiting
= atp
->atp_rcb_waiting
;
1093 atp
->atp_trans_waiting
= 0;
1094 atp
->atp_rcb_waiting
= 0;
1095 ATENABLE(s
, atpall_lock
);
1099 atp_timout(func
, trp
, ticks
)
1101 struct atp_trans
*trp
;
1106 struct atp_trans
*curr_trp
, *prev_trp
;
1108 ATDISABLE(s
, atptmo_lock
);
1109 if (trp
->tr_tmo_func
) {
1110 ATENABLE(s
, atptmo_lock
);
1114 trp
->tr_tmo_func
= func
;
1115 trp
->tr_tmo_delta
= 1+(ticks
>>5);
1117 if (trp_tmo_list
== 0) {
1118 trp
->tr_tmo_next
= trp
->tr_tmo_prev
= 0;
1120 ATENABLE(s
, atptmo_lock
);
1125 curr_trp
= trp_tmo_list
;
1129 sum
+= curr_trp
->tr_tmo_delta
;
1130 if (sum
> trp
->tr_tmo_delta
) {
1131 sum
-= curr_trp
->tr_tmo_delta
;
1132 trp
->tr_tmo_delta
-= sum
;
1133 curr_trp
->tr_tmo_delta
-= trp
->tr_tmo_delta
;
1136 prev_trp
= curr_trp
;
1137 if ((curr_trp
= curr_trp
->tr_tmo_next
) == 0) {
1138 trp
->tr_tmo_delta
-= sum
;
1144 trp
->tr_tmo_prev
= prev_trp
;
1145 if ((trp
->tr_tmo_next
= prev_trp
->tr_tmo_next
) != 0)
1146 prev_trp
->tr_tmo_next
->tr_tmo_prev
= trp
;
1147 prev_trp
->tr_tmo_next
= trp
;
1149 trp
->tr_tmo_prev
= 0;
1150 trp
->tr_tmo_next
= trp_tmo_list
;
1151 trp_tmo_list
->tr_tmo_prev
= trp
;
1154 ATENABLE(s
, atptmo_lock
);
1158 atp_untimout(func
, trp
)
1160 struct atp_trans
*trp
;
1164 ATDISABLE(s
, atptmo_lock
);
1165 if (trp
->tr_tmo_func
== 0) {
1166 ATENABLE(s
, atptmo_lock
);
1170 if (trp_tmo_list
== trp
) {
1171 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0) {
1172 trp_tmo_list
->tr_tmo_prev
= 0;
1173 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1176 if ((trp
->tr_tmo_prev
->tr_tmo_next
= trp
->tr_tmo_next
) != 0) {
1177 trp
->tr_tmo_next
->tr_tmo_prev
= trp
->tr_tmo_prev
;
1178 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1181 trp
->tr_tmo_func
= 0;
1182 ATENABLE(s
, atptmo_lock
);
1186 atp_trp_clock_funnel(arg
)
1189 thread_funnel_set(network_flock
, TRUE
);
1191 thread_funnel_set(network_flock
, FALSE
);
1199 struct atp_trans
*trp
;
1200 void (*tr_tmo_func
)();
1202 ATDISABLE(s
, atptmo_lock
);
1204 trp_tmo_list
->tr_tmo_delta
--;
1205 while (((trp
= trp_tmo_list
) != 0) && (trp_tmo_list
->tr_tmo_delta
== 0)) {
1206 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0)
1207 trp_tmo_list
->tr_tmo_prev
= 0;
1208 if ((tr_tmo_func
= trp
->tr_tmo_func
) != 0) {
1209 trp
->tr_tmo_func
= 0;
1210 ATENABLE(s
, atptmo_lock
);
1211 (*tr_tmo_func
)(trp
);
1212 ATDISABLE(s
, atptmo_lock
);
1215 ATENABLE(s
, atptmo_lock
);
1217 timeout(atp_trp_clock_funnel
, (void *)arg
, (1<<5));
1221 atp_send_req(gref
, mioc
)
1225 register struct atp_state
*atp
;
1226 register struct atp_trans
*trp
;
1227 register ioc_t
*iocbp
;
1228 register at_atp_t
*athp
;
1229 register at_ddp_t
*ddp
;
1230 gbuf_t
*m
, *m2
, *bds
;
1231 struct atp_set_default
*sdb
;
1235 atp
= (struct atp_state
*)((struct atp_state
*)gref
->info
)->atp_msgq
;
1236 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1238 if ((trp
= atp_trans_alloc(atp
)) == NULL
) {
1240 ((asp_scb_t
*)gref
->info
)->stat_msg
= mioc
;
1241 iocbp
->ioc_private
= (void *)gref
;
1242 timeout(atp_retry_req
, mioc
, 10);
1246 m2
= gbuf_cont(mioc
);
1247 if ((bds
= gbuf_dupb(m2
)) == NULL
) {
1248 atp_trans_free(trp
);
1251 gbuf_rinc(m2
,atpBDSsize
);
1252 gbuf_wset(bds
,atpBDSsize
);
1253 iocbp
->ioc_count
-= atpBDSsize
;
1254 gbuf_cont(m2
) = NULL
;
1256 old
= iocbp
->ioc_cmd
;
1257 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
1258 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1261 * The at_snd_req library routine multiplies seconds by 100.
1262 * We need to divide by 100 in order to obtain the timer.
1264 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1266 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1267 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1269 trp
->tr_retry
= sdb
->def_retries
;
1270 trp
->tr_timeout
= timer
;
1272 trp
->tr_tid
= atp_tid(atp
);
1276 * Now fill in the header (and remember the bits
1279 athp
= AT_ATP_HDR(m2
);
1280 athp
->cmd
= ATP_CMD_TREQ
;
1281 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1284 trp
->tr_xo
= athp
->xo
;
1285 trp
->tr_bitmap
= athp
->bitmap
;
1286 ddp
= AT_DDP_HDR(m2
);
1287 ddp
->type
= DDP_ATP
;
1288 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1289 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1290 trp
->tr_socket
.node
= ddp
->dst_node
;
1291 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1292 trp
->tr_local_socket
= atp
->atp_socket_no
;
1293 trp
->tr_local_node
= ddp
->src_node
;
1294 NET_NET(trp
->tr_local_net
, ddp
->src_net
);
1297 /* save the local information in the gref */
1298 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1299 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1300 atp
->atp_gref
->lport
= ddp
->src_node
;
1301 atp
->atp_gref
->ddptype
= DDP_ATP
;
1305 * Put us in the transaction waiting queue
1307 ATDISABLE(s
, atp
->atp_lock
);
1308 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1309 ATENABLE(s
, atp
->atp_lock
);
1312 * Send the message and set the timer
1314 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1315 if (!trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1316 atp_x_done(trp
); /* no reason to tie up resources */
1318 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1320 trace_mbufs(D_M_ATP_LOW
, " s", m
);
1323 } /* atp_send_req */
1325 void atp_retry_req(m
)
1329 boolean_t funnel_state
;
1331 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1333 gref
= (gref_t
*)((ioc_t
*)gbuf_rptr(m
))->ioc_private
;
1335 ((asp_scb_t
*)gref
->info
)->stat_msg
= 0;
1336 atp_send_req(gref
, m
);
1338 (void) thread_funnel_set(network_flock
, FALSE
);
1341 void atp_send_rsp(gref
, m
, wait
)
1346 register struct atp_state
*atp
;
1347 register struct atp_rcb
*rcbp
;
1348 register at_atp_t
*athp
;
1349 register at_ddp_t
*ddp
;
1352 atp
= (struct atp_state
*)gref
->info
;
1354 atp
= (struct atp_state
*)atp
->atp_msgq
;
1355 ddp
= AT_DDP_HDR(m
);
1356 athp
= AT_ATP_HDR(m
);
1359 * search for the corresponding rcb
1361 ATDISABLE(s
, atp
->atp_lock
);
1362 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1363 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1364 (rcbp
->rc_socket
.node
== ddp
->dst_node
) &&
1365 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
)) &&
1366 (rcbp
->rc_socket
.socket
== ddp
->dst_socket
) )
1371 * If it has already been sent then drop the request
1373 if ((rcbp
&& (rcbp
->rc_state
!= RCB_NOTIFIED
)) ||
1374 (rcbp
== NULL
&& athp
->xo
) ) {
1375 ATENABLE(s
, atp
->atp_lock
);
1379 ATENABLE(s
, atp
->atp_lock
);
1381 if (rcbp
== NULL
) { /* a response is being sent for an ALO transaction */
1382 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
1387 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
1388 rcbp
->rc_socket
.node
= ddp
->dst_node
;
1389 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
1390 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
1391 rcbp
->rc_bitmap
= 0xff;
1393 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
1394 ATDISABLE(s
, atp
->atp_lock
);
1395 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1396 ATENABLE(s
, atp
->atp_lock
);
1398 else if (ddp
->src_node
== 0) {
1399 NET_NET(ddp
->src_net
, rcbp
->rc_local_net
);
1400 ddp
->src_node
= rcbp
->rc_local_node
;
1403 xcnt
= get_bds_entries(m
);
1404 s
= atp_unpack_bdsp(atp
, m
, rcbp
, xcnt
, wait
);
1406 atp_send_replies(atp
, rcbp
);
1407 } /* atp_send_rsp */
1409 int asp_pack_bdsp(trp
, xm
)
1410 register struct atp_trans
*trp
;
1413 register struct atpBDS
*bdsp
;
1414 register gbuf_t
*m
, *m2
;
1416 gbuf_t
*m_prev
, *m_head
= 0;
1418 dPrintf(D_M_ATP
, D_L_INFO
, ("asp_pack_bdsp: socket=%d\n",
1419 trp
->tr_queue
->atp_socket_no
));
1421 if ((m2
= trp
->tr_bdsp
) == NULL
)
1423 trp
->tr_bdsp
= NULL
;
1424 bdsp
= (struct atpBDS
*)gbuf_rptr(m2
);
1426 for (i
= 0; (i
< ATP_TRESP_MAX
&&
1427 bdsp
< (struct atpBDS
*)(gbuf_wptr(m2
))); i
++) {
1428 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
1431 /* discard ddp hdr on first packet */
1432 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
1435 UAL_UAL(bdsp
->bdsUserData
, (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
1436 gbuf_rinc(m
, ATP_HDR_SIZE
);
1438 if (UAL_VALUE(bdsp
->bdsBuffAddr
)) {
1441 /* user expects data back */
1446 gbuf_cont(m_prev
) = m
;
1448 tmp
= (short)gbuf_len(m
);
1449 while (gbuf_cont(m
)) {
1451 tmp
+= (short)(gbuf_len(m
));
1455 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
1457 trp
->tr_rcv
[i
] = NULL
;
1462 * report the number of packets
1464 UAS_ASSIGN(((struct atpBDS
*)gbuf_rptr(m2
))->bdsBuffSz
, i
);
1466 if (trp
->tr_xmt
) /* an ioctl block is still held? */
1467 gbuf_cont(trp
->tr_xmt
) = m2
;
1476 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
1477 gbuf_msgsize(*xm
)));
1483 * The following routines are direct entries from system
1484 * calls to allow fast sending and recving of ATP data.
1488 _ATPsndreq(fd
, buf
, len
, nowait
, err
, proc
)
1500 register struct atp_state
*atp
;
1501 register struct atp_trans
*trp
;
1502 register ioc_t
*iocbp
;
1503 register at_atp_t
*athp
;
1504 register at_ddp_t
*ddp
;
1505 struct atp_set_default
*sdb
;
1506 gbuf_t
*m2
, *m
, *mioc
;
1507 char bds
[atpBDSsize
];
1509 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 0)
1512 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1513 || (atp
->atp_flags
& ATP_CLOSING
)) {
1514 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
1515 (u_int
) gref
, gref
->pid
));
1521 while ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_MED
)) == 0) {
1522 ATDISABLE(s
, atp
->atp_delay_lock
);
1523 rc
= tsleep(&atp
->atp_delay_event
, PSOCK
| PCATCH
, "atpmioc", 10);
1524 ATENABLE(s
, atp
->atp_delay_lock
);
1531 gbuf_wset(mioc
,sizeof(ioc_t
));
1533 while ((m2
= gbuf_alloc(len
, PRI_MED
)) == 0) {
1534 ATDISABLE(s
, atp
->atp_delay_lock
);
1535 rc
= tsleep(&atp
->atp_delay_event
, PSOCK
| PCATCH
, "atpm2", 10);
1536 ATENABLE(s
, atp
->atp_delay_lock
);
1544 gbuf_cont(mioc
) = m2
;
1545 if (((*err
= copyin((caddr_t
)buf
, (caddr_t
)bds
, atpBDSsize
)) != 0)
1546 || ((*err
= copyin((caddr_t
)&buf
[atpBDSsize
],
1547 (caddr_t
)gbuf_rptr(m2
), len
)) != 0)) {
1551 gbuf_set_type(mioc
, MSG_IOCTL
);
1552 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1553 iocbp
->ioc_count
= len
;
1554 iocbp
->ioc_cmd
= nowait
? AT_ATP_ISSUE_REQUEST_NOTE
: AT_ATP_ISSUE_REQUEST
;
1555 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1558 * The at_snd_req library routine multiplies seconds by 100.
1559 * We need to divide by 100 in order to obtain the timer.
1561 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1563 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1564 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1567 * allocate and set up the transaction record
1569 while ((trp
= atp_trans_alloc(atp
)) == 0) {
1570 ATDISABLE(s
, atp
->atp_delay_lock
);
1571 rc
= tsleep(&atp
->atp_delay_event
, PSOCK
| PCATCH
, "atptrp", 10);
1572 ATENABLE(s
, atp
->atp_delay_lock
);
1579 trp
->tr_retry
= sdb
->def_retries
;
1580 trp
->tr_timeout
= timer
;
1581 trp
->tr_bdsp
= NULL
;
1582 trp
->tr_tid
= atp_tid(atp
);
1586 * remember the IOCTL packet so we can ack it
1592 * Now fill in the header (and remember the bits
1595 athp
= AT_ATP_HDR(m2
);
1596 athp
->cmd
= ATP_CMD_TREQ
;
1597 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1600 trp
->tr_xo
= athp
->xo
;
1601 trp
->tr_bitmap
= athp
->bitmap
;
1602 ddp
= AT_DDP_HDR(m2
);
1603 ddp
->type
= DDP_ATP
;
1604 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1606 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1607 trp
->tr_socket
.node
= ddp
->dst_node
;
1608 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1609 trp
->tr_local_socket
= atp
->atp_socket_no
;
1612 /* save the local information in the gref */
1613 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1614 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1615 atp
->atp_gref
->lport
= ddp
->src_node
;
1616 atp
->atp_gref
->ddptype
= DDP_ATP
;
1620 * Put us in the transaction waiting queue
1622 ATDISABLE(s
, atp
->atp_lock
);
1623 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1624 ATENABLE(s
, atp
->atp_lock
);
1627 * Send the message and set the timer
1629 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1630 if ( !trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1631 atp_x_done(trp
); /* no reason to tie up resources */
1633 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1641 * wait for the transaction to complete
1643 ATDISABLE(s
, trp
->tr_lock
);
1644 while ((trp
->tr_state
!= TRANS_DONE
) && (trp
->tr_state
!= TRANS_FAILED
) &&
1645 (trp
->tr_state
!= TRANS_ABORTING
)) {
1646 trp
->tr_rsp_wait
= 1;
1647 rc
= tsleep(&trp
->tr_event
, PSOCK
| PCATCH
, "atpsndreq", 0);
1649 trp
->tr_rsp_wait
= 0;
1650 ATENABLE(s
, trp
->tr_lock
);
1655 trp
->tr_rsp_wait
= 0;
1656 ATENABLE(s
, trp
->tr_lock
);
1659 if (trp
->tr_state
== TRANS_FAILED
|| trp
->tr_state
== TRANS_ABORTING
) {
1661 * transaction timed out, return error
1669 * copy out the recv data
1671 atp_pack_bdsp(trp
, bds
);
1674 * copyout the result info
1676 copyout((caddr_t
)bds
, (caddr_t
)buf
, atpBDSsize
);
1684 _ATPsndrsp(fd
, respbuff
, resplen
, datalen
, err
, proc
)
1686 unsigned char *respbuff
;
1698 register struct atp_state
*atp
;
1699 register struct atpBDS
*bdsp
;
1702 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 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
));
1715 * allocate buffer and copy in the response info
1717 if ((m
= gbuf_alloc_wait(resplen
, TRUE
)) == 0) {
1721 if ((*err
= copyin((caddr_t
)respbuff
, (caddr_t
)gbuf_rptr(m
), resplen
)) != 0) {
1725 gbuf_wset(m
,resplen
);
1726 ((at_ddp_t
*)gbuf_rptr(m
))->src_node
= 0;
1727 bdsp
= (struct atpBDS
*)(gbuf_rptr(m
) + TOTAL_ATP_HDR_SIZE
);
1728 if ((resplen
== TOTAL_ATP_HDR_SIZE
) || ((len
= UAS_VALUE(bdsp
->bdsDataSz
)) == 1))
1731 len
= 16 * sizeof(gbuf_t
);
1734 * allocate buffer and copy in the response data
1736 if ((mdata
= gbuf_alloc_wait(datalen
+len
, TRUE
)) == 0) {
1741 gbuf_cont(m
) = mdata
;
1742 for (size
=0; bdsp
< (struct atpBDS
*)gbuf_wptr(m
); bdsp
++) {
1743 if ((bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
)) != 0) {
1744 len
= UAS_VALUE(bdsp
->bdsBuffSz
);
1745 buf
= (char *)bufaddr
;
1746 if ((*err
= copyin((caddr_t
)buf
,
1747 (caddr_t
)&gbuf_rptr(mdata
)[size
], len
)) != 0) {
1754 gbuf_wset(mdata
,size
);
1756 atp_send_rsp(gref
, m
, TRUE
);
1761 _ATPgetreq(fd
, buf
, buflen
, err
, proc
)
1769 register struct atp_state
*atp
;
1770 register struct atp_rcb
*rcbp
;
1771 register gbuf_t
*m
, *m_head
;
1774 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 0)
1777 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1778 || (atp
->atp_flags
& ATP_CLOSING
)) {
1779 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
1780 (u_int
) gref
, gref
->pid
));
1785 ATDISABLE(s
, atp
->atp_lock
);
1786 if ((rcbp
= atp
->atp_attached
.head
) != NULL
) {
1788 * Got one, move it to the active response Q
1790 m_head
= rcbp
->rc_ioctl
;
1791 rcbp
->rc_ioctl
= NULL
;
1794 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
1795 rcbp
->rc_state
= RCB_NOTIFIED
;
1796 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1798 /* detach rcbp from attached queue,
1799 * and free any outstanding resources
1803 ATENABLE(s
, atp
->atp_lock
);
1806 * copyout the request data, including the protocol header
1808 for (size
=0, m
=m_head
; m
; m
= gbuf_cont(m
)) {
1809 if ((len
= gbuf_len(m
)) > buflen
)
1811 copyout((caddr_t
)gbuf_rptr(m
), (caddr_t
)&buf
[size
], len
);
1813 if ((buflen
-= len
) == 0)
1820 ATENABLE(s
, atp
->atp_lock
);
1826 _ATPgetrsp(fd
, bdsp
, err
, proc
)
1828 struct atpBDS
*bdsp
;
1833 register struct atp_state
*atp
;
1834 register struct atp_trans
*trp
;
1836 char bds
[atpBDSsize
];
1838 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) != 0)
1841 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1842 || (atp
->atp_flags
& ATP_CLOSING
)) {
1843 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
1844 (u_int
) gref
, gref
->pid
));
1849 ATDISABLE(s
, atp
->atp_lock
);
1850 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1851 dPrintf(D_M_ATP
, D_L_INFO
,
1852 ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
1853 (u_int
) atp
, (u_int
) trp
, trp
->tr_state
));
1855 switch (trp
->tr_state
) {
1857 ATENABLE(s
, atp
->atp_lock
);
1858 if ((*err
= copyin((caddr_t
)bdsp
,
1859 (caddr_t
)bds
, sizeof(bds
))) != 0)
1861 atp_pack_bdsp(trp
, bds
);
1862 tid
= (int)trp
->tr_tid
;
1864 copyout((caddr_t
)bds
, (caddr_t
)bdsp
, sizeof(bds
));
1869 * transaction timed out, return error
1871 ATENABLE(s
, atp
->atp_lock
);
1880 ATENABLE(s
, atp
->atp_lock
);
1887 atp_drop_req(gref
, m
)
1892 struct atp_state
*atp
;
1893 struct atp_rcb
*rcbp
;
1897 atp
= (struct atp_state
*)gref
->info
;
1899 atp
= (struct atp_state
*)atp
->atp_msgq
;
1900 ddp
= AT_DDP_HDR(m
);
1901 athp
= AT_ATP_HDR(m
);
1904 * search for the corresponding rcb
1906 ATDISABLE(s
, atp
->atp_lock
);
1907 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1908 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1909 (rcbp
->rc_socket
.node
== ddp
->src_node
) &&
1910 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->src_net
)) &&
1911 (rcbp
->rc_socket
.socket
== ddp
->src_socket
) )
1920 ATENABLE(s
, atp
->atp_lock
);