|
|
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.