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