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