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