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 56extern int *adsp_pidM; 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 70unsigned short NextCID(void) 71{ 72 unsigned short num; 73 register CCB *queue; 74 75 while (1) { 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 if (queue == (CCBPtr)NULL) 87 break; 88 } 89 return num; 90} 91 92static byte xlateStateTbl[4] = /* The value to be given to the CCB's state. */ 93{ /* indexed by ocMode */ 94 sOpening, /* ocRequest */ 95 sPassive, /* ocPassive */ 96 sOpening, /* ocAccept */ 97 sOpen /* ocEstablish */ 98}; 99static byte xlateOpenTbl[4] = /* Value to use for open state. */ 100{ /* indexed by ocMode */ 101 O_STATE_OPENWAIT, /* ocRequest */ 102 O_STATE_LISTEN, /* ocPassive */ 103 O_STATE_ESTABLISHED, /* ocAccept */ 104 O_STATE_OPEN /* ocEstablish */ 105}; 106 107/* 108 * adspOpen 109 * 110 * INPUTS: 111 * --> ccbRefNum refnum of connection end 112 * --> remoteCID connection id of remote connection end 113 * --> remoteAddress internet address of remote connection end 114 * --> filterAddress filter for incoming open connection requests 115 * --> sendSeq initial send sequence number to use 116 * --> sendWindow initial size of remote end's receive buffer 117 * --> recvSeq initial receive sequence number to use 118 * --> attnSendSeq initial attention send sequence number 119 * --> attnRecvSeq initial receive sequence number 120 * --> ocMode connection opening mode 121 * --> ocMaximum maximum retries of open connection request 122 * 123 * OUTPUTS: 124 * <-- localCID connection identifier of this connection end 125 * <-- remoteCID connection id of remote connection end 126 * <-- remoteAddress 127 * <-- sendSeq 128 * <-- sendWindow 129 * <-- attnSendSeq 130 * 131 * ERRORS: 132 * errRefNum bad connection refnum 133 * errState connection end must be closed 134 * errOpening open connection attempt failed 135 * errAborted request aborted by a remove or close call 136 */ 137int adspOpen(sp, pb) /* (DSPPBPtr pb) */ 138 register CCBPtr sp; 139 register struct adspcmd *pb; 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_HTON(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, (gbuf_t *)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, (gbuf_t *)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} 300