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