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>
41 #include <kern/locks.h>
43 #include <sys/ioctl.h>
44 #include <sys/malloc.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
50 #include <netat/sysglue.h>
51 #include <netat/appletalk.h>
52 #include <netat/ddp.h>
53 #include <netat/at_pcb.h>
54 #include <netat/atp.h>
55 #include <netat/at_var.h>
56 #include <netat/asp.h>
57 #include <netat/at_pat.h>
58 #include <netat/debug.h>
60 static int loop_cnt
; /* for debugging loops */
61 #define CHK_LOOP(str) { \
62 if (loop_cnt++ > 100) { \
68 static int atp_pack_bdsp(struct atp_trans
*, struct atpBDS
*);
69 static int atp_unpack_bdsp(struct atp_state
*, gbuf_t
*, struct atp_rcb
*,
71 void atp_trp_clock(), asp_clock(), asp_clock_locked(), atp_trp_clock_locked();;
73 extern struct atp_rcb_qhead atp_need_rel
;
74 extern int atp_inited
;
75 extern struct atp_state
*atp_used_list
;
76 extern asp_scb_t
*scb_free_list
;
77 extern atlock_t atpgen_lock
;
78 extern atlock_t atpall_lock
;
79 extern atlock_t atptmo_lock
;
81 extern gbuf_t
*scb_resource_m
;
82 extern gbuf_t
*atp_resource_m
;
83 extern gref_t
*atp_inputQ
[];
84 extern int atp_pidM
[];
85 extern at_ifaddr_t
*ifID_home
;
86 extern lck_mtx_t
* atalk_mutex
;
88 static struct atp_trans
*trp_tmo_list
;
89 struct atp_trans
*trp_tmo_rcb
;
91 /* first bds entry gives number of bds entries in total (hack) */
92 #define get_bds_entries(m) \
93 ((gbuf_len(m) > TOTAL_ATP_HDR_SIZE)? \
94 (UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz)): 0)
96 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
101 trp_tmo_rcb
= atp_trans_alloc(0);
102 atp_timout(atp_rcb_timer
, trp_tmo_rcb
, 10 * HZ
);
103 atp_trp_clock((void *)&atp_inited
);
104 asp_clock((void *)&atp_inited
);
109 untimeout(asp_clock_locked
, (void *)&atp_inited
);
110 untimeout(atp_trp_clock_locked
, (void *)&atp_inited
);
111 atp_untimout(atp_rcb_timer
, trp_tmo_rcb
);
115 /* allocated in asp_scb_alloc(), which is called
117 if (scb_resource_m
) {
118 gbuf_freem(scb_resource_m
);
122 /* allocated in atp_trans_alloc() */
123 if (atp_resource_m
) {
124 gbuf_freem(atp_resource_m
);
126 atp_trans_free_list
= 0;
132 * write queue put routine .... filter out other than IOCTLs
133 * Version 1.8 of atp_write.c on 89/02/09 17:53:26
138 register gref_t
*gref
;
141 register ioc_t
*iocbp
;
143 struct atp_state
*atp
;
144 struct atp_trans
*trp
;
145 struct atp_rcb
*rcbp
;
148 atp
= (struct atp_state
*)gref
->info
;
150 atp
= (struct atp_state
*)atp
->atp_msgq
;
152 switch(gbuf_type(m
)) {
156 dPrintf(D_M_ATP
, D_L_WARNING
,
157 ("atp_wput: atp_msgq discarded\n"));
163 /* Need to ensure that all copyin/copyout calls are made at
164 * put routine time which should be in the user context. (true when
165 * we are the stream head). The service routine can be called on an
166 * unpredictable context and copyin/copyout calls will get wrong results
167 * or even panic the kernel.
169 iocbp
= (ioc_t
*)gbuf_rptr(m
);
171 switch (iocbp
->ioc_cmd
) {
172 case AT_ATP_BIND_REQ
:
173 if (gbuf_cont(m
) == NULL
) {
174 iocbp
->ioc_rval
= -1;
175 atp_iocnak(atp
, m
, EINVAL
);
178 skt
= *(at_socket
*)gbuf_rptr(gbuf_cont(m
));
179 if ((skt
= (at_socket
)atp_bind(gref
, (unsigned int)skt
, 0)) == 0)
180 atp_iocnak(atp
, m
, EINVAL
);
182 *(at_socket
*)gbuf_rptr(gbuf_cont(m
)) = skt
;
185 atp_dequeue_atp(atp
);
189 case AT_ATP_GET_CHANID
:
190 if (gbuf_cont(m
) == NULL
) {
191 iocbp
->ioc_rval
= -1;
192 atp_iocnak(atp
, m
, EINVAL
);
195 *(gref_t
**)gbuf_rptr(gbuf_cont(m
)) = gref
;
199 /* not the close and not the tickle(?) */
200 case AT_ATP_ISSUE_REQUEST_DEF
:
201 case AT_ATP_ISSUE_REQUEST_DEF_NOTE
: {
202 gbuf_t
*bds
, *tmp
, *m2
;
203 struct atp_rcb
*rcbp
;
207 if ((tmp
= gbuf_cont(m
)) != 0) {
208 if ((bds
= gbuf_dupb(tmp
)) == NULL
) {
209 atp_iocnak(atp
, m
, ENOBUFS
);
212 gbuf_rinc(tmp
,atpBDSsize
);
213 gbuf_wset(bds
,atpBDSsize
);
214 iocbp
->ioc_count
-= atpBDSsize
;
215 gbuf_cont(tmp
) = bds
;
219 * send a response to a transaction
222 if (iocbp
->ioc_count
< TOTAL_ATP_HDR_SIZE
) {
223 atp_iocnak(atp
, m
, EINVAL
);
228 * remove the response from the message
232 iocbp
->ioc_count
= 0;
233 ddp
= AT_DDP_HDR(m2
);
234 athp
= AT_ATP_HDR(m2
);
236 gbuf_cont(m2
) = atp
->atp_msgq
;
240 ATDISABLE(s
, atp
->atp_lock
);
242 * search for the corresponding rcb
244 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
245 if (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
) &&
246 rcbp
->rc_socket
.node
== ddp
->dst_node
&&
247 rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
) &&
248 rcbp
->rc_socket
.socket
== ddp
->dst_socket
)
251 ATENABLE(s
, atp
->atp_lock
);
254 * If it has already been sent then return an error
256 if ((rcbp
&& rcbp
->rc_state
!= RCB_NOTIFIED
) ||
257 (rcbp
== NULL
&& athp
->xo
)) {
258 atp_iocnak(atp
, m
, ENOENT
);
262 if (rcbp
== NULL
) { /* a response for an ALO transaction */
263 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
264 atp_iocnak(atp
, m
, ENOBUFS
);
269 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
270 rcbp
->rc_socket
.node
= ddp
->dst_node
;
271 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
272 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
273 rcbp
->rc_bitmap
= 0xff;
275 ATDISABLE(s
, atp
->atp_lock
);
276 rcbp
->rc_state
= RCB_SENDING
;
277 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
278 ATENABLE(s
, atp
->atp_lock
);
280 xcnt
= get_bds_entries(m2
);
281 if ((i
= atp_unpack_bdsp(atp
, m2
, rcbp
, xcnt
, FALSE
))) {
284 atp_iocnak(atp
, m
, i
);
287 atp_send_replies(atp
, rcbp
);
290 * send the ack back to the responder
296 case AT_ATP_GET_POLL
: {
298 gbuf_freem(gbuf_cont(m
));
300 iocbp
->ioc_count
= 0;
304 * search for a waiting request
306 ATDISABLE(s
, atp
->atp_lock
);
307 if ((rcbp
= atp
->atp_attached
.head
)) {
309 * Got one, move it to the active response Q
311 gbuf_cont(m
) = rcbp
->rc_ioctl
;
312 rcbp
->rc_ioctl
= NULL
;
314 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
315 rcbp
->rc_state
= RCB_NOTIFIED
;
316 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
318 /* detach rcbp from attached queue,
319 * and free any outstanding resources
323 ATENABLE(s
, atp
->atp_lock
);
327 * None available - can out
329 ATENABLE(s
, atp
->atp_lock
);
330 atp_iocnak(atp
, m
, EAGAIN
);
335 case AT_ATP_CANCEL_REQUEST
: {
337 * Cancel a pending request
339 if (iocbp
->ioc_count
!= sizeof(int)) {
340 atp_iocnak(atp
, m
, EINVAL
);
343 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
344 gbuf_freem(gbuf_cont(m
));
346 ATDISABLE(s
, atp
->atp_lock
);
347 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
348 if (trp
->tr_tid
== i
)
352 ATENABLE(s
, atp
->atp_lock
);
353 atp_iocnak(atp
, m
, ENOENT
);
355 ATENABLE(s
, atp
->atp_lock
);
364 if (atalk_peek(gref
, &event
) == -1)
365 atp_iocnak(atp
, m
, EAGAIN
);
367 *gbuf_rptr(gbuf_cont(m
)) = event
;
373 case DDP_IOC_GET_CFG
:
374 #ifdef APPLETALK_DEBUG
375 kprintf("atp_wput: DDP_IOC_GET_CFG\n");
377 if (gbuf_cont(m
) == 0) {
378 atp_iocnak(atp
, m
, EINVAL
);
382 /* *** was ddp_get_cfg() *** */
384 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(m
));
385 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
386 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
387 cfgp
->inet
.socket
= atp
->atp_socket_no
;
388 cfgp
->ddptype
= DDP_ATP
;
390 cfgp
->inet
.net
= atp
->atp_gref
->laddr
.s_net
;
391 cfgp
->inet
.node
= atp
->atp_gref
->laddr
.s_node
;
392 cfgp
->inet
.socket
= atp
->atp_gref
->lport
;
393 cfgp
->ddptype
= atp
->atp_gref
->ddptype
;
396 gbuf_wset(gbuf_cont(m
), sizeof(ddp_addr_t
));
402 * Otherwise pass it on, if possible
404 iocbp
->ioc_private
= (void *)gref
;
416 gbuf_t
*atp_build_release(trp
)
417 register struct atp_trans
*trp
;
420 register at_ddp_t
*ddp
;
421 register at_atp_t
*athp
;
424 * Now try and allocate enough space to send the message
425 * if none is available the caller will schedule
426 * a timeout so we can retry for more space soon
428 if ((m
= (gbuf_t
*)gbuf_alloc(AT_WR_OFFSET
+ATP_HDR_SIZE
, PRI_HI
)) != NULL
) {
429 gbuf_rinc(m
,AT_WR_OFFSET
);
430 gbuf_wset(m
,TOTAL_ATP_HDR_SIZE
);
433 UAS_ASSIGN(ddp
->checksum
, 0);
434 ddp
->dst_socket
= trp
->tr_socket
.socket
;
435 ddp
->dst_node
= trp
->tr_socket
.node
;
436 NET_ASSIGN(ddp
->dst_net
, trp
->tr_socket
.net
);
437 ddp
->src_node
= trp
->tr_local_node
;
438 NET_NET(ddp
->src_net
, trp
->tr_local_net
);
441 * clear the cmd/xo/eom/sts/unused fields
443 athp
= AT_ATP_HDR(m
);
444 ATP_CLEAR_CONTROL(athp
);
445 athp
->cmd
= ATP_CMD_TREL
;
446 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
452 void atp_send_replies(atp
, rcbp
)
453 register struct atp_state
*atp
;
454 register struct atp_rcb
*rcbp
;
455 { register gbuf_t
*m
;
457 int s_gen
, s
, cnt
, err
, offset
, space
;
458 unsigned char *m0_rptr
= NULL
, *m0_wptr
= NULL
;
459 register at_atp_t
*athp
;
460 register struct atpBDS
*bdsp
;
461 register gbuf_t
*m2
, *m1
, *m0
, *mhdr
;
463 gbuf_t
*mprev
, *mlist
= 0;
464 at_socket src_socket
= (at_socket
)atp
->atp_socket_no
;
465 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
467 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
469 struct timeval timenow
;
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
;
500 if (gbuf_len(m
) > TOTAL_ATP_HDR_SIZE
)
501 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
506 space
= gbuf_msgsize(m0
);
509 for (i
= 0; i
< cnt
; i
++) {
510 if (rcbp
->rc_snd
[i
] == 0) {
511 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
))) {
517 /* setup header fields */
518 gbuf_rinc(mhdr
,AT_WR_OFFSET
);
519 gbuf_wset(mhdr
,TOTAL_ATP_HDR_SIZE
);
520 *(struct ddp_atp
*)(gbuf_rptr(mhdr
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
521 athp
= AT_ATP_HDR(mhdr
);
522 ATP_CLEAR_CONTROL(athp
);
523 athp
->cmd
= ATP_CMD_TRESP
;
526 athp
->eom
= 1; /* for the last fragment */
528 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
529 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)) && m0
!= 0 && space
> 0) {
530 if ((m1
= m_copym(m0
, offset
, len
, M_DONTWAIT
)) == 0) {
531 for (i
= 0; i
< cnt
; i
++)
533 gbuf_freem(rc_xmt
[i
]);
534 goto nothing_to_send
;
538 gbuf_cont(mhdr
) = m1
;
542 AT_DDP_HDR(mhdr
)->src_socket
= src_socket
;
543 dPrintf(D_M_ATP_LOW
, D_L_OUTPUT
,
544 ("atp_send_replies: %d, socket=%d, size=%d\n",
545 i
, atp
->atp_socket_no
, gbuf_msgsize(gbuf_cont(m2
))));
548 gbuf_next(mprev
) = mhdr
;
554 rcbp
->rc_not_sent_bitmap
&= ~atp_mask
[i
];
555 if (rcbp
->rc_not_sent_bitmap
== 0)
559 * on to the next frag
564 ATENABLE(s
, atp
->atp_lock
);
566 ATDISABLE(s
, atp
->atp_lock
);
571 * If all replies from this reply block have been sent then
572 * remove it from the queue and mark it so
574 if (rcbp
->rc_queue
!= atp
) {
575 ATENABLE(s
, atp
->atp_lock
);
578 rcbp
->rc_rep_waiting
= 0;
581 * If we are doing execute once re-set the rcb timeout
582 * each time we send back any part of the response. Note
583 * that this timer is started when an initial request is
584 * received. Each response reprimes the timer. Duplicate
585 * requests do not reprime the timer.
587 * We have sent all of a response so free the
590 if (rcbp
->rc_xo
&& rcbp
->rc_state
!= RCB_RELEASED
) {
591 getmicrouptime(&timenow
);
592 ATDISABLE(s_gen
, atpgen_lock
);
593 if (rcbp
->rc_timestamp
== 0) {
594 rcbp
->rc_timestamp
= timenow
.tv_sec
;
595 if (rcbp
->rc_timestamp
== 0)
596 rcbp
->rc_timestamp
= 1;
597 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
599 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
600 ATENABLE(s_gen
, atpgen_lock
);
603 ATENABLE(s
, atp
->atp_lock
);
604 } /* atp_send_replies */
608 atp_pack_bdsp(trp
, bdsp
)
609 register struct atp_trans
*trp
;
610 register struct atpBDS
*bdsp
;
612 register gbuf_t
*m
= NULL
;
613 register int i
, datsize
= 0;
614 struct atpBDS
*bdsbase
= bdsp
;
617 dPrintf(D_M_ATP
, D_L_INFO
, ("atp_pack_bdsp: socket=%d\n",
618 trp
->tr_queue
->atp_socket_no
));
620 for (i
= 0; i
< ATP_TRESP_MAX
; i
++, bdsp
++) {
621 unsigned short bufsize
= UAS_VALUE(bdsp
->bdsBuffSz
);
622 long bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
);
624 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
627 /* discard ddp hdr on first packet */
629 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
631 /* this field may contain control information even when
632 no data is present */
633 UAL_UAL(bdsp
->bdsUserData
,
634 (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
635 gbuf_rinc(m
, ATP_HDR_SIZE
);
637 if ((bufsize
!= 0) && (bufaddr
!= 0)) {
638 /* user expects data back */
640 register char *buf
= (char *)bufaddr
;
643 unsigned short len
= (unsigned short)(gbuf_len(m
));
647 if ((error
= copyout((caddr_t
)gbuf_rptr(m
),
648 CAST_USER_ADDR_T(&buf
[tmp
]),
658 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
661 gbuf_freem(trp
->tr_rcv
[i
]);
662 trp
->tr_rcv
[i
] = NULL
;
665 /* report the number of packets */
666 UAS_ASSIGN(((struct atpBDS
*)bdsbase
)->bdsBuffSz
, i
);
668 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
672 } /* atp_pack_bdsp */
675 /* create an mbuf chain with mbuf packet headers for each ATP response packet
676 * to be sent. m contains the DDP hdr, ATP hdr, and and array of atpBDS structs.
677 * chained to m is an mbuf that contians the actual data pointed to by the atpBDS
681 atp_unpack_bdsp(atp
, m
, rcbp
, cnt
, wait
)
682 struct atp_state
*atp
;
683 gbuf_t
*m
; /* ddp, atp and bdsp gbuf_t */
684 register struct atp_rcb
*rcbp
;
685 register int cnt
, wait
;
687 register struct atpBDS
*bdsp
;
688 register gbuf_t
*m2
, *m1
, *m0
, *mhdr
;
692 at_socket src_socket
;
695 char ddp_atp_hdr
[TOTAL_ATP_HDR_SIZE
];
697 gbuf_t
*mprev
, *mlist
= 0;
698 gbuf_t
*rc_xmt
[ATP_TRESP_MAX
];
699 unsigned char *m0_rptr
, *m0_wptr
;
700 int err
, offset
, space
;
701 struct timeval timenow
;
704 * get the user data structure pointer
706 bdsp
= (struct atpBDS
*)(AT_ATP_HDR(m
)->data
);
709 * Guard against bogus count argument.
711 if ((unsigned) cnt
> ATP_TRESP_MAX
) {
712 dPrintf(D_M_ATP
, D_L_ERROR
,
713 ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt
));
717 if ((src_socket
= (at_socket
)atp
->atp_socket_no
) == 0xFF) {
718 /* comparison was to -1, however src_socket is a u_char */
725 rcbp
->rc_pktcnt
= cnt
;
726 rcbp
->rc_state
= RCB_SENDING
;
727 rcbp
->rc_not_sent_bitmap
= 0;
731 * special case this to
732 * improve AFP write transactions to the server
735 if ((m2
= gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
,
738 gbuf_rinc(m2
,AT_WR_OFFSET
);
739 gbuf_wset(m2
,TOTAL_ATP_HDR_SIZE
);
740 *(struct ddp_atp
*)(gbuf_rptr(m2
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
741 athp
= AT_ATP_HDR(m2
);
742 ATP_CLEAR_CONTROL(athp
);
743 athp
->cmd
= ATP_CMD_TRESP
;
745 athp
->eom
= 1; /* there's only 1 fragment */
747 /* *** why only if cnt > 0? *** */
749 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
751 if (!append_copy((struct mbuf
*)m2
,
752 (struct mbuf
*)m0
, wait
)) {
757 * send the message and mark it as sent
759 AT_DDP_HDR(m2
)->src_socket
= src_socket
;
760 dPrintf(D_M_ATP_LOW
, D_L_INFO
,
761 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
762 0,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(m2
)),cnt
));
767 /* create an array of mbuf packet headers for the packets to be sent
768 * to contain the atp and ddp headers with room at the front for the
771 for (i
= 0; i
< cnt
; i
++) {
772 /* all hdrs, packet data and dst addr storage */
774 gbuf_alloc_wait(AT_WR_OFFSET
+TOTAL_ATP_HDR_SIZE
, wait
)) == NULL
) {
775 for (cnt
= 0; cnt
< i
; cnt
++)
777 gbuf_freeb(rc_xmt
[cnt
]);
782 /* run through the atpBDS structs and create an mbuf for the data
783 * portion of each packet to be sent. these get chained to the mbufs
784 * containing the ATP and DDP headers. this code assumes that no ATP
785 * packet is contained in more than 2 mbufs (e.i crosses mbuf boundary
786 * no more than one time).
790 space
= gbuf_msgsize(m0
);
791 for (i
= 0; i
< cnt
; i
++) { /* for each hdr mbuf */
793 /* setup header fields */
794 gbuf_rinc(mhdr
,AT_WR_OFFSET
);
795 gbuf_wset(mhdr
,TOTAL_ATP_HDR_SIZE
);
796 *(struct ddp_atp
*)(gbuf_rptr(mhdr
))= *(struct ddp_atp
*)(gbuf_rptr(m
));
797 athp
= AT_ATP_HDR(mhdr
);
798 ATP_CLEAR_CONTROL(athp
);
799 athp
->cmd
= ATP_CMD_TRESP
;
802 athp
->eom
= 1; /* for the last fragment */
803 UAL_UAL(athp
->user_bytes
, bdsp
->bdsUserData
);
805 if ((len
= UAS_VALUE(bdsp
->bdsBuffSz
)) != 0 && m0
!= 0 && space
> 0) {
806 if ((m1
= m_copym(m0
, offset
, len
, wait
)) == 0) {
807 for (i
= 0; i
< cnt
; i
++)
809 gbuf_freem(rc_xmt
[i
]);
812 gbuf_cont(mhdr
) = m1
;
817 AT_DDP_HDR(mhdr
)->src_socket
= src_socket
;
818 dPrintf(D_M_ATP_LOW
,D_L_INFO
,
819 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
820 i
,atp
->atp_socket_no
,gbuf_msgsize(gbuf_cont(mhdr
)),cnt
));
822 gbuf_next(mprev
) = mhdr
;
827 * on to the next frag
836 getmicrouptime(&timenow
);
837 ATDISABLE(s_gen
, atpgen_lock
);
838 if (rcbp
->rc_timestamp
== 0) {
839 if ((rcbp
->rc_timestamp
= timenow
.tv_sec
) == 0)
840 rcbp
->rc_timestamp
= 1;
841 ATP_Q_APPEND(atp_need_rel
, rcbp
, rc_tlist
);
843 ATENABLE(s_gen
, atpgen_lock
);
849 } /* atp_unpack_bdsp */
851 #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6)
852 #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
853 static unsigned int sNext
= 0;
855 int atp_bind(gref
, sVal
, flag
)
860 extern unsigned char asp_inpC
[];
861 extern asp_scb_t
*asp_scbQ
[];
862 unsigned char inpC
, sNextUsed
= 0;
863 unsigned int sMin
, sMax
, sSav
;
864 struct atp_state
*atp
;
867 atp
= (struct atp_state
*)gref
->info
;
869 atp
= (struct atp_state
*)atp
->atp_msgq
;
871 sMax
= ATP_SOCKET_LAST
;
872 sMin
= ATP_SOCKET_FIRST
;
873 ATDISABLE(s
, atpgen_lock
);
874 if (flag
&& (*flag
== 3)) {
883 ((sVal
> sMax
) || (sVal
< 2) || (sVal
== 6) ||
884 (ddp_socket_inuse(sVal
, DDP_ATP
) &&
885 (atp_inputQ
[sVal
] != (gref_t
*)1)))) {
886 ATENABLE(s
, atpgen_lock
);
893 for (sVal
=sMin
; sVal
<= sMax
; sVal
++) {
894 if (!ddp_socket_inuse(sVal
, DDP_ATP
) ||
895 atp_inputQ
[sVal
] == (gref_t
*)1)
897 else if (flag
&& (*flag
== 3) && asp_scbQ
[sVal
]) {
898 if ((asp_scbQ
[sVal
]->dflag
== *flag
)
899 && (asp_inpC
[sVal
] < inpC
) ) {
900 inpC
= asp_inpC
[sVal
];
906 if (flag
&& (*flag
== 3)) {
910 sMin
= ATP_SOCKET_FIRST
+40;
914 *flag
= (unsigned char)sSav
;
916 ATENABLE(s
, atpgen_lock
);
920 atp
->atp_socket_no
= (short)sVal
;
921 atp_inputQ
[sVal
] = gref
;
923 atp_pidM
[sVal
] = atp
->atp_pid
;
924 else if (*flag
== 3) {
926 if (sNext
> ATP_SOCKET_LAST
)
930 ATENABLE(s
, atpgen_lock
);
934 void atp_req_ind(atp
, mioc
)
935 register struct atp_state
*atp
;
936 register gbuf_t
*mioc
;
938 register struct atp_rcb
*rcbp
;
941 if ((rcbp
= atp
->atp_attached
.head
) != 0) {
942 gbuf_cont(mioc
) = rcbp
->rc_ioctl
;
943 rcbp
->rc_ioctl
= NULL
;
944 ATDISABLE(s
, atp
->atp_lock
);
946 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
947 rcbp
->rc_state
= RCB_NOTIFIED
;
948 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
951 ATENABLE(s
, atp
->atp_lock
);
953 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
955 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
956 asp_ack_reply(atp
->atp_gref
, mioc
);
961 void atp_rsp_ind(trp
, mioc
)
962 register struct atp_trans
*trp
;
963 register gbuf_t
*mioc
;
965 register struct atp_state
*atp
= trp
->tr_queue
;
971 switch (trp
->tr_state
) {
973 if (asp_pack_bdsp(trp
, &xm
) < 0)
975 gbuf_cont(mioc
) = trp
->tr_xmt
;
990 dPrintf(D_M_ATP
, D_L_ERROR
,
991 ("atp_rsp_ind: TRANSACTION error\n"));
992 atp_iocnak(atp
, mioc
, err
);
994 gbuf_cont(gbuf_cont(mioc
)) = xm
;
995 atp_iocack(atp
, mioc
);
1000 void atp_cancel_req(gref
, tid
)
1005 struct atp_state
*atp
;
1006 struct atp_trans
*trp
;
1008 atp
= (struct atp_state
*)gref
->info
;
1010 atp
= (struct atp_state
*)atp
->atp_msgq
;
1012 ATDISABLE(s
, atp
->atp_lock
);
1013 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1014 if (trp
->tr_tid
== tid
)
1017 ATENABLE(s
, atp
->atp_lock
);
1023 * remove atp from the use list
1026 atp_dequeue_atp(atp
)
1027 struct atp_state
*atp
;
1031 ATDISABLE(s
, atpall_lock
);
1032 if (atp
== atp_used_list
) {
1033 if ((atp_used_list
= atp
->atp_trans_waiting
) != 0)
1034 atp
->atp_trans_waiting
->atp_rcb_waiting
= 0;
1035 } else if (atp
->atp_rcb_waiting
) {
1036 if ((atp
->atp_rcb_waiting
->atp_trans_waiting
1037 = atp
->atp_trans_waiting
) != 0)
1038 atp
->atp_trans_waiting
->atp_rcb_waiting
= atp
->atp_rcb_waiting
;
1041 atp
->atp_trans_waiting
= 0;
1042 atp
->atp_rcb_waiting
= 0;
1043 ATENABLE(s
, atpall_lock
);
1047 atp_timout(func
, trp
, ticks
)
1049 struct atp_trans
*trp
;
1054 struct atp_trans
*curr_trp
, *prev_trp
;
1056 ATDISABLE(s
, atptmo_lock
);
1057 if (trp
->tr_tmo_func
) {
1058 ATENABLE(s
, atptmo_lock
);
1062 trp
->tr_tmo_func
= func
;
1063 trp
->tr_tmo_delta
= 1+(ticks
>>5);
1065 if (trp_tmo_list
== 0) {
1066 trp
->tr_tmo_next
= trp
->tr_tmo_prev
= 0;
1068 ATENABLE(s
, atptmo_lock
);
1073 curr_trp
= trp_tmo_list
;
1077 sum
+= curr_trp
->tr_tmo_delta
;
1078 if (sum
> trp
->tr_tmo_delta
) {
1079 sum
-= curr_trp
->tr_tmo_delta
;
1080 trp
->tr_tmo_delta
-= sum
;
1081 curr_trp
->tr_tmo_delta
-= trp
->tr_tmo_delta
;
1084 prev_trp
= curr_trp
;
1085 if ((curr_trp
= curr_trp
->tr_tmo_next
) == 0) {
1086 trp
->tr_tmo_delta
-= sum
;
1092 trp
->tr_tmo_prev
= prev_trp
;
1093 if ((trp
->tr_tmo_next
= prev_trp
->tr_tmo_next
) != 0)
1094 prev_trp
->tr_tmo_next
->tr_tmo_prev
= trp
;
1095 prev_trp
->tr_tmo_next
= trp
;
1097 trp
->tr_tmo_prev
= 0;
1098 trp
->tr_tmo_next
= trp_tmo_list
;
1099 trp_tmo_list
->tr_tmo_prev
= trp
;
1102 ATENABLE(s
, atptmo_lock
);
1106 atp_untimout(func
, trp
)
1108 struct atp_trans
*trp
;
1112 ATDISABLE(s
, atptmo_lock
);
1113 if (trp
->tr_tmo_func
== 0) {
1114 ATENABLE(s
, atptmo_lock
);
1118 if (trp_tmo_list
== trp
) {
1119 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0) {
1120 trp_tmo_list
->tr_tmo_prev
= 0;
1121 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1124 if ((trp
->tr_tmo_prev
->tr_tmo_next
= trp
->tr_tmo_next
) != 0) {
1125 trp
->tr_tmo_next
->tr_tmo_prev
= trp
->tr_tmo_prev
;
1126 trp
->tr_tmo_next
->tr_tmo_delta
+= trp
->tr_tmo_delta
;
1129 trp
->tr_tmo_func
= 0;
1130 ATENABLE(s
, atptmo_lock
);
1134 atp_trp_clock_locked(arg
)
1147 struct atp_trans
*trp
;
1148 void (*tr_tmo_func
)();
1150 ATDISABLE(s
, atptmo_lock
);
1152 trp_tmo_list
->tr_tmo_delta
--;
1153 while (((trp
= trp_tmo_list
) != 0) && (trp_tmo_list
->tr_tmo_delta
== 0)) {
1154 if ((trp_tmo_list
= trp
->tr_tmo_next
) != 0)
1155 trp_tmo_list
->tr_tmo_prev
= 0;
1156 if ((tr_tmo_func
= trp
->tr_tmo_func
) != 0) {
1157 trp
->tr_tmo_func
= 0;
1158 ATENABLE(s
, atptmo_lock
);
1159 (*tr_tmo_func
)(trp
);
1160 ATDISABLE(s
, atptmo_lock
);
1163 ATENABLE(s
, atptmo_lock
);
1165 timeout(atp_trp_clock_locked
, (void *)arg
, (1<<5));
1169 atp_send_req(gref
, mioc
)
1173 register struct atp_state
*atp
;
1174 register struct atp_trans
*trp
;
1175 register ioc_t
*iocbp
;
1176 register at_atp_t
*athp
;
1177 register at_ddp_t
*ddp
;
1178 gbuf_t
*m
, *m2
, *bds
;
1179 struct atp_set_default
*sdb
;
1183 atp
= (struct atp_state
*)((struct atp_state
*)gref
->info
)->atp_msgq
;
1184 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1186 if ((trp
= atp_trans_alloc(atp
)) == NULL
) {
1188 ((asp_scb_t
*)gref
->info
)->stat_msg
= mioc
;
1189 iocbp
->ioc_private
= (void *)gref
;
1190 timeout(atp_retry_req
, mioc
, 10);
1194 m2
= gbuf_cont(mioc
);
1195 if ((bds
= gbuf_dupb(m2
)) == NULL
) {
1196 atp_trans_free(trp
);
1199 gbuf_rinc(m2
,atpBDSsize
);
1200 gbuf_wset(bds
,atpBDSsize
);
1201 iocbp
->ioc_count
-= atpBDSsize
;
1202 gbuf_cont(m2
) = NULL
;
1204 old
= iocbp
->ioc_cmd
;
1205 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
1206 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1209 * The at_snd_req library routine multiplies seconds by 100.
1210 * We need to divide by 100 in order to obtain the timer.
1212 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1214 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1215 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1217 trp
->tr_retry
= sdb
->def_retries
;
1218 trp
->tr_timeout
= timer
;
1220 trp
->tr_tid
= atp_tid(atp
);
1224 * Now fill in the header (and remember the bits
1227 athp
= AT_ATP_HDR(m2
);
1228 athp
->cmd
= ATP_CMD_TREQ
;
1229 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1232 trp
->tr_xo
= athp
->xo
;
1233 trp
->tr_bitmap
= athp
->bitmap
;
1234 ddp
= AT_DDP_HDR(m2
);
1235 ddp
->type
= DDP_ATP
;
1236 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1237 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1238 trp
->tr_socket
.node
= ddp
->dst_node
;
1239 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1240 trp
->tr_local_socket
= atp
->atp_socket_no
;
1241 trp
->tr_local_node
= ddp
->src_node
;
1242 NET_NET(trp
->tr_local_net
, ddp
->src_net
);
1245 /* save the local information in the gref */
1246 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1247 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1248 atp
->atp_gref
->lport
= ddp
->src_node
;
1249 atp
->atp_gref
->ddptype
= DDP_ATP
;
1253 * Put us in the transaction waiting queue
1255 ATDISABLE(s
, atp
->atp_lock
);
1256 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1257 ATENABLE(s
, atp
->atp_lock
);
1260 * Send the message and set the timer
1262 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1263 if (!trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1264 atp_x_done(trp
); /* no reason to tie up resources */
1266 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1268 trace_mbufs(D_M_ATP_LOW
, " s", m
);
1271 } /* atp_send_req */
1273 void atp_retry_req(arg
)
1276 gbuf_t
*m
= (gbuf_t
*)arg
;
1281 gref
= (gref_t
*)((ioc_t
*)gbuf_rptr(m
))->ioc_private
;
1283 ((asp_scb_t
*)gref
->info
)->stat_msg
= 0;
1284 atp_send_req(gref
, m
);
1289 void atp_send_rsp(gref
, m
, wait
)
1294 register struct atp_state
*atp
;
1295 register struct atp_rcb
*rcbp
;
1296 register at_atp_t
*athp
;
1297 register at_ddp_t
*ddp
;
1300 atp
= (struct atp_state
*)gref
->info
;
1302 atp
= (struct atp_state
*)atp
->atp_msgq
;
1303 ddp
= AT_DDP_HDR(m
);
1304 athp
= AT_ATP_HDR(m
);
1307 * search for the corresponding rcb
1309 ATDISABLE(s
, atp
->atp_lock
);
1310 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1311 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1312 (rcbp
->rc_socket
.node
== ddp
->dst_node
) &&
1313 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->dst_net
)) &&
1314 (rcbp
->rc_socket
.socket
== ddp
->dst_socket
) )
1319 * If it has already been sent then drop the request
1321 if ((rcbp
&& (rcbp
->rc_state
!= RCB_NOTIFIED
)) ||
1322 (rcbp
== NULL
&& athp
->xo
) ) {
1323 ATENABLE(s
, atp
->atp_lock
);
1327 ATENABLE(s
, atp
->atp_lock
);
1329 if (rcbp
== NULL
) { /* a response is being sent for an ALO transaction */
1330 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
1335 rcbp
->rc_socket
.socket
= ddp
->dst_socket
;
1336 rcbp
->rc_socket
.node
= ddp
->dst_node
;
1337 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->dst_net
);
1338 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
1339 rcbp
->rc_bitmap
= 0xff;
1341 rcbp
->rc_state
= RCB_RESPONSE_FULL
;
1342 ATDISABLE(s
, atp
->atp_lock
);
1343 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1344 ATENABLE(s
, atp
->atp_lock
);
1346 else if (ddp
->src_node
== 0) {
1347 NET_NET(ddp
->src_net
, rcbp
->rc_local_net
);
1348 ddp
->src_node
= rcbp
->rc_local_node
;
1351 xcnt
= get_bds_entries(m
);
1352 s
= atp_unpack_bdsp(atp
, m
, rcbp
, xcnt
, wait
);
1354 atp_send_replies(atp
, rcbp
);
1355 } /* atp_send_rsp */
1357 int asp_pack_bdsp(trp
, xm
)
1358 register struct atp_trans
*trp
;
1361 register struct atpBDS
*bdsp
;
1362 register gbuf_t
*m
, *m2
;
1364 gbuf_t
*m_prev
, *m_head
= 0;
1366 dPrintf(D_M_ATP
, D_L_INFO
, ("asp_pack_bdsp: socket=%d\n",
1367 trp
->tr_queue
->atp_socket_no
));
1369 if ((m2
= trp
->tr_bdsp
) == NULL
)
1371 trp
->tr_bdsp
= NULL
;
1372 bdsp
= (struct atpBDS
*)gbuf_rptr(m2
);
1374 for (i
= 0; (i
< ATP_TRESP_MAX
&&
1375 bdsp
< (struct atpBDS
*)(gbuf_wptr(m2
))); i
++) {
1376 if ((m
= trp
->tr_rcv
[i
]) == NULL
)
1379 /* discard ddp hdr on first packet */
1380 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
1383 UAL_UAL(bdsp
->bdsUserData
, (((at_atp_t
*)(gbuf_rptr(m
)))->user_bytes
));
1384 gbuf_rinc(m
, ATP_HDR_SIZE
);
1386 if (UAL_VALUE(bdsp
->bdsBuffAddr
)) {
1389 /* user expects data back */
1394 gbuf_cont(m_prev
) = m
;
1396 tmp
= (short)gbuf_len(m
);
1397 while (gbuf_cont(m
)) {
1399 tmp
+= (short)(gbuf_len(m
));
1403 UAS_ASSIGN(bdsp
->bdsDataSz
, tmp
);
1405 trp
->tr_rcv
[i
] = NULL
;
1410 * report the number of packets
1412 UAS_ASSIGN(((struct atpBDS
*)gbuf_rptr(m2
))->bdsBuffSz
, i
);
1414 if (trp
->tr_xmt
) /* an ioctl block is still held? */
1415 gbuf_cont(trp
->tr_xmt
) = m2
;
1424 dPrintf(D_M_ATP
, D_L_INFO
, (" : size=%d\n",
1425 gbuf_msgsize(*xm
)));
1431 * The following routines are direct entries from system
1432 * calls to allow fast sending and recving of ATP data.
1436 _ATPsndreq(fd
, buf
, len
, nowait
, err
, proc
)
1448 register struct atp_state
*atp
;
1449 register struct atp_trans
*trp
;
1450 register ioc_t
*iocbp
;
1451 register at_atp_t
*athp
;
1452 register at_ddp_t
*ddp
;
1453 struct atp_set_default
*sdb
;
1454 gbuf_t
*m2
, *m
, *mioc
;
1455 char bds
[atpBDSsize
];
1457 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1460 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1461 || (atp
->atp_flags
& ATP_CLOSING
)) {
1462 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
1463 (u_int
) gref
, gref
->pid
));
1470 while ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_MED
)) == 0) {
1472 /* the vaue of 10n terms of hz is 100ms */
1474 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1476 ATDISABLE(s
, atp
->atp_delay_lock
);
1477 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpmioc", &ts
);
1478 ATENABLE(s
, atp
->atp_delay_lock
);
1486 gbuf_wset(mioc
,sizeof(ioc_t
));
1488 while ((m2
= gbuf_alloc(len
, PRI_MED
)) == 0) {
1490 /* the vaue of 10n terms of hz is 100ms */
1492 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1494 ATDISABLE(s
, atp
->atp_delay_lock
);
1495 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpm2", &ts
);
1496 ATENABLE(s
, atp
->atp_delay_lock
);
1505 gbuf_cont(mioc
) = m2
;
1506 if (((*err
= copyin(CAST_USER_ADDR_T(buf
), (caddr_t
)bds
, atpBDSsize
)) != 0)
1507 || ((*err
= copyin(CAST_USER_ADDR_T(&buf
[atpBDSsize
]),
1508 (caddr_t
)gbuf_rptr(m2
), len
)) != 0)) {
1513 gbuf_set_type(mioc
, MSG_IOCTL
);
1514 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1515 iocbp
->ioc_count
= len
;
1516 iocbp
->ioc_cmd
= nowait
? AT_ATP_ISSUE_REQUEST_NOTE
: AT_ATP_ISSUE_REQUEST
;
1517 sdb
= (struct atp_set_default
*)gbuf_rptr(m2
);
1520 * The at_snd_req library routine multiplies seconds by 100.
1521 * We need to divide by 100 in order to obtain the timer.
1523 if ((timer
= (sdb
->def_rate
* HZ
)/100) == 0)
1525 iocbp
->ioc_count
-= sizeof(struct atp_set_default
);
1526 gbuf_rinc(m2
,sizeof(struct atp_set_default
));
1529 * allocate and set up the transaction record
1531 while ((trp
= atp_trans_alloc(atp
)) == 0) {
1533 /* the vaue of 10n terms of hz is 100ms */
1535 ts
.tv_nsec
= 100 *1000 * NSEC_PER_USEC
;
1537 ATDISABLE(s
, atp
->atp_delay_lock
);
1538 rc
= msleep(&atp
->atp_delay_event
, atalk_mutex
, PSOCK
| PCATCH
, "atptrp", &ts
);
1539 ATENABLE(s
, atp
->atp_delay_lock
);
1547 trp
->tr_retry
= sdb
->def_retries
;
1548 trp
->tr_timeout
= timer
;
1549 trp
->tr_bdsp
= NULL
;
1550 trp
->tr_tid
= atp_tid(atp
);
1554 * remember the IOCTL packet so we can ack it
1560 * Now fill in the header (and remember the bits
1563 athp
= AT_ATP_HDR(m2
);
1564 athp
->cmd
= ATP_CMD_TREQ
;
1565 UAS_ASSIGN(athp
->tid
, trp
->tr_tid
);
1568 trp
->tr_xo
= athp
->xo
;
1569 trp
->tr_bitmap
= athp
->bitmap
;
1570 ddp
= AT_DDP_HDR(m2
);
1571 ddp
->type
= DDP_ATP
;
1572 ddp
->src_socket
= (at_socket
)atp
->atp_socket_no
;
1574 trp
->tr_socket
.socket
= ddp
->dst_socket
;
1575 trp
->tr_socket
.node
= ddp
->dst_node
;
1576 trp
->tr_socket
.net
= NET_VALUE(ddp
->dst_net
);
1577 trp
->tr_local_socket
= atp
->atp_socket_no
;
1580 /* save the local information in the gref */
1581 atp
->atp_gref
->laddr
.s_net
= NET_VALUE(ddp
->src_net
);
1582 atp
->atp_gref
->laddr
.s_node
= ddp
->src_node
;
1583 atp
->atp_gref
->lport
= ddp
->src_node
;
1584 atp
->atp_gref
->ddptype
= DDP_ATP
;
1588 * Put us in the transaction waiting queue
1590 ATDISABLE(s
, atp
->atp_lock
);
1591 ATP_Q_APPEND(atp
->atp_trans_wait
, trp
, tr_list
);
1592 ATENABLE(s
, atp
->atp_lock
);
1595 * Send the message and set the timer
1597 m
= (gbuf_t
*)copy_pkt(m2
, sizeof(llc_header_t
));
1598 if ( !trp
->tr_retry
&& !trp
->tr_bitmap
&& !trp
->tr_xo
)
1599 atp_x_done(trp
); /* no reason to tie up resources */
1601 atp_timout(atp_req_timeout
, trp
, trp
->tr_timeout
);
1611 * wait for the transaction to complete
1613 ATDISABLE(s
, trp
->tr_lock
);
1614 while ((trp
->tr_state
!= TRANS_DONE
) && (trp
->tr_state
!= TRANS_FAILED
) &&
1615 (trp
->tr_state
!= TRANS_ABORTING
)) {
1616 trp
->tr_rsp_wait
= 1;
1617 rc
= msleep(&trp
->tr_event
, atalk_mutex
, PSOCK
| PCATCH
, "atpsndreq", 0);
1619 trp
->tr_rsp_wait
= 0;
1620 ATENABLE(s
, trp
->tr_lock
);
1626 trp
->tr_rsp_wait
= 0;
1627 ATENABLE(s
, trp
->tr_lock
);
1630 if (trp
->tr_state
== TRANS_FAILED
|| trp
->tr_state
== TRANS_ABORTING
) {
1632 * transaction timed out, return error
1641 * copy out the recv data
1643 if ((*err
= atp_pack_bdsp(trp
, (struct atpBDS
*)bds
)) != 0) {
1650 * copyout the result info
1652 if ((*err
= copyout((caddr_t
)bds
, CAST_USER_ADDR_T(buf
), atpBDSsize
)) != 0) {
1665 /* entry point for ATP send response. respbuf contains a DDP hdr,
1666 * ATP hdr, and atpBDS array. The bdsDataSz field of the first atpBDS
1667 * struct contains the number of atpBDS structs in the array. resplen
1668 * contains the len of the data in respbuf and datalen contains the
1669 * len of the data buffer holding the response packets which the atpBDS
1670 * struct entries point to.
1673 _ATPsndrsp(fd
, respbuff
, resplen
, datalen
, err
, proc
)
1675 unsigned char *respbuff
;
1687 struct atp_state
*atp
;
1688 struct atpBDS
*bdsp
;
1691 int bds_cnt
, count
, len
;
1694 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1697 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1698 || (atp
->atp_flags
& ATP_CLOSING
)) {
1699 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
1700 (u_int
) gref
, gref
->pid
));
1708 * allocate buffer and copy in the response info
1710 if ((m
= gbuf_alloc_wait(resplen
, TRUE
)) == 0) {
1715 if ((*err
= copyin(CAST_USER_ADDR_T(respbuff
), (caddr_t
)gbuf_rptr(m
), resplen
)) != 0) {
1720 gbuf_wset(m
,resplen
);
1721 ((at_ddp_t
*)gbuf_rptr(m
))->src_node
= 0;
1722 bdsp
= (struct atpBDS
*)(gbuf_rptr(m
) + TOTAL_ATP_HDR_SIZE
);
1725 * allocate buffers and copy in the response data.
1726 * note that only the size field of the atpBDS field
1727 * is used internally in the kernel.
1729 bds_cnt
= get_bds_entries(m
); /* count of # entries */
1730 /* check correctness of parameters */
1731 if (bds_cnt
> ATP_TRESP_MAX
) {
1738 for (size
= 0, count
= 0; count
< bds_cnt
; count
++) {
1739 size
+= UAS_VALUE(bdsp
[count
].bdsBuffSz
);
1741 if (size
> datalen
) {
1748 /* get the first mbuf */
1749 if ((mdata
= gbuf_alloc_wait((space
= (size
> MCLBYTES
? MCLBYTES
: size
)), TRUE
)) == 0) {
1755 gbuf_cont(m
) = mdata
;
1756 dataptr
= mtod(mdata
, caddr_t
);
1757 for (count
= 0; count
< bds_cnt
; bdsp
++, count
++) {
1758 if ((bufaddr
= UAL_VALUE(bdsp
->bdsBuffAddr
)) != 0 &&
1759 (len
= UAS_VALUE(bdsp
->bdsBuffSz
)) != 0) {
1760 if (len
> space
) { /* enough room ? */
1761 gbuf_wset(mdata
, dataptr
- mtod(mdata
, caddr_t
)); /* set len of last mbuf */
1762 /* allocate the next mbuf */
1763 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
1769 mdata
= gbuf_cont(mdata
);
1770 MCLGET(mdata
, M_WAIT
);
1771 if (!(mdata
->m_flags
& M_EXT
)) {
1776 dataptr
= mtod(mdata
, caddr_t
);
1780 if ((*err
= copyin(CAST_USER_ADDR_T(bufaddr
), dataptr
, len
)) != 0) {
1789 gbuf_wset(mdata
, dataptr
- mtod(mdata
, caddr_t
)); /* set len of last mbuf */
1790 gbuf_cont(m
)->m_pkthdr
.len
= size
; /* set packet hdr len */
1792 atp_send_rsp(gref
, m
, TRUE
);
1798 _ATPgetreq(fd
, buf
, buflen
, err
, proc
)
1806 register struct atp_state
*atp
;
1807 register struct atp_rcb
*rcbp
;
1808 register gbuf_t
*m
, *m_head
;
1811 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1814 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1815 || (atp
->atp_flags
& ATP_CLOSING
)) {
1816 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
1817 (u_int
) gref
, gref
->pid
));
1823 ATDISABLE(s
, atp
->atp_lock
);
1824 if ((rcbp
= atp
->atp_attached
.head
) != NULL
) {
1826 * Got one, move it to the active response Q
1828 m_head
= rcbp
->rc_ioctl
;
1829 rcbp
->rc_ioctl
= NULL
;
1832 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
1833 rcbp
->rc_state
= RCB_NOTIFIED
;
1834 ATP_Q_APPEND(atp
->atp_rcb
, rcbp
, rc_list
);
1836 /* detach rcbp from attached queue,
1837 * and free any outstanding resources
1841 ATENABLE(s
, atp
->atp_lock
);
1844 * copyout the request data, including the protocol header
1846 for (size
=0, m
=m_head
; m
; m
= gbuf_cont(m
)) {
1847 if ((len
= gbuf_len(m
)) > buflen
)
1849 copyout((caddr_t
)gbuf_rptr(m
), CAST_USER_ADDR_T(&buf
[size
]), len
);
1851 if ((buflen
-= len
) == 0)
1859 ATENABLE(s
, atp
->atp_lock
);
1866 _ATPgetrsp(fd
, bdsp
, err
, proc
)
1868 struct atpBDS
*bdsp
;
1873 register struct atp_state
*atp
;
1874 register struct atp_trans
*trp
;
1876 char bds
[atpBDSsize
];
1878 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) != 0)
1881 if ((gref
== 0) || ((atp
= (struct atp_state
*)gref
->info
) == 0)
1882 || (atp
->atp_flags
& ATP_CLOSING
)) {
1883 dPrintf(D_M_ATP
, D_L_ERROR
, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
1884 (u_int
) gref
, gref
->pid
));
1890 ATDISABLE(s
, atp
->atp_lock
);
1891 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
1892 dPrintf(D_M_ATP
, D_L_INFO
,
1893 ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
1894 (u_int
) atp
, (u_int
) trp
, trp
->tr_state
));
1896 switch (trp
->tr_state
) {
1898 ATENABLE(s
, atp
->atp_lock
);
1899 if ((*err
= copyin(CAST_USER_ADDR_T(bdsp
),
1900 (caddr_t
)bds
, sizeof(bds
))) != 0) {
1905 if ((*err
= atp_pack_bdsp(trp
, (struct atpBDS
*)bds
)) != 0) {
1910 tid
= (int)trp
->tr_tid
;
1912 if ((*err
= copyout((caddr_t
)bds
, CAST_USER_ADDR_T(bdsp
), sizeof(bds
))) != 0) {
1921 * transaction timed out, return error
1923 ATENABLE(s
, atp
->atp_lock
);
1933 ATENABLE(s
, atp
->atp_lock
);
1941 atp_drop_req(gref
, m
)
1946 struct atp_state
*atp
;
1947 struct atp_rcb
*rcbp
;
1951 atp
= (struct atp_state
*)gref
->info
;
1953 atp
= (struct atp_state
*)atp
->atp_msgq
;
1954 ddp
= AT_DDP_HDR(m
);
1955 athp
= AT_ATP_HDR(m
);
1958 * search for the corresponding rcb
1960 ATDISABLE(s
, atp
->atp_lock
);
1961 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
1962 if ( (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
)) &&
1963 (rcbp
->rc_socket
.node
== ddp
->src_node
) &&
1964 (rcbp
->rc_socket
.net
== NET_VALUE(ddp
->src_net
)) &&
1965 (rcbp
->rc_socket
.socket
== ddp
->src_socket
) )
1974 ATENABLE(s
, atp
->atp_lock
);