]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/atp_open.c
16f2a8eb08c2ad298745aca99533fa7b2b94caf9
[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
62 /**********/
63 int atp_pidM[256];
64 gref_t *atp_inputQ[256];
65 struct atp_state *atp_used_list;
66
67 int atp_input(mp)
68 gbuf_t *mp;
69 {
70 register gref_t *gref;
71
72 switch (gbuf_type(mp)) {
73 case MSG_DATA:
74 gref = atp_inputQ[((at_ddp_t *)gbuf_rptr(mp))->dst_socket];
75 if ((gref == 0) || (gref == (gref_t *)1)) {
76 dPrintf(D_M_ATP, D_L_WARNING, ("atp_input: no socket, skt=%d\n",
77 ((at_ddp_t *)gbuf_rptr(mp))->dst_socket));
78 gbuf_freem(mp);
79 return 0;
80 }
81 break;
82
83 case MSG_IOCACK:
84 case MSG_IOCNAK:
85 gref = (gref_t *)((ioc_t *)gbuf_rptr(mp))->ioc_private;
86 break;
87
88 case MSG_IOCTL:
89 default:
90 dPrintf(D_M_ATP, D_L_WARNING, ("atp_input: unknown msg, type=%d\n",
91 gbuf_type(mp)));
92 gbuf_freem(mp);
93 return 0;
94 }
95
96 atp_rput(gref, mp);
97 return 0;
98 }
99
100 /**********/
101 void atp_init()
102 {
103 int i;
104
105 if (!atp_inited) {
106 atp_inited = 1;
107 atp_used_list = 0;
108 atp_trans_abort.head = NULL;
109 atp_trans_abort.tail = NULL;
110
111 atp_need_rel.head = NULL;
112 atp_need_rel.tail = NULL;
113
114 bzero(atp_inputQ, sizeof(atp_inputQ));
115 bzero(atp_pidM, sizeof(atp_pidM));
116 asp_init();
117 }
118 }
119
120 /*
121 * The open routine allocates a state structure
122 */
123
124 /*ARGSUSED*/
125 int atp_open(gref, flag)
126 gref_t *gref;
127 int flag;
128 {
129 register struct atp_state *atp;
130 register int i;
131 vm_offset_t temp;
132
133 /*
134 * Allocate and init state and reply control block lists
135 * if this is the first open
136 */
137 if (atp_rcb_data == NULL) {
138 if (kmem_alloc(kernel_map, &temp, sizeof(struct atp_rcb) * NATP_RCB) != KERN_SUCCESS)
139 return(ENOMEM);
140 if (atp_rcb_data == NULL) {
141 bzero((caddr_t)temp, sizeof(struct atp_rcb) * NATP_RCB);
142 atp_rcb_data = (struct atp_rcb*)temp;
143 for (i = 0; i < NATP_RCB; i++) {
144 atp_rcb_data[i].rc_list.next = atp_rcb_free_list;
145 atp_rcb_free_list = &atp_rcb_data[i];
146 }
147 } else
148 kmem_free(kernel_map, temp, sizeof(struct atp_rcb) * NATP_RCB); /* already allocated by another process */
149 }
150
151 if (atp_state_data == NULL) {
152 if (kmem_alloc(kernel_map, &temp, sizeof(struct atp_state) * NATP_STATE) != KERN_SUCCESS)
153 return(ENOMEM);
154 if (atp_state_data == NULL) {
155 bzero((caddr_t)temp, sizeof(struct atp_state) * NATP_STATE);
156 atp_state_data = (struct atp_state*) temp;
157 for (i = 0; i < NATP_STATE; i++) {
158 atp_state_data[i].atp_trans_waiting = atp_free_list;
159 atp_free_list = &atp_state_data[i];
160 }
161 } else
162 kmem_free(kernel_map, temp, sizeof(struct atp_state) * NATP_STATE);
163 }
164
165
166 /*
167 * If no atp structure available return failure
168 */
169
170 if ((atp = atp_free_list) == NULL)
171 return(EAGAIN);
172
173 /*
174 * Update free list
175 */
176
177 atp_free_list = atp->atp_trans_waiting;
178
179 /*
180 * Initialize the data structure
181 */
182
183 atp->dflag = 0;
184 atp->atp_trans_wait.head = NULL;
185 atp->atp_trans_waiting = NULL;
186 atp->atp_gref = gref;
187 atp->atp_retry = 10;
188 atp->atp_timeout = HZ/8;
189 atp->atp_rcb_waiting = NULL;
190 atp->atp_rcb.head = NULL;
191 atp->atp_flags = T_MPSAFE;
192 atp->atp_socket_no = -1;
193 atp->atp_pid = gref->pid;
194 atp->atp_msgq = 0;
195 ATEVENTINIT(atp->atp_event);
196 ATEVENTINIT(atp->atp_delay_event);
197 gref->info = (void *)atp;
198
199 /*
200 * Return success
201 */
202
203 if (flag) {
204 if ((atp->atp_trans_waiting = atp_used_list) != 0)
205 atp->atp_trans_waiting->atp_rcb_waiting = atp;
206 atp_used_list = atp;
207 }
208 return(0);
209 }
210
211 /*
212 * The close routine frees all the data structures
213 */
214
215 /*ARGSUSED*/
216 int atp_close(gref, flag)
217 gref_t *gref;
218 int flag;
219 {
220 extern void atp_req_timeout();
221 register struct atp_state *atp;
222 register struct atp_trans *trp;
223 register struct atp_rcb *rcbp;
224 int socket;
225 pid_t pid;
226
227 atp = (struct atp_state *)gref->info;
228 if (atp->dflag)
229 atp = (struct atp_state *)atp->atp_msgq;
230 if (atp->atp_msgq) {
231 gbuf_freem(atp->atp_msgq);
232 atp->atp_msgq = 0;
233 }
234
235 atp->atp_flags |= ATP_CLOSING;
236 socket = atp->atp_socket_no;
237 if (socket != -1)
238 atp_inputQ[socket] = (gref_t *)1;
239
240 /*
241 * blow away all pending timers
242 */
243 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next)
244 atp_untimout(atp_req_timeout, trp);
245
246 /*
247 * Release pending transactions + rcbs
248 */
249 while ((trp = atp->atp_trans_wait.head))
250 atp_free(trp);
251 while ((rcbp = atp->atp_rcb.head))
252 atp_rcb_free(rcbp);
253 while ((rcbp = atp->atp_attached.head))
254 atp_rcb_free(rcbp);
255
256 if (flag && (socket == -1))
257 atp_dequeue_atp(atp);
258
259 /*
260 * free the state variable
261 */
262 atp->atp_socket_no = -1;
263 atp->atp_trans_waiting = atp_free_list;
264 atp_free_list = atp;
265
266 if (socket != -1) {
267 pid = (pid_t)atp_pidM[socket];
268 atp_pidM[socket] = 0;
269 atp_inputQ[socket] = NULL;
270 if (pid)
271 ddp_notify_nbp(socket, pid, DDP_ATP);
272 }
273
274 return 0;
275 }