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