2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1996-1998 Apple Computer, Inc.
32 * All Rights Reserved.
35 /* Modified for MP, 1996 by Tuyen Nguyen
36 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
38 #include <sys/errno.h>
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <machine/spl.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
45 #include <sys/filedesc.h>
46 #include <sys/fcntl.h>
48 #include <sys/ioctl.h>
49 #include <sys/malloc.h>
50 #include <sys/socket.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/debug.h>
59 static void atp_trans_complete();
61 void atp_x_done_locked(void *);
62 extern void atp_req_timeout();
65 * Decide what to do about received messages
66 * Version 1.7 of atp_read.c on 89/02/09 17:53:16
69 void atp_treq_event(void *arg
)
71 register gref_t
*gref
= (gref_t
*)arg
;
73 register struct atp_state
*atp
;
76 atp
= (struct atp_state
*)gref
->info
;
78 atp
= (struct atp_state
*)atp
->atp_msgq
;
81 if ((m
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) != NULL
) {
82 gbuf_set_type(m
, MSG_IOCTL
);
83 gbuf_wset(m
,sizeof(ioc_t
));
84 ((ioc_t
*)gbuf_rptr(m
))->ioc_cmd
= AT_ATP_GET_POLL
;
88 else if ((m
= gbuf_alloc(1, PRI_HI
)) != NULL
) {
91 atalk_putnext(gref
, m
);
95 timeout(atp_treq_event
, gref
, 10);
99 void atp_rput(gref
, m
)
103 register at_atp_t
*athp
;
104 register struct atp_state
*atp
;
105 register int s
, s_gen
;
106 gbuf_t
*m_asp
= NULL
;
107 struct timeval timenow
;
109 atp
= (struct atp_state
*)gref
->info
;
111 atp
= (struct atp_state
*)atp
->atp_msgq
;
113 switch(gbuf_type(m
)) {
116 * Decode the message, make sure it is an atp
119 if (((AT_DDP_HDR(m
))->type
!= DDP_ATP
) ||
120 (atp
->atp_flags
& ATP_CLOSING
)) {
122 dPrintf(D_M_ATP_LOW
, (D_L_INPUT
|D_L_ERROR
),
123 ("atp_rput: dropping MSG, not atp\n"));
127 athp
= AT_ATP_HDR(m
);
128 dPrintf(D_M_ATP_LOW
, D_L_INPUT
,
129 ("atp_rput MSG_DATA: %s (%d)\n",
130 (athp
->cmd
== ATP_CMD_TRESP
)? "TRESP":
131 (athp
->cmd
== ATP_CMD_TREL
)? "TREL":
132 (athp
->cmd
== ATP_CMD_TREQ
)? "TREQ": "unknown",
134 trace_mbufs(D_M_ATP_LOW
, " r", m
);
140 register struct atp_trans
*trp
;
142 register at_ddp_t
*ddp
;
145 * we just got a response, find the trans record
148 ATDISABLE(s
, atp
->atp_lock
);
149 for (trp
= atp
->atp_trans_wait
.head
; trp
; trp
= trp
->tr_list
.next
) {
150 if (trp
->tr_tid
== UAS_VALUE(athp
->tid
))
155 * If we can't find one then ignore the message
157 seqno
= athp
->bitmap
;
159 ATENABLE(s
, atp
->atp_lock
);
161 dPrintf(D_M_ATP_LOW
, (D_L_INPUT
|D_L_ERROR
),
162 ("atp_rput: dropping TRESP, no trp,tid=%d,loc=%d,rem=%d.%d,seqno=%d\n",
163 UAS_VALUE(athp
->tid
),
164 ddp
->dst_socket
,ddp
->src_node
,ddp
->src_socket
,seqno
));
170 * If no longer valid, drop it
172 if (trp
->tr_state
== TRANS_FAILED
) {
173 ATENABLE(s
, atp
->atp_lock
);
175 dPrintf(D_M_ATP_LOW
, (D_L_INPUT
|D_L_ERROR
),
176 ("atp_rput: dropping TRESP, failed trp,tid=%d,loc=%d,rem=%d.%d\n",
177 UAS_VALUE(athp
->tid
),
178 ddp
->dst_socket
, ddp
->src_node
, ddp
->src_socket
));
184 * If we have already received it, ignore it
186 if (!(trp
->tr_bitmap
&atp_mask
[seqno
]) || trp
->tr_rcv
[seqno
]) {
187 ATENABLE(s
, atp
->atp_lock
);
189 dPrintf(D_M_ATP_LOW
, (D_L_INPUT
|D_L_ERROR
),
190 ("atp_rput: dropping TRESP, duplicate,tid=%d,loc=%d,rem=%d.%d,seqno=%d\n",
191 UAS_VALUE(athp
->tid
),
192 ddp
->dst_socket
, ddp
->src_node
, ddp
->src_socket
, seqno
));
198 * Update the received packet bitmap
201 trp
->tr_bitmap
&= atp_lomask
[seqno
];
203 trp
->tr_bitmap
&= ~atp_mask
[seqno
];
206 * Save the message in the trans record
208 trp
->tr_rcv
[seqno
] = m
;
211 * If it isn't the first message then
215 gbuf_rinc(m
,DDP_X_HDR_SIZE
);
218 * If we now have all the responses then return
219 * the message to the user
221 if (trp
->tr_bitmap
== 0) {
222 ATENABLE(s
, atp
->atp_lock
);
225 * Cancel the request timer and any
228 atp_untimout(atp_req_timeout
, trp
);
231 * Send the results back to the user
238 * If they want treq again, send them
240 ATENABLE(s
, atp
->atp_lock
);
241 atp_untimout(atp_req_timeout
, trp
);
245 ATENABLE(s
, atp
->atp_lock
);
250 { register struct atp_rcb
*rcbp
;
251 register at_ddp_t
*ddp
;
254 * Search for a matching transaction
258 ATDISABLE(s
, atp
->atp_lock
);
259 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
260 if (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
) &&
261 rcbp
->rc_socket
.node
== ddp
->src_node
&&
262 rcbp
->rc_socket
.net
== NET_VALUE(ddp
->src_net
) &&
263 rcbp
->rc_socket
.socket
== ddp
->src_socket
) {
265 * Mark the rcb released
267 rcbp
->rc_not_sent_bitmap
= 0;
268 if (rcbp
->rc_state
== RCB_SENDING
)
269 rcbp
->rc_state
= RCB_RELEASED
;
274 ATENABLE(s
, atp
->atp_lock
);
281 ATENABLE(s
, atp
->atp_lock
);
288 { register struct atp_rcb
*rcbp
;
289 register at_ddp_t
*ddp
;
293 * If it is a request message, first
295 * if matches something in our active
300 ATDISABLE(s
, atp
->atp_lock
);
301 for (rcbp
= atp
->atp_rcb
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
302 if (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
) &&
303 rcbp
->rc_socket
.node
== ddp
->src_node
&&
304 rcbp
->rc_socket
.net
== NET_VALUE(ddp
->src_net
) &&
305 rcbp
->rc_socket
.socket
== ddp
->src_socket
)
309 * If this is a new req then do
314 * see if it matches something in the
315 * attached request queue
316 * if it does, just release the message
317 * and go on about our buisness
319 /* we just did this, why do again? -jjs 4-10-95 */
320 for (rcbp
= atp
->atp_attached
.head
; rcbp
; rcbp
= rcbp
->rc_list
.next
) {
321 if (rcbp
->rc_tid
== UAS_VALUE(athp
->tid
) &&
322 rcbp
->rc_socket
.node
== ddp
->src_node
&&
323 rcbp
->rc_socket
.net
== NET_VALUE(ddp
->src_net
) &&
324 rcbp
->rc_socket
.socket
== ddp
->src_socket
) {
325 ATENABLE(s
, atp
->atp_lock
);
327 dPrintf(D_M_ATP_LOW
, D_L_INPUT
,
328 ("atp_rput: dropping TREQ, matches req queue\n"));
334 * assume someone is interested in
335 * in an asynchronous incoming request
337 ATENABLE(s
, atp
->atp_lock
);
338 if ((rcbp
= atp_rcb_alloc(atp
)) == NULL
) {
342 rcbp
->rc_state
= RCB_UNQUEUED
;
343 ATDISABLE(s
, atp
->atp_lock
);
345 rcbp
->rc_local_node
= ddp
->dst_node
;
346 NET_NET(rcbp
->rc_local_net
, ddp
->dst_net
);
347 rcbp
->rc_socket
.socket
= ddp
->src_socket
;
348 rcbp
->rc_socket
.node
= ddp
->src_node
;
349 rcbp
->rc_socket
.net
= NET_VALUE(ddp
->src_net
);
350 rcbp
->rc_tid
= UAS_VALUE(athp
->tid
);
351 rcbp
->rc_bitmap
= athp
->bitmap
;
352 rcbp
->rc_not_sent_bitmap
= athp
->bitmap
;
353 rcbp
->rc_xo
= athp
->xo
;
355 * if async then send it as
357 * otherwise, it is a synchronous ioctl so
360 if (atp
->dflag
) { /* for ASP? */
361 if ((m2
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
))) {
362 gbuf_set_type(m2
, MSG_DATA
);
363 gbuf_wset(m2
,sizeof(ioc_t
));
364 ((ioc_t
*)gbuf_rptr(m2
))->ioc_cmd
= AT_ATP_GET_POLL
;
367 } else if ((m2
= gbuf_alloc(1, PRI_HI
))) {
370 atalk_putnext(gref
, m2
);
373 dPrintf(D_M_ATP
,D_L_WARNING
,
374 ("atp_rput: out of buffer for TREQ\n"));
375 timeout(atp_treq_event
, gref
, 10);
380 * move it to the attached list
382 dPrintf(D_M_ATP_LOW
, D_L_INPUT
,
383 ("atp_rput: moving to attached list\n"));
384 rcbp
->rc_state
= RCB_PENDING
;
385 ATP_Q_APPEND(atp
->atp_attached
, rcbp
, rc_list
);
387 ATENABLE(s
, atp
->atp_lock
);
388 atp_req_ind(atp
, m_asp
);
392 dPrintf(D_M_ATP_LOW
, D_L_INPUT
,
393 ("atp_rput: found match, state:%d\n",
397 * Otherwise we have found a matching request
398 * look for what to do
400 switch (rcbp
->rc_state
) {
402 case RCB_RESPONSE_FULL
:
404 * If it is one we have in progress
405 * (either have all the responses
406 * or are waiting for them)
407 * update the bitmap and resend
410 getmicrouptime(&timenow
);
411 ATDISABLE(s_gen
, atpgen_lock
);
412 if (rcbp
->rc_timestamp
) {
413 rcbp
->rc_timestamp
= timenow
.tv_sec
;
414 if (rcbp
->rc_timestamp
== 0)
415 rcbp
->rc_timestamp
= 1;
417 ATENABLE(s_gen
, atpgen_lock
);
418 rcbp
->rc_bitmap
= athp
->bitmap
;
419 rcbp
->rc_not_sent_bitmap
= athp
->bitmap
;
420 ATENABLE(s
, atp
->atp_lock
);
428 * If we have a release or
429 * we haven't sent any data yet
432 ATENABLE(s
, atp
->atp_lock
);
437 ATENABLE(s
, atp
->atp_lock
);
449 asp_ack_reply(gref
, m
);
451 atalk_putnext(gref
, m
);
456 asp_nak_reply(gref
, m
);
458 atalk_putnext(gref
, m
);
467 atp_x_done_locked(trp
)
471 atp_x_done((struct atp_trans
*)trp
);
478 register struct atp_trans
*trp
;
480 struct atp_state
*atp
;
485 atp_trans_complete(trp
);
488 * If execute once send a release
490 if ((m
= (gbuf_t
*)atp_build_release(trp
)) != NULL
) {
491 AT_DDP_HDR(m
)->src_socket
= ((struct atp_state
*)
492 trp
->tr_queue
)->atp_socket_no
;
495 * Now send back the transaction reply to the process
496 * or notify the process if required
498 atp_trans_complete(trp
);
502 trp
->tr_state
= TRANS_RELEASE
;
503 timeout(atp_x_done_locked
, trp
, 10);
509 atp_trans_complete(trp
)
510 register struct atp_trans
*trp
;
511 { register gbuf_t
*m
;
513 struct atp_state
*atp
;
515 /* we could gbuf_freem(trp->tr_xmt) here if were not planning to
516 re-use the mbuf later */
519 trp
->tr_state
= TRANS_DONE
;
521 if (gbuf_cont(m
) == NULL
) /* issued via the new interface */
522 type
= AT_ATP_ISSUE_REQUEST_NOTE
;
524 type
= ((ioc_t
*)(gbuf_rptr(m
)))->ioc_cmd
;
526 * free any data following the ioctl blk
528 gbuf_freem(gbuf_cont(m
));
531 dPrintf(D_M_ATP_LOW
, D_L_INPUT
, ("atp_trans_comp: trp=0x%x type = %s\n",
533 (type
==AT_ATP_ISSUE_REQUEST
)? "AT_ATP_ISSUE_REQUEST":
534 (type
==AT_ATP_ISSUE_REQUEST_NOTE
)? "AT_ATP_ISSUE_REQUEST_NOTE" :
538 case AT_ATP_ISSUE_REQUEST
:
541 ((ioc_t
*)gbuf_rptr(m
))->ioc_count
= 0;
542 ((ioc_t
*)gbuf_rptr(m
))->ioc_error
= 0;
543 ((ioc_t
*)gbuf_rptr(m
))->ioc_rval
= trp
->tr_tid
;
544 ((ioc_t
*)gbuf_rptr(m
))->ioc_cmd
= AT_ATP_REQUEST_COMPLETE
;
545 gbuf_set_type(m
, MSG_IOCTL
);
548 if (trp
->tr_bdsp
== NULL
) {
550 if (trp
->tr_rsp_wait
)
551 wakeup(&trp
->tr_event
);
553 gbuf_set_type(m
, MSG_IOCACK
);
554 ((ioc_t
*)gbuf_rptr(m
))->ioc_count
= 0;
555 ((ioc_t
*)gbuf_rptr(m
))->ioc_error
= 0;
556 ((ioc_t
*)gbuf_rptr(m
))->ioc_rval
= 0;
557 atalk_putnext(trp
->tr_queue
->atp_gref
, m
);
562 case AT_ATP_ISSUE_REQUEST_NOTE
:
565 gbuf_set_type(m
, MSG_DATA
);
566 atalk_putnext(trp
->tr_queue
->atp_gref
, m
);
569 } /* atp_trans_complete */