]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netat/adsp_RxData.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
31 * From v01.28 Handle an incoming Data Packet 06/21/90 mbs
35 * 06/29/95 - Modified to handle flow control for writing (Tuyen Nguyen)
36 * Modified for MP, 1996 by Tuyen Nguyen
37 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
40 #include <sys/errno.h>
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <machine/spl.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
47 #include <sys/filedesc.h>
48 #include <sys/fcntl.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
54 #include <netat/sysglue.h>
55 #include <netat/appletalk.h>
56 #include <netat/at_pcb.h>
57 #include <netat/debug.h>
58 #include <netat/adsp.h>
59 #include <netat/adsp_internal.h>
61 gbuf_t
*releaseData(gbuf_t
*, int);
63 gbuf_t
*releaseData(mp
, len
)
71 dPrintf(D_M_ADSP
, D_L_TRACE
,
72 ("releaseData: mbuf=0x%x, len=%d\n", (unsigned)mp
, len
));
74 KERNEL_DEBUG(DBG_ADSP_RCV
, 0, mp
, len
, 0, 0);
77 freeit
= 1; /* assume we use the whole mblk */
78 if ((cnt
= gbuf_len(mp
)) > len
) {
79 freeit
= 0; /* using only part of the mblk */
89 return tmp
; /* if we don't use the whole block */
90 /* pass back the partial gbuf_t pointer */
98 * We just got a non-attention packet. Check the pktNextRecvSeq field
99 * to see if it acknowledges any of our sent data.
101 * If any data was acked, check to see if we have anything to fill the
102 * newly opened up remote receive window. Otherwise, if the ACK request
103 * bit was set, we need to send an Ack Packet
105 * Always called as the result of receiving a packet. Interrupts
106 * are completely masked when this routine is called.
110 * f pointer to ASDP header
114 void CheckRecvSeq(sp
, f
) /* (CCBPtr sp, ADSP_FRAMEPtr f) */
116 register ADSP_FRAMEPtr f
;
124 if (f
->descriptor
& ADSP_ACK_REQ_BIT
) { /* He wants an Ack */
129 pktNextRecvSeq
= UAL_VALUE_NTOH(f
->pktNextRecvSeq
); /* Local copy */
132 * Make sure the sequence number corresponds to reality -- i.e. for
133 * unacknowledged data that we have sent
136 if (GT(pktNextRecvSeq
, sp
->maxSendSeq
)) /* We've never sent this seq #! */
139 if (GTE(pktNextRecvSeq
, sp
->timerSeq
) && sp
->waitingAck
) {
140 /* This acks our Ack Request */
141 sp
->waitingAck
= 0; /* Allow sending more */
142 sp
->pktSendCnt
= 0; /* Reset packet count */
143 /* Remove retry timer */
144 RemoveTimerElem(&adspGlobal
.fastTimers
, &sp
->RetryTimer
);
146 if (!sp
->resentData
) { /* Data sent without retries */
147 short diff
; /* Signed!! */
148 /* All timings done in 6th second base */
149 /* The contortions here are to prevent C from promoting
150 * everything to longs and then using a library routine
151 * to do the division. As 16-bit words, a DIVU instruction
155 diff
= (((word
)(SysTicks() - sp
->sendStamp
)) / (word
)10) -
158 sp
->roundTrip
+= diff
>> 3; /* Update average */
160 if (diff
< 0) /* Take absolute value */
162 sp
->deviation
+= (diff
- sp
->deviation
) >> 2; /* Update deviation*/
164 sp
->rtmtInterval
= sp
->roundTrip
+
165 ((short)2 * (short)sp
->deviation
);
167 if (!sp
->noXmitFlow
&&
168 sp
->pktSendMax
< 50) /* Bump # of sequential */
169 sp
->pktSendMax
++; /* Packets we'll send */
176 } /* Acked our data */
178 if (LTE(pktNextRecvSeq
,
179 sp
->firstRtmtSeq
)) /* Was duplicate ack, so ignore */
182 if (!sp
->sData
) /* If nothing in send queue, ignore */
186 do { /* This acks bytes in our buffer */
187 if ((mp
= sp
->sbuf_mb
)) { /* Get ptr to oldest data header */
188 sp
->sbuf_mb
= gbuf_next(mp
); /* unlink it from send queue */
196 if (mp
== 0) { /* shouldn't happen! */
201 * Does this ack the entire data block we're now pointing at?
203 if (LTE((sp
->firstRtmtSeq
+ eom
+ (hlen
= gbuf_msgsize(mp
))),
208 /* Update seq # of oldest byte in bfr */
209 sp
->firstRtmtSeq
+= eom
+ hlen
;
211 if ((sp
->sbuf_mb
== 0) && (sp
->csbuf_mb
== 0)) {
212 /* If this was only block, then ... */
213 sp
->sData
= 0; /* ... no data in queue */
215 if (sp
->state
== sClosing
) /* this may allow us to close... */
217 atalk_enablew(sp
->gref
);
220 } /* whole data block acked */
221 else /* Only some of the data was acked */
225 acked
= (pktNextRecvSeq
- sp
->firstRtmtSeq
);
226 mp
= releaseData(mp
, acked
);
229 gbuf_next(mp
) = sp
->sbuf_mb
;
235 sp
->firstRtmtSeq
= pktNextRecvSeq
; /* Update seq # oldest byte */
238 } while (LT(sp
->firstRtmtSeq
, pktNextRecvSeq
));
240 if (sp
->sData
) /* We've got stuff to send */
244 sendWdwSeq
= UAS_VALUE_NTOH(f
->pktRecvWdw
) - 1 + pktNextRecvSeq
;
246 if (GT(sendWdwSeq
, sp
->sendWdwSeq
)) /* Don't make send window smaller */
248 sp
->callSend
= 1; /* His recv wdw opened, so see */
249 /* if we can send more data */
250 sp
->sendWdwSeq
= sendWdwSeq
;
257 * We just got a Data Packet
258 * See if it came from anybody we know.
260 * Called from ADSP Packet with interrupts masked completely OFF
261 * *** In MacOSX interrupts do not seem to be off! ***
266 * Pointer to ADSP header, (part of the mblk pointer to by mp)
267 * Length of header plus data
269 * Returns 1 if packet was ignored
271 int RXData(sp
, mp
, f
, len
) /* (CCBPtr sp, ADSP_FRAMEPtr f, word len) */
282 len
-= ADSP_FRAME_LEN
;
284 /* Does packet have eom bit set? */
285 eom
= (f
->descriptor
& ADSP_EOM_BIT
) ? 1 : 0;
287 dPrintf(D_M_ADSP
, D_L_TRACE
,
288 ("RXData: sp=0x%x, mbuf=0x%x, f=0x%x, len=%d, eom=%d\n",
289 (unsigned)sp
, (unsigned)mp
, (unsigned)f
, len
, eom
));
291 KERNEL_DEBUG(DBG_ADSP_RCV
, 1, sp
, mp
, len
, eom
);
293 trace_mbufs(D_M_ADSP
, " mp", mp
);
295 PktFirstByteSeq
= UAL_VALUE_NTOH(f
->pktFirstByteSeq
); /* Local copy */
297 if (GT(PktFirstByteSeq
, sp
->recvSeq
)) /* missed a packet (out of order) */
299 if (sp
->badSeqCnt
++ > sp
->badSeqCnt
) /* Need to send rexmit advice */
300 sp
->sendCtl
|= B_CTL_RETRANSMIT
;
301 CheckRecvSeq(sp
, f
); /* Will set send ACK flag if requested */
305 KERNEL_DEBUG(DBG_ADSP_RCV
, 2, sp
, 0, 0, 0);
306 trace_mbufs(D_M_ADSP
, " exRXD m", sp
->rbuf_mb
);
307 dPrintf(D_M_ADSP
, D_L_TRACE
, (" End RXData - missed a packet\n"));
312 if (LTE(PktFirstByteSeq
+ len
+ eom
, sp
->recvSeq
)) { /* duplicate data? */
313 CheckRecvSeq(sp
, f
); /* Will set send ACK flag if requested */
317 KERNEL_DEBUG(DBG_ADSP_RCV
, 3, sp
, 0, 0, 0);
318 trace_mbufs(D_M_ADSP
, " exRXD m", sp
->rbuf_mb
);
319 dPrintf(D_M_ADSP
, D_L_TRACE
, (" End RXData - duplicate data\n"));
324 sp
->badSeqCnt
= 0; /* reset out of sequence pckt counter */
326 cnt
= sp
->recvSeq
- PktFirstByteSeq
; /* # bytes we've seen already */
328 offset
= ((unsigned char *)&f
->data
[cnt
]) - (unsigned char *)gbuf_rptr(mp
);
329 gbuf_rinc(mp
,offset
);
330 /* point recv mblk to data (past headers) */
332 len
-= cnt
; /* # of new data bytes */
334 cnt
= len
; /* # bytes left to deal with */
336 if (!sp
->rData
) /* Recv bfr is empty */
338 sp
->rData
= 1; /* Not empty any more */
340 if ((sp
->rpb
)->ioc
== (caddr_t
)mp
) {
341 dPrintf(D_M_ADSP
, D_L_TRACE
,
342 ("RXData: (pb->ioc == mp) no stored data\n"));
343 KERNEL_DEBUG(DBG_ADSP_RCV
, 4, sp
, sp
->rpb
, 0, 0);
349 } /* Recv queue is empty */
352 * Else, there's already stored data.
357 * Is this a new "message?"
361 gbuf_linkb(sp
->crbuf_mb
, mp
);
365 if ((rmp
= sp
->rbuf_mb
)) {
369 while(gbuf_next(rmp
))
370 rmp
= gbuf_next(rmp
);
374 } else if (sp
->crbuf_mb
)
375 gbuf_linkb(sp
->crbuf_mb
, mp
);
379 sp
->recvSeq
+= (cnt
+ eom
); /* We've got these bytes */
381 /* %%% We really should call check recv seq first, but let's
382 * continue to do it down here. We really want to service the
383 * received packet first, and maybe reenable scc ints before
384 * doing anything that might take a long while
387 CheckRecvSeq(sp
, f
); /* Will set send ACK flag if requested */
389 KERNEL_DEBUG(DBG_ADSP_RCV
, 5, sp
, sp
->rbuf_mb
, 0, 0);
390 trace_mbufs(D_M_ADSP
, " eRXD m", sp
->rbuf_mb
);