]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/adsp_Open.c
xnu-792.21.3.tar.gz
[apple/xnu.git] / bsd / netat / adsp_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 /* adspOpen.c v01.20
29 *
30 * From v01.20 08/23/90 Mike Shoemaker for MacOS
31 * Modified for MP, 1996 by Tuyen Nguyen
32 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
33 */
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/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/time.h>
48
49 #include <netat/sysglue.h>
50 #include <netat/appletalk.h>
51 #include <netat/at_pcb.h>
52 #include <netat/debug.h>
53 #include <netat/adsp.h>
54 #include <netat/adsp_internal.h>
55
56 extern atlock_t adspgen_lock;
57
58 /*
59 * NextCID
60 *
61 * Create a unique connection ID.
62 *
63 * INPUTS:
64 * none
65 * OUTPUTS:
66 * unique connection ID
67 */
68 unsigned short NextCID()
69 {
70 int s;
71 unsigned short num;
72 register CCB *queue;
73
74 while (1) {
75 ATDISABLE(s, adspgen_lock); /* Disable interrupts */
76 num = ++adspGlobal.lastCID;
77 /* qfind_w below is in 68K assembly */
78 /* point to the first element */
79 queue = (CCB *)AT_ADSP_STREAMS;
80 while (queue) {
81 /* and scan .. */
82 if (queue->locCID == num)
83 break;
84 queue = queue->ccbLink;
85 }
86 ATENABLE(s, adspgen_lock);
87 if (queue == (CCBPtr)NULL)
88 break;
89 }
90 return num;
91 }
92
93 static byte xlateStateTbl[4] = /* The value to be given to the CCB's state. */
94 { /* indexed by ocMode */
95 sOpening, /* ocRequest */
96 sPassive, /* ocPassive */
97 sOpening, /* ocAccept */
98 sOpen /* ocEstablish */
99 };
100 static byte xlateOpenTbl[4] = /* Value to use for open state. */
101 { /* indexed by ocMode */
102 O_STATE_OPENWAIT, /* ocRequest */
103 O_STATE_LISTEN, /* ocPassive */
104 O_STATE_ESTABLISHED, /* ocAccept */
105 O_STATE_OPEN /* ocEstablish */
106 };
107
108 /*
109 * adspOpen
110 *
111 * INPUTS:
112 * --> ccbRefNum refnum of connection end
113 * --> remoteCID connection id of remote connection end
114 * --> remoteAddress internet address of remote connection end
115 * --> filterAddress filter for incoming open connection requests
116 * --> sendSeq initial send sequence number to use
117 * --> sendWindow initial size of remote end's receive buffer
118 * --> recvSeq initial receive sequence number to use
119 * --> attnSendSeq initial attention send sequence number
120 * --> attnRecvSeq initial receive sequence number
121 * --> ocMode connection opening mode
122 * --> ocMaximum maximum retries of open connection request
123 *
124 * OUTPUTS:
125 * <-- localCID connection identifier of this connection end
126 * <-- remoteCID connection id of remote connection end
127 * <-- remoteAddress
128 * <-- sendSeq
129 * <-- sendWindow
130 * <-- attnSendSeq
131 *
132 * ERRORS:
133 * errRefNum bad connection refnum
134 * errState connection end must be closed
135 * errOpening open connection attempt failed
136 * errAborted request aborted by a remove or close call
137 */
138 int adspOpen(sp, pb) /* (DSPPBPtr pb) */
139 register CCBPtr sp;
140 register struct adspcmd *pb;
141 {
142 extern int adsp_pidM[];
143
144 int ocMode;
145 register gbuf_t *mp;
146
147 if (sp == 0) {
148 pb->ioResult = errRefNum; /* Unknown refnum */
149 return EINVAL;
150 }
151
152 if ((sp->state != sClosed) ||
153 (sp->removing)) { /* The CCB must be closed */
154 pb->ioResult = errState;
155 return EALREADY;
156 }
157
158 ocMode = pb->u.openParams.ocMode; /* get a local copy of open mode */
159 if (ocMode == ocRequest)
160 adsp_pidM[pb->socket] = 0;
161
162 /*
163 * Save parameters. Fill in defaults if zero
164 */
165 if (pb->u.openParams.ocInterval)
166 sp->openInterval = pb->u.openParams.ocInterval;
167 else
168 sp->openInterval = ocIntervalDefault;
169
170 if (pb->u.openParams.ocMaximum)
171 sp->openRetrys = pb->u.openParams.ocMaximum;
172 else
173 sp->openRetrys = ocMaximumDefault;
174
175 sp->remoteAddress = *((AddrUnionPtr)&pb->u.openParams.remoteAddress);
176 /* Not used for passive */
177 /*
178 * Clear out send/receive buffers.
179 */
180 if (sp->sbuf_mb) { /* clear the send queue */
181 gbuf_freel(sp->sbuf_mb);
182 sp->sbuf_mb = 0;
183 }
184 if (sp->csbuf_mb) {
185 gbuf_freem(sp->csbuf_mb);
186 sp->csbuf_mb = 0;
187 }
188 if (sp->rbuf_mb) { /* clear the receive queue */
189 gbuf_freel(sp->rbuf_mb);
190 sp->rbuf_mb = 0;
191 }
192 if (sp->crbuf_mb) {
193 gbuf_freem(sp->crbuf_mb);
194 sp->crbuf_mb = 0;
195 }
196
197 sp->rData = 0; /* Flag both buffers as empty */
198 sp->sData = 0;
199 sp->recvQPending = 0; /* No bytes in receive queue */
200
201 /*
202 * Clear all of those pesky flags
203 */
204 sp->userFlags = 0;
205 sp->sendDataAck = 0;
206 sp->sendAttnAck = 0;
207 sp->sendAttnData = 0;
208 sp->callSend = 0;
209 sp->removing = 0;
210 sp->writeFlush = 0;
211
212 /*
213 * Reset round-trip timers
214 */
215 sp->roundTrip = sp->rtmtInterval;
216 sp->deviation = 0;
217
218 /*
219 * Reset stuff for retransmit advice packet
220 */
221 sp->badSeqCnt = 0;
222 /*
223 * Reset flow control variables
224 */
225 sp->pktSendMax = 1; /* Slow start says we should set this to 1 */
226 sp->pktSendCnt = 0;
227 sp->rbufFull = 0;
228 sp->resentData = 0;
229 sp->noXmitFlow = 0;
230 sp->waitingAck = 0;
231
232 /*
233 * Copy required information out of parameter block
234 */
235 if (ocMode == ocAccept || ocMode == ocEstablish) {
236 sp->remCID = pb->u.openParams.remoteCID;
237 sp->sendSeq = sp->firstRtmtSeq = pb->u.openParams.sendSeq;
238 sp->sendWdwSeq = sp->sendSeq + pb->u.openParams.sendWindow;
239 sp->attnSendSeq = pb->u.openParams.attnSendSeq;
240 } else { /* accept or establish */
241 sp->remCID = 0;
242 sp->sendSeq = 0;
243 sp->sendWdwSeq = 0;
244 sp->attnSendSeq = 0;
245 }
246
247 if (ocMode == ocEstablish) { /* Only set these if establish mode */
248 sp->recvSeq = pb->u.openParams.recvSeq;
249 sp->attnRecvSeq = pb->u.openParams.attnRecvSeq;
250 UAS_ASSIGN(sp->f.CID, sp->locCID); /* Preset the CID in the ADSP header */
251 /* This is done elsewhere for all other modes */
252 InsertTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer,
253 sp->probeInterval);
254 } else { /* establish */
255 /* All other modes need a CID assigned */
256 sp->locCID = NextCID();
257 sp->recvSeq = 0;
258 sp->attnRecvSeq = 0;
259 }
260
261 /*
262 * Now set the state variables for this CCB.
263 */
264
265 sp->openState = xlateOpenTbl[ocMode-ocRequest];
266 sp->state = xlateStateTbl[ocMode-ocRequest];
267
268 if (ocMode == ocEstablish) { /* For establish call, we're done */
269 pb->ioResult = 0;
270 adspioc_ack(0, pb->ioc, pb->gref);
271 return 0;
272 }
273
274 pb->qLink = 0; /* Clear link field before putting on queue */
275 mp = gbuf_copym(pb->mp); /* Save parameter block to match later */
276
277 if (mp == 0) {
278 pb->ioResult = errDSPQueueSize;
279 return ENOBUFS;
280 }
281 pb->ioResult = 1; /* not open -> not done */
282 adspioc_ack(0, pb->ioc, pb->gref); /* release user */
283 sp->opb = (struct adspcmd *)gbuf_rptr(mp);
284 sp->opb->ioc = 0; /* unlink saved pb from ioctl block */
285 sp->opb->mp = mp;
286
287 /*
288 * For request & accept, need to send a packet
289 */
290 if ((ocMode == ocRequest) || (ocMode == ocAccept)) {
291 sp->sendCtl |= (1 << (ocMode == ocRequest ?
292 ADSP_CTL_OREQ : ADSP_CTL_OREQACK));
293 CheckSend(sp);
294 }
295 return 0;
296 }
297
298 int adspMode(pb)
299 register struct adspcmd *pb;
300 {
301 return pb->u.openParams.ocMode;
302 }