]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/atp_open.c
524a3b7f6257d625e2dd36ced37c78e96ec519b4
[apple/xnu.git] / bsd / netat / atp_open.c
1 /*
2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
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
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
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.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 /*
31 * Copyright (c) 1996-1998 Apple Computer, Inc.
32 * All Rights Reserved.
33 */
34
35 /* Modified for MP, 1996 by Tuyen Nguyen
36 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
37 */
38 #define ATP_DECLARE
39
40 #include <sys/errno.h>
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <machine/spl.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/proc.h>
47 #include <sys/filedesc.h>
48 #include <sys/fcntl.h>
49 #include <sys/mbuf.h>
50 #include <sys/ioctl.h>
51 #include <sys/malloc.h>
52 #include <sys/socket.h>
53 #include <vm/vm_kern.h> /* for kernel_map */
54
55 #include <netat/sysglue.h>
56 #include <netat/appletalk.h>
57 #include <netat/ddp.h>
58 #include <netat/at_pcb.h>
59 #include <netat/atp.h>
60 #include <netat/debug.h>
61
62 /*
63 * The init routine creates all the free lists
64 * Version 1.4 of atp_open.c on 89/02/09 17:53:11
65 */
66
67 int atp_inited = 0;
68 struct atp_rcb_qhead atp_need_rel;
69 atlock_t atpall_lock;
70 atlock_t atptmo_lock;
71 atlock_t atpgen_lock;
72
73 /**********/
74 int atp_pidM[256];
75 gref_t *atp_inputQ[256];
76 struct atp_state *atp_used_list;
77
78 int atp_input(mp)
79 gbuf_t *mp;
80 {
81 register gref_t *gref;
82
83 switch (gbuf_type(mp)) {
84 case MSG_DATA:
85 gref = atp_inputQ[((at_ddp_t *)gbuf_rptr(mp))->dst_socket];
86 if ((gref == 0) || (gref == (gref_t *)1)) {
87 dPrintf(D_M_ATP, D_L_WARNING, ("atp_input: no socket, skt=%d\n",
88 ((at_ddp_t *)gbuf_rptr(mp))->dst_socket));
89 gbuf_freem(mp);
90 return 0;
91 }
92 break;
93
94 case MSG_IOCACK:
95 case MSG_IOCNAK:
96 gref = (gref_t *)((ioc_t *)gbuf_rptr(mp))->ioc_private;
97 break;
98
99 case MSG_IOCTL:
100 default:
101 dPrintf(D_M_ATP, D_L_WARNING, ("atp_input: unknown msg, type=%d\n",
102 gbuf_type(mp)));
103 gbuf_freem(mp);
104 return 0;
105 }
106
107 atp_rput(gref, mp);
108 return 0;
109 }
110
111 /**********/
112 void atp_init()
113 {
114 int i;
115
116 if (!atp_inited) {
117 atp_inited = 1;
118 atp_used_list = 0;
119 atp_trans_abort.head = NULL;
120 atp_trans_abort.tail = NULL;
121
122 atp_need_rel.head = NULL;
123 atp_need_rel.tail = NULL;
124
125 bzero(atp_inputQ, sizeof(atp_inputQ));
126 bzero(atp_pidM, sizeof(atp_pidM));
127 asp_init();
128 }
129 }
130
131 /*
132 * The open routine allocates a state structure
133 */
134
135 /*ARGSUSED*/
136 int atp_open(gref, flag)
137 gref_t *gref;
138 int flag;
139 {
140 register struct atp_state *atp;
141 register int s, i;
142 vm_offset_t temp;
143
144 /*
145 * Allocate and init state and reply control block lists
146 * if this is the first open
147 */
148 if (atp_rcb_data == NULL) {
149 if (kmem_alloc(kernel_map, &temp, sizeof(struct atp_rcb) * NATP_RCB) != KERN_SUCCESS)
150 return(ENOMEM);
151 if (atp_rcb_data == NULL) {
152 bzero((caddr_t)temp, sizeof(struct atp_rcb) * NATP_RCB);
153 atp_rcb_data = (struct atp_rcb*)temp;
154 for (i = 0; i < NATP_RCB; i++) {
155 atp_rcb_data[i].rc_list.next = atp_rcb_free_list;
156 atp_rcb_free_list = &atp_rcb_data[i];
157 }
158 } else
159 kmem_free(kernel_map, temp, sizeof(struct atp_rcb) * NATP_RCB); /* already allocated by another process */
160 }
161
162 if (atp_state_data == NULL) {
163 if (kmem_alloc(kernel_map, &temp, sizeof(struct atp_state) * NATP_STATE) != KERN_SUCCESS)
164 return(ENOMEM);
165 if (atp_state_data == NULL) {
166 bzero((caddr_t)temp, sizeof(struct atp_state) * NATP_STATE);
167 atp_state_data = (struct atp_state*) temp;
168 for (i = 0; i < NATP_STATE; i++) {
169 atp_state_data[i].atp_trans_waiting = atp_free_list;
170 atp_free_list = &atp_state_data[i];
171 }
172 } else
173 kmem_free(kernel_map, temp, sizeof(struct atp_state) * NATP_STATE);
174 }
175
176
177 /*
178 * If no atp structure available return failure
179 */
180
181 ATDISABLE(s, atpall_lock);
182 if ((atp = atp_free_list) == NULL) {
183 ATENABLE(s, atpall_lock);
184 return(EAGAIN);
185 }
186
187 /*
188 * Update free list
189 */
190
191 atp_free_list = atp->atp_trans_waiting;
192 ATENABLE(s, atpall_lock);
193
194 /*
195 * Initialize the data structure
196 */
197
198 atp->dflag = 0;
199 atp->atp_trans_wait.head = NULL;
200 atp->atp_trans_waiting = NULL;
201 atp->atp_gref = gref;
202 atp->atp_retry = 10;
203 atp->atp_timeout = HZ/8;
204 atp->atp_rcb_waiting = NULL;
205 atp->atp_rcb.head = NULL;
206 atp->atp_flags = T_MPSAFE;
207 atp->atp_socket_no = -1;
208 atp->atp_pid = gref->pid;
209 atp->atp_msgq = 0;
210 ATLOCKINIT(atp->atp_lock);
211 ATLOCKINIT(atp->atp_delay_lock);
212 ATEVENTINIT(atp->atp_event);
213 ATEVENTINIT(atp->atp_delay_event);
214 gref->info = (void *)atp;
215
216 /*
217 * Return success
218 */
219
220 if (flag) {
221 ATDISABLE(s, atpall_lock);
222 if ((atp->atp_trans_waiting = atp_used_list) != 0)
223 atp->atp_trans_waiting->atp_rcb_waiting = atp;
224 atp_used_list = atp;
225 ATENABLE(s, atpall_lock);
226 }
227 return(0);
228 }
229
230 /*
231 * The close routine frees all the data structures
232 */
233
234 /*ARGSUSED*/
235 int atp_close(gref, flag)
236 gref_t *gref;
237 int flag;
238 {
239 extern void atp_req_timeout();
240 register struct atp_state *atp;
241 register struct atp_trans *trp;
242 register struct atp_rcb *rcbp;
243 register int s;
244 int socket;
245 pid_t pid;
246
247 atp = (struct atp_state *)gref->info;
248 if (atp->dflag)
249 atp = (struct atp_state *)atp->atp_msgq;
250 if (atp->atp_msgq) {
251 gbuf_freem(atp->atp_msgq);
252 atp->atp_msgq = 0;
253 }
254
255 ATDISABLE(s, atp->atp_lock);
256 atp->atp_flags |= ATP_CLOSING;
257 socket = atp->atp_socket_no;
258 if (socket != -1)
259 atp_inputQ[socket] = (gref_t *)1;
260
261 /*
262 * blow away all pending timers
263 */
264 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next)
265 atp_untimout(atp_req_timeout, trp);
266
267 /*
268 * Release pending transactions + rcbs
269 */
270 while ((trp = atp->atp_trans_wait.head))
271 atp_free(trp);
272 while ((rcbp = atp->atp_rcb.head))
273 atp_rcb_free(rcbp);
274 while ((rcbp = atp->atp_attached.head))
275 atp_rcb_free(rcbp);
276 ATENABLE(s, atp->atp_lock);
277
278 if (flag && (socket == -1))
279 atp_dequeue_atp(atp);
280
281 /*
282 * free the state variable
283 */
284 ATDISABLE(s, atpall_lock);
285 atp->atp_socket_no = -1;
286 atp->atp_trans_waiting = atp_free_list;
287 atp_free_list = atp;
288 ATENABLE(s, atpall_lock);
289
290 if (socket != -1) {
291 pid = (pid_t)atp_pidM[socket];
292 atp_pidM[socket] = 0;
293 atp_inputQ[socket] = NULL;
294 if (pid)
295 ddp_notify_nbp(socket, pid, DDP_ATP);
296 }
297
298 return 0;
299 }