]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netat/adsp_RxData.c
96280bb611d0e46c42801025d9b4e83a0597876d
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
28 * From v01.28 Handle an incoming Data Packet 06/21/90 mbs
32 * 06/29/95 - Modified to handle flow control for writing (Tuyen Nguyen)
33 * Modified for MP, 1996 by Tuyen Nguyen
34 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
37 #include <sys/errno.h>
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <machine/spl.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
44 #include <sys/filedesc.h>
45 #include <sys/fcntl.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
51 #include <netat/sysglue.h>
52 #include <netat/appletalk.h>
53 #include <netat/at_pcb.h>
54 #include <netat/debug.h>
55 #include <netat/adsp.h>
56 #include <netat/adsp_internal.h>
58 gbuf_t
*releaseData(mp
, len
)
66 dPrintf(D_M_ADSP
, D_L_TRACE
,
67 ("releaseData: mbuf=0x%x, len=%d\n", (unsigned)mp
, len
));
69 KERNEL_DEBUG(DBG_ADSP_RCV
, 0, mp
, len
, 0, 0);
72 freeit
= 1; /* assume we use the whole mblk */
73 if ((cnt
= gbuf_len(mp
)) > len
) {
74 freeit
= 0; /* using only part of the mblk */
84 return tmp
; /* if we don't use the whole block */
85 /* pass back the partial gbuf_t pointer */
93 * We just got a non-attention packet. Check the pktNextRecvSeq field
94 * to see if it acknowledges any of our sent data.
96 * If any data was acked, check to see if we have anything to fill the
97 * newly opened up remote receive window. Otherwise, if the ACK request
98 * bit was set, we need to send an Ack Packet
100 * Always called as the result of receiving a packet. Interrupts
101 * are completely masked when this routine is called.
105 * f pointer to ASDP header
109 void CheckRecvSeq(sp
, f
) /* (CCBPtr sp, ADSP_FRAMEPtr f) */
111 register ADSP_FRAMEPtr f
;
120 ATDISABLE(s
, sp
->lock
);
121 if (f
->descriptor
& ADSP_ACK_REQ_BIT
) { /* He wants an Ack */
126 pktNextRecvSeq
= netdw(UAL_VALUE(f
->pktNextRecvSeq
)); /* Local copy */
129 * Make sure the sequence number corresponds to reality -- i.e. for
130 * unacknowledged data that we have sent
133 if (GT(pktNextRecvSeq
, sp
->maxSendSeq
)) /* We've never sent this seq #! */
136 if (GTE(pktNextRecvSeq
, sp
->timerSeq
) && sp
->waitingAck
) {
137 /* This acks our Ack Request */
138 sp
->waitingAck
= 0; /* Allow sending more */
139 sp
->pktSendCnt
= 0; /* Reset packet count */
140 /* Remove retry timer */
141 RemoveTimerElem(&adspGlobal
.fastTimers
, &sp
->RetryTimer
);
143 if (!sp
->resentData
) { /* Data sent without retries */
144 short diff
; /* Signed!! */
145 /* All timings done in 6th second base */
146 /* The contortions here are to prevent C from promoting
147 * everything to longs and then using a library routine
148 * to do the division. As 16-bit words, a DIVU instruction
152 diff
= (((word
)(SysTicks() - sp
->sendStamp
)) / (word
)10) -
155 sp
->roundTrip
+= diff
>> 3; /* Update average */
157 if (diff
< 0) /* Take absolute value */
159 sp
->deviation
+= (diff
- sp
->deviation
) >> 2; /* Update deviation*/
161 sp
->rtmtInterval
= sp
->roundTrip
+
162 ((short)2 * (short)sp
->deviation
);
164 if (!sp
->noXmitFlow
&&
165 sp
->pktSendMax
< 50) /* Bump # of sequential */
166 sp
->pktSendMax
++; /* Packets we'll send */
173 } /* Acked our data */
175 if (LTE(pktNextRecvSeq
,
176 sp
->firstRtmtSeq
)) /* Was duplicate ack, so ignore */
179 if (!sp
->sData
) /* If nothing in send queue, ignore */
183 do { /* This acks bytes in our buffer */
184 if (mp
= sp
->sbuf_mb
) { /* Get ptr to oldest data header */
185 sp
->sbuf_mb
= gbuf_next(mp
); /* unlink it from send queue */
193 if (mp
== 0) { /* shouldn't happen! */
198 * Does this ack the entire data block we're now pointing at?
200 if (LTE((sp
->firstRtmtSeq
+ eom
+ (hlen
= gbuf_msgsize(mp
))),
205 /* Update seq # of oldest byte in bfr */
206 sp
->firstRtmtSeq
+= eom
+ hlen
;
208 if ((sp
->sbuf_mb
== 0) && (sp
->csbuf_mb
== 0)) {
209 /* If this was only block, then ... */
210 sp
->sData
= 0; /* ... no data in queue */
212 if (sp
->state
== sClosing
) /* this may allow us to close... */
214 atalk_enablew(sp
->gref
);
217 } /* whole data block acked */
218 else /* Only some of the data was acked */
222 acked
= (pktNextRecvSeq
- sp
->firstRtmtSeq
);
223 mp
= releaseData(mp
, acked
);
226 gbuf_next(mp
) = sp
->sbuf_mb
;
232 sp
->firstRtmtSeq
= pktNextRecvSeq
; /* Update seq # oldest byte */
235 } while (LT(sp
->firstRtmtSeq
, pktNextRecvSeq
));
237 if (sp
->sData
) /* We've got stuff to send */
241 sendWdwSeq
= netw(UAS_VALUE(f
->pktRecvWdw
)) - 1 + pktNextRecvSeq
;
243 if (GT(sendWdwSeq
, sp
->sendWdwSeq
)) /* Don't make send window smaller */
245 sp
->callSend
= 1; /* His recv wdw opened, so see */
246 /* if we can send more data */
247 sp
->sendWdwSeq
= sendWdwSeq
;
249 ATENABLE(s
, sp
->lock
);
255 * We just got a Data Packet
256 * See if it came from anybody we know.
258 * Called from ADSP Packet with interrupts masked completely OFF
259 * *** In MacOSX interrupts do not seem to be off! ***
264 * Pointer to ADSP header, (part of the mblk pointer to by mp)
265 * Length of header plus data
267 * Returns 1 if packet was ignored
269 int RXData(sp
, mp
, f
, len
) /* (CCBPtr sp, ADSP_FRAMEPtr f, word len) */
280 len
-= ADSP_FRAME_LEN
;
282 /* Does packet have eom bit set? */
283 eom
= (f
->descriptor
& ADSP_EOM_BIT
) ? 1 : 0;
285 dPrintf(D_M_ADSP
, D_L_TRACE
,
286 ("RXData: sp=0x%x, mbuf=0x%x, f=0x%x, len=%d, eom=%d\n",
287 (unsigned)sp
, (unsigned)mp
, (unsigned)f
, len
, eom
));
289 KERNEL_DEBUG(DBG_ADSP_RCV
, 1, sp
, mp
, len
, eom
);
291 trace_mbufs(D_M_ADSP
, " mp", mp
);
293 PktFirstByteSeq
= netdw(UAL_VALUE(f
->pktFirstByteSeq
)); /* Local copy */
295 ATDISABLE(s
, sp
->lock
);
296 if (GT(PktFirstByteSeq
, sp
->recvSeq
)) /* missed a packet (out of order) */
298 if (sp
->badSeqCnt
++ > sp
->badSeqCnt
) /* Need to send rexmit advice */
299 sp
->sendCtl
|= B_CTL_RETRANSMIT
;
300 ATENABLE(s
, sp
->lock
);
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 ATENABLE(s
, sp
->lock
);
314 CheckRecvSeq(sp
, f
); /* Will set send ACK flag if requested */
318 KERNEL_DEBUG(DBG_ADSP_RCV
, 3, sp
, 0, 0, 0);
319 trace_mbufs(D_M_ADSP
, " exRXD m", sp
->rbuf_mb
);
320 dPrintf(D_M_ADSP
, D_L_TRACE
, (" End RXData - duplicate data\n"));
325 sp
->badSeqCnt
= 0; /* reset out of sequence pckt counter */
327 cnt
= sp
->recvSeq
- PktFirstByteSeq
; /* # bytes we've seen already */
329 offset
= ((unsigned char *)&f
->data
[cnt
]) - (unsigned char *)gbuf_rptr(mp
);
330 gbuf_rinc(mp
,offset
);
331 /* point recv mblk to data (past headers) */
333 len
-= cnt
; /* # of new data bytes */
335 cnt
= len
; /* # bytes left to deal with */
337 if (!sp
->rData
) /* Recv bfr is empty */
339 sp
->rData
= 1; /* Not empty any more */
341 if ((sp
->rpb
)->ioc
== mp
) {
342 dPrintf(D_M_ADSP
, D_L_TRACE
,
343 ("RXData: (pb->ioc == mp) no stored data\n"));
344 KERNEL_DEBUG(DBG_ADSP_RCV
, 4, sp
, sp
->rpb
, 0, 0);
350 } /* Recv queue is empty */
353 * Else, there's already stored data.
358 * Is this a new "message?"
362 gbuf_linkb(sp
->crbuf_mb
, mp
);
366 if (rmp
= sp
->rbuf_mb
) {
370 while(gbuf_next(rmp
))
371 rmp
= gbuf_next(rmp
);
375 } else if (sp
->crbuf_mb
)
376 gbuf_linkb(sp
->crbuf_mb
, mp
);
380 sp
->recvSeq
+= (cnt
+ eom
); /* We've got these bytes */
382 /* %%% We really should call check recv seq first, but let's
383 * continue to do it down here. We really want to service the
384 * received packet first, and maybe reenable scc ints before
385 * doing anything that might take a long while
388 ATENABLE(s
, sp
->lock
);
389 CheckRecvSeq(sp
, f
); /* Will set send ACK flag if requested */
391 KERNEL_DEBUG(DBG_ADSP_RCV
, 5, sp
, sp
->rbuf_mb
, 0, 0);
392 trace_mbufs(D_M_ADSP
, " eRXD m", sp
->rbuf_mb
);