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