|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: ! 26: #include <adsp_local.h> ! 27: ! 28: gbuf_t *releaseData(mp, len) ! 29: gbuf_t *mp; ! 30: int len; ! 31: { ! 32: register gbuf_t *tmp; ! 33: register int cnt; ! 34: char *src; ! 35: int freeit; ! 36: ! 37: do { ! 38: freeit = 1; /* assume we use the whole mblk */ ! 39: if ((cnt = gbuf_len(mp)) > len) { ! 40: freeit = 0; /* using only part of the mblk */ ! 41: cnt = len; ! 42: } ! 43: gbuf_rinc(mp,cnt); ! 44: len -= cnt; ! 45: tmp = mp; ! 46: mp = gbuf_cont(mp); ! 47: if (freeit) { ! 48: gbuf_freeb(tmp); ! 49: } else ! 50: return tmp; /* if we don't use the whole block */ ! 51: /* pass back the partial gbuf_t pointer */ ! 52: } while (len && mp); ! 53: return mp; ! 54: } ! 55: ! 56: /* ! 57: * CheckRecvSeq ! 58: * ! 59: * We just got a non-attention packet. Check the pktNextRecvSeq field ! 60: * to see if it acknowledges any of our sent data. ! 61: * ! 62: * If any data was acked, check to see if we have anything to fill the ! 63: * newly opened up remote receive window. Otherwise, if the ACK request ! 64: * bit was set, we need to send an Ack Packet ! 65: * ! 66: * Always called as the result of receiving a packet. Interrupts ! 67: * are completely masked when this routine is called. ! 68: * ! 69: * INPUTS: ! 70: * sp stream ! 71: * f pointer to ASDP header ! 72: * OUTPUTS: ! 73: * none ! 74: */ ! 75: void CheckRecvSeq(sp, f) /* (CCBPtr sp, ADSP_FRAMEPtr f) */ ! 76: register CCBPtr sp; ! 77: register ADSP_FRAMEPtr f; ! 78: { ! 79: int s; ! 80: int pktNextRecvSeq; ! 81: int sendWdwSeq; ! 82: int eom; ! 83: int hlen; ! 84: register gbuf_t *mp; ! 85: ! 86: ATDISABLE(s, sp->lock); ! 87: if (f->descriptor & ADSP_ACK_REQ_BIT) { /* He wants an Ack */ ! 88: sp->sendDataAck = 1; ! 89: sp->callSend = 1; ! 90: } ! 91: ! 92: pktNextRecvSeq = netdw(UAL_VALUE(f->pktNextRecvSeq)); /* Local copy */ ! 93: ! 94: /* ! 95: * Make sure the sequence number corresponds to reality -- i.e. for ! 96: * unacknowledged data that we have sent ! 97: */ ! 98: ! 99: if (GT(pktNextRecvSeq, sp->maxSendSeq)) /* We've never sent this seq #! */ ! 100: goto noack; ! 101: ! 102: if (GTE(pktNextRecvSeq, sp->timerSeq) && sp->waitingAck) { ! 103: /* This acks our Ack Request */ ! 104: sp->waitingAck = 0; /* Allow sending more */ ! 105: sp->pktSendCnt = 0; /* Reset packet count */ ! 106: /* Remove retry timer */ ! 107: RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer); ! 108: ! 109: if (!sp->resentData) { /* Data sent without retries */ ! 110: short diff; /* Signed!! */ ! 111: /* All timings done in 6th second base */ ! 112: /* The contortions here are to prevent C from promoting ! 113: * everything to longs and then using a library routine ! 114: * to do the division. As 16-bit words, a DIVU instruction ! 115: * is used. ! 116: */ ! 117: ! 118: diff = (((word)(SysTicks() - sp->sendStamp)) / (word)10) - ! 119: sp->roundTrip + 1; ! 120: ! 121: sp->roundTrip += diff >> 3; /* Update average */ ! 122: ! 123: if (diff < 0) /* Take absolute value */ ! 124: diff = -diff; ! 125: sp->deviation += (diff - sp->deviation) >> 2; /* Update deviation*/ ! 126: ! 127: sp->rtmtInterval = sp->roundTrip + ! 128: ((short)2 * (short)sp->deviation); ! 129: ! 130: if (!sp->noXmitFlow && ! 131: sp->pktSendMax < 50) /* Bump # of sequential */ ! 132: sp->pktSendMax++; /* Packets we'll send */ ! 133: ! 134: sp->noXmitFlow = 0; ! 135: } ! 136: else ! 137: sp->resentData = 0; ! 138: ! 139: } /* Acked our data */ ! 140: ! 141: if (LTE(pktNextRecvSeq, ! 142: sp->firstRtmtSeq)) /* Was duplicate ack, so ignore */ ! 143: goto noack; ! 144: ! 145: if (!sp->sData) /* If nothing in send queue, ignore */ ! 146: goto noack; ! 147: ! 148: ! 149: do { /* This acks bytes in our buffer */ ! 150: if (mp = sp->sbuf_mb) { /* Get ptr to oldest data header */ ! 151: sp->sbuf_mb = gbuf_next(mp); /* unlink it from send queue */ ! 152: eom = 1; ! 153: } else { ! 154: mp = sp->csbuf_mb; ! 155: sp->csbuf_mb = 0; ! 156: eom = 0; ! 157: } ! 158: ! 159: if (mp == 0) { /* shouldn't happen! */ ! 160: sp->sData = 0; ! 161: goto noack; ! 162: } ! 163: /* ! 164: * Does this ack the entire data block we're now pointing at? ! 165: */ ! 166: if (LTE((sp->firstRtmtSeq + eom + (hlen = gbuf_msgsize(mp))), ! 167: pktNextRecvSeq)) { ! 168: ! 169: gbuf_freem(mp); ! 170: ! 171: /* Update seq # of oldest byte in bfr */ ! 172: sp->firstRtmtSeq += eom + hlen; ! 173: ! 174: if ((sp->sbuf_mb == 0) && (sp->csbuf_mb == 0)) { ! 175: /* If this was only block, then ... */ ! 176: sp->sData = 0; /* ... no data in queue */ ! 177: sp->writeFlush = 0; ! 178: if (sp->state == sClosing) /* this may allow us to close... */ ! 179: CheckOkToClose(sp); ! 180: atalk_enablew(sp->gref); ! 181: break; ! 182: } ! 183: } /* whole data block acked */ ! 184: else /* Only some of the data was acked */ ! 185: { ! 186: short acked; ! 187: ! 188: acked = (pktNextRecvSeq - sp->firstRtmtSeq); ! 189: mp = releaseData(mp, acked); ! 190: if (eom) { ! 191: if (mp) { ! 192: gbuf_next(mp) = sp->sbuf_mb; ! 193: sp->sbuf_mb = mp; ! 194: } ! 195: } else ! 196: sp->csbuf_mb = mp; ! 197: ! 198: sp->firstRtmtSeq = pktNextRecvSeq; /* Update seq # oldest byte */ ! 199: break; ! 200: } ! 201: } while (LT(sp->firstRtmtSeq, pktNextRecvSeq)); ! 202: ! 203: if (sp->sData) /* We've got stuff to send */ ! 204: sp->callSend = 1; ! 205: ! 206: noack: ! 207: sendWdwSeq = netw(UAS_VALUE(f->pktRecvWdw)) - 1 + pktNextRecvSeq; ! 208: ! 209: if (GT(sendWdwSeq, sp->sendWdwSeq)) /* Don't make send window smaller */ ! 210: { ! 211: sp->callSend = 1; /* His recv wdw opened, so see */ ! 212: /* if we can send more data */ ! 213: sp->sendWdwSeq = sendWdwSeq; ! 214: } ! 215: ATENABLE(s, sp->lock); ! 216: } ! 217: ! 218: /* ! 219: * RXData ! 220: * ! 221: * We just got a Data Packet ! 222: * See if it came from anybody we know. ! 223: * ! 224: * Called from ADSP Packet with interrupts masked completely OFF ! 225: * ! 226: * INPUTS: ! 227: * Stream pointer ! 228: * gbuf_t pointer ! 229: * Pointer to ADSP header, (part of the mblk pointer to by mp) ! 230: * Length of header plus data ! 231: * OUTPUTS: ! 232: * Returns 1 if packet was ignored ! 233: */ ! 234: int RXData(sp, mp, f, len) /* (CCBPtr sp, ADSP_FRAMEPtr f, word len) */ ! 235: CCBPtr sp; ! 236: register gbuf_t *mp; ! 237: ADSP_FRAMEPtr f; ! 238: int len; ! 239: { ! 240: int s, offset; ! 241: int PktFirstByteSeq; ! 242: short cnt; ! 243: char eom; ! 244: register gbuf_t *rmp; ! 245: len -= ADSP_FRAME_LEN; ! 246: ! 247: /* Does packet have eom bit set? */ ! 248: eom = (f->descriptor & ADSP_EOM_BIT) ? 1 : 0; ! 249: ! 250: PktFirstByteSeq = netdw(UAL_VALUE(f->pktFirstByteSeq)); /* Local copy */ ! 251: ! 252: ATDISABLE(s, sp->lock); ! 253: if (GT(PktFirstByteSeq, sp->recvSeq)) /* missed a packet (out of order) */ ! 254: { ! 255: if (sp->badSeqCnt++ > sp->badSeqCnt) /* Need to send rexmit advice */ ! 256: sp->sendCtl |= B_CTL_RETRANSMIT; ! 257: ATENABLE(s, sp->lock); ! 258: CheckRecvSeq(sp, f); /* Will set send ACK flag if requested */ ! 259: CheckReadQueue(sp); ! 260: gbuf_freem(mp); ! 261: return 0; ! 262: } ! 263: ! 264: if (LTE(PktFirstByteSeq + len + eom, sp->recvSeq)) { /* duplicate data? */ ! 265: ATENABLE(s, sp->lock); ! 266: CheckRecvSeq(sp, f); /* Will set send ACK flag if requested */ ! 267: CheckReadQueue(sp); ! 268: gbuf_freem(mp); ! 269: return 0; ! 270: } ! 271: ! 272: sp->badSeqCnt = 0; /* reset out of sequence pckt counter */ ! 273: ! 274: cnt = sp->recvSeq - PktFirstByteSeq; /* # bytes we've seen already */ ! 275: ! 276: offset = ((unsigned char *)&f->data[cnt]) - (unsigned char *)gbuf_rptr(mp); ! 277: gbuf_rinc(mp,offset); ! 278: /* point recv mblk to data (past headers) */ ! 279: ! 280: len -= cnt; /* # of new data bytes */ ! 281: ! 282: cnt = len; /* # bytes left to deal with */ ! 283: ! 284: if (!sp->rData) /* Recv bfr is empty */ ! 285: { ! 286: sp->rData = 1; /* Not empty any more */ ! 287: if (eom) ! 288: sp->rbuf_mb = mp; ! 289: else ! 290: sp->crbuf_mb = mp; ! 291: } /* Recv queue is empty */ ! 292: ! 293: /* ! 294: * Else, there's already stored data. ! 295: */ ! 296: else { ! 297: /* ! 298: * Is this a new "message?" ! 299: */ ! 300: if (eom) { ! 301: if (sp->crbuf_mb) { ! 302: gbuf_linkb(sp->crbuf_mb, mp); ! 303: mp = sp->crbuf_mb; ! 304: sp->crbuf_mb = 0; ! 305: } ! 306: if (rmp = sp->rbuf_mb) { ! 307: /* ! 308: * Add it to the end ! 309: */ ! 310: while(gbuf_next(rmp)) ! 311: rmp = gbuf_next(rmp); ! 312: gbuf_next(rmp) = mp; ! 313: } else ! 314: sp->rbuf_mb = mp; ! 315: } else if (sp->crbuf_mb) ! 316: gbuf_linkb(sp->crbuf_mb, mp); ! 317: else ! 318: sp->crbuf_mb = mp; ! 319: } ! 320: ! 321: sp->recvSeq += (cnt + eom); /* We've got these bytes */ ! 322: ! 323: /* %%% We really should call check recv seq first, but let's ! 324: * continue to do it down here. We really want to service the ! 325: * received packet first, and maybe reenable scc ints before ! 326: * doing anything that might take a long while ! 327: */ ! 328: ! 329: ATENABLE(s, sp->lock); ! 330: CheckRecvSeq(sp, f); /* Will set send ACK flag if requested */ ! 331: CheckReadQueue(sp); ! 332: ! 333: return 0; ! 334: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.