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@
22 /* Modified for MP, 1996 by Tuyen Nguyen */
24 * tcb (transaction) allocation routine. If no transaction data structure
25 * is available then put the module on a queue of modules waiting
26 * for transaction structures. When a tcb is available it will be
27 * removed from this list and its write queue will be scheduled.
28 * Version 1.4 of atp_alloc.c on 89/02/09 17:53:01
29 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
31 #include <sys/errno.h>
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <machine/spl.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
38 #include <sys/filedesc.h>
39 #include <sys/fcntl.h>
41 #include <sys/socket.h>
43 #include <netat/sysglue.h>
44 #include <netat/appletalk.h>
45 #include <netat/ddp.h>
46 #include <netat/debug.h>
47 #include <netat/at_pcb.h>
48 #include <netat/atp.h>
50 /*### MacOSX MCLBYTE is 2048, not 4096 like AIX */
51 #define TRPS_PER_BLK 16
53 gbuf_t
*atp_resource_m
= 0;
54 extern atlock_t atpgen_lock
;
56 struct atp_trans
*atp_trans_alloc(atp
)
57 struct atp_state
*atp
;
62 register struct atp_trans
*trp
, *trp_array
;
64 ATDISABLE(s
, atpgen_lock
);
65 if (atp_trans_free_list
== 0) {
66 ATENABLE(s
, atpgen_lock
);
67 if ((m
= gbuf_alloc(TRPS_PER_BLK
*sizeof(struct atp_trans
),PRI_HI
)) == 0)
68 return (struct atp_trans
*)0;
69 bzero(gbuf_rptr(m
), TRPS_PER_BLK
*sizeof(struct atp_trans
));
70 trp_array
= (struct atp_trans
*)gbuf_rptr(m
);
71 for (i
=0; i
< TRPS_PER_BLK
-1; i
++)
72 trp_array
[i
].tr_list
.next
= (struct atp_trans
*)&trp_array
[i
+1];
73 ATDISABLE(s
, atpgen_lock
);
74 gbuf_cont(m
) = atp_resource_m
;
76 trp_array
[i
].tr_list
.next
= atp_trans_free_list
;
77 atp_trans_free_list
= (struct atp_trans
*)&trp_array
[0];
80 trp
= atp_trans_free_list
;
81 atp_trans_free_list
= trp
->tr_list
.next
;
82 ATENABLE(s
, atpgen_lock
);
84 trp
->tr_state
= TRANS_TIMEOUT
;
85 trp
->tr_local_node
= 0;
86 ATLOCKINIT(trp
->tr_lock
);
87 ATEVENTINIT(trp
->tr_event
);
89 dPrintf(D_M_ATP_LOW
, D_L_TRACE
,
90 ("atp_trans_alloc(0x%x): alloc'd trp 0x%x\n",
91 (u_int
) atp
, (u_int
) trp
));
93 } /* atp_trans_alloc */
96 * tcb free routine - if modules are waiting schedule them
97 * always called at 'lock'
100 void atp_trans_free(trp
)
101 register struct atp_trans
*trp
;
105 ATDISABLE(s
, atpgen_lock
);
107 trp
->tr_list
.next
= atp_trans_free_list
;
108 atp_trans_free_list
= trp
;
109 ATENABLE(s
, atpgen_lock
);
113 * This routine allocates a rcb, if none are available it makes sure the
114 * the write service routine will be called when one is
115 * always called at 'lock'
118 struct atp_rcb
*atp_rcb_alloc(atp
)
119 struct atp_state
*atp
;
121 register struct atp_rcb
*rcbp
;
124 ATDISABLE(s
, atpgen_lock
);
125 if ((rcbp
= atp_rcb_free_list
) != NULL
) {
126 atp_rcb_free_list
= rcbp
->rc_list
.next
;
127 rcbp
->rc_queue
= atp
;
129 rcbp
->rc_local_node
= 0;
131 ATENABLE(s
, atpgen_lock
);
132 dPrintf(D_M_ATP_LOW
, D_L_TRACE
,
133 ("atp_rcb_alloc: allocated rcbp 0x%x\n", (u_int
) rcbp
));
138 * Here we free rcbs, if required reschedule other people waiting for them
139 * always called at 'lock'
142 void atp_rcb_free(rcbp
)
143 register struct atp_rcb
*rcbp
;
145 register struct atp_state
*atp
;
147 register int rc_state
;
150 dPrintf(D_M_ATP_LOW
, D_L_TRACE
,
151 ("atp_rcb_free: freeing rcbp 0x%x\n", (u_int
) rcbp
));
152 ATDISABLE(s
, atpgen_lock
);
153 atp
= rcbp
->rc_queue
;
154 if ((rc_state
= rcbp
->rc_state
) == -1) {
155 ATENABLE(s
, atpgen_lock
);
156 dPrintf(D_M_ATP
, D_L_WARNING
,
157 ("atp_rcb_free(%d): tid=%d,loc=%d,rem=%d\n",
159 rcbp
->rc_socket
.socket
, atp
->atp_socket_no
));
166 if (rcbp
->rc_timestamp
) {
167 extern struct atp_rcb_qhead atp_need_rel
;
169 rcbp
->rc_timestamp
= 0;
170 ATP_Q_REMOVE(atp_need_rel
, rcbp
, rc_tlist
);
171 rcbp
->rc_tlist
.prev
= NULL
;
172 rcbp
->rc_tlist
.next
= NULL
;
176 gbuf_freem(rcbp
->rc_xmt
); /* *** bad free is the second mbuf in this chain *** */
178 for (i
=0; i
< rcbp
->rc_pktcnt
; i
++)
181 if (rc_state
!= RCB_UNQUEUED
) {
182 if (rc_state
== RCB_PENDING
) {
183 ATP_Q_REMOVE(atp
->atp_attached
, rcbp
, rc_list
);
185 ATP_Q_REMOVE(atp
->atp_rcb
, rcbp
, rc_list
);
188 if (rcbp
->rc_ioctl
) {
189 gbuf_freem(rcbp
->rc_ioctl
);
190 rcbp
->rc_ioctl
= NULL
;
192 rcbp
->rc_list
.next
= atp_rcb_free_list
;
193 atp_rcb_free_list
= rcbp
;
194 ATENABLE(s
, atpgen_lock
);