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