]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netat/adsp_RxData.c
0536cd277cf9504f2b276be400d1fb783ca53678
2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
33 * From v01.28 Handle an incoming Data Packet 06/21/90 mbs
37 * 06/29/95 - Modified to handle flow control for writing (Tuyen Nguyen)
38 * Modified for MP, 1996 by Tuyen Nguyen
39 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
42 #include <sys/errno.h>
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <machine/spl.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
49 #include <sys/filedesc.h>
50 #include <sys/fcntl.h>
52 #include <sys/socket.h>
53 #include <sys/socketvar.h>
56 #include <netat/sysglue.h>
57 #include <netat/appletalk.h>
58 #include <netat/at_pcb.h>
59 #include <netat/debug.h>
60 #include <netat/adsp.h>
61 #include <netat/adsp_internal.h>
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
;
125 ATDISABLE(s
, sp
->lock
);
126 if (f
->descriptor
& ADSP_ACK_REQ_BIT
) { /* He wants an Ack */
131 pktNextRecvSeq
= netdw(UAL_VALUE(f
->pktNextRecvSeq
)); /* Local copy */
134 * Make sure the sequence number corresponds to reality -- i.e. for
135 * unacknowledged data that we have sent
138 if (GT(pktNextRecvSeq
, sp
->maxSendSeq
)) /* We've never sent this seq #! */
141 if (GTE(pktNextRecvSeq
, sp
->timerSeq
) && sp
->waitingAck
) {
142 /* This acks our Ack Request */
143 sp
->waitingAck
= 0; /* Allow sending more */
144 sp
->pktSendCnt
= 0; /* Reset packet count */
145 /* Remove retry timer */
146 RemoveTimerElem(&adspGlobal
.fastTimers
, &sp
->RetryTimer
);
148 if (!sp
->resentData
) { /* Data sent without retries */
149 short diff
; /* Signed!! */
150 /* All timings done in 6th second base */
151 /* The contortions here are to prevent C from promoting
152 * everything to longs and then using a library routine
153 * to do the division. As 16-bit words, a DIVU instruction
157 diff
= (((word
)(SysTicks() - sp
->sendStamp
)) / (word
)10) -
160 sp
->roundTrip
+= diff
>> 3; /* Update average */
162 if (diff
< 0) /* Take absolute value */
164 sp
->deviation
+= (diff
- sp
->deviation
) >> 2; /* Update deviation*/
166 sp
->rtmtInterval
= sp
->roundTrip
+
167 ((short)2 * (short)sp
->deviation
);
169 if (!sp
->noXmitFlow
&&
170 sp
->pktSendMax
< 50) /* Bump # of sequential */
171 sp
->pktSendMax
++; /* Packets we'll send */
178 } /* Acked our data */
180 if (LTE(pktNextRecvSeq
,
181 sp
->firstRtmtSeq
)) /* Was duplicate ack, so ignore */
184 if (!sp
->sData
) /* If nothing in send queue, ignore */
188 do { /* This acks bytes in our buffer */
189 if (mp
= sp
->sbuf_mb
) { /* Get ptr to oldest data header */
190 sp
->sbuf_mb
= gbuf_next(mp
); /* unlink it from send queue */
198 if (mp
== 0) { /* shouldn't happen! */
203 * Does this ack the entire data block we're now pointing at?
205 if (LTE((sp
->firstRtmtSeq
+ eom
+ (hlen
= gbuf_msgsize(mp
))),
210 /* Update seq # of oldest byte in bfr */
211 sp
->firstRtmtSeq
+= eom
+ hlen
;
213 if ((sp
->sbuf_mb
== 0) && (sp
->csbuf_mb
== 0)) {
214 /* If this was only block, then ... */
215 sp
->sData
= 0; /* ... no data in queue */
217 if (sp
->state
== sClosing
) /* this may allow us to close... */
219 atalk_enablew(sp
->gref
);
222 } /* whole data block acked */
223 else /* Only some of the data was acked */
227 acked
= (pktNextRecvSeq
- sp
->firstRtmtSeq
);
228 mp
= releaseData(mp
, acked
);
231 gbuf_next(mp
) = sp
->sbuf_mb
;
237 sp
->firstRtmtSeq
= pktNextRecvSeq
; /* Update seq # oldest byte */
240 } while (LT(sp
->firstRtmtSeq
, pktNextRecvSeq
));
242 if (sp
->sData
) /* We've got stuff to send */
246 sendWdwSeq
= netw(UAS_VALUE(f
->pktRecvWdw
)) - 1 + pktNextRecvSeq
;
248 if (GT(sendWdwSeq
, sp
->sendWdwSeq
)) /* Don't make send window smaller */
250 sp
->callSend
= 1; /* His recv wdw opened, so see */
251 /* if we can send more data */
252 sp
->sendWdwSeq
= sendWdwSeq
;
254 ATENABLE(s
, sp
->lock
);
260 * We just got a Data Packet
261 * See if it came from anybody we know.
263 * Called from ADSP Packet with interrupts masked completely OFF
264 * *** In MacOSX interrupts do not seem to be off! ***
269 * Pointer to ADSP header, (part of the mblk pointer to by mp)
270 * Length of header plus data
272 * Returns 1 if packet was ignored
274 int RXData(sp
, mp
, f
, len
) /* (CCBPtr sp, ADSP_FRAMEPtr f, word len) */
285 len
-= ADSP_FRAME_LEN
;
287 /* Does packet have eom bit set? */
288 eom
= (f
->descriptor
& ADSP_EOM_BIT
) ? 1 : 0;
290 dPrintf(D_M_ADSP
, D_L_TRACE
,
291 ("RXData: sp=0x%x, mbuf=0x%x, f=0x%x, len=%d, eom=%d\n",
292 (unsigned)sp
, (unsigned)mp
, (unsigned)f
, len
, eom
));
294 KERNEL_DEBUG(DBG_ADSP_RCV
, 1, sp
, mp
, len
, eom
);
296 trace_mbufs(D_M_ADSP
, " mp", mp
);
298 PktFirstByteSeq
= netdw(UAL_VALUE(f
->pktFirstByteSeq
)); /* Local copy */
300 ATDISABLE(s
, sp
->lock
);
301 if (GT(PktFirstByteSeq
, sp
->recvSeq
)) /* missed a packet (out of order) */
303 if (sp
->badSeqCnt
++ > sp
->badSeqCnt
) /* Need to send rexmit advice */
304 sp
->sendCtl
|= B_CTL_RETRANSMIT
;
305 ATENABLE(s
, sp
->lock
);
306 CheckRecvSeq(sp
, f
); /* Will set send ACK flag if requested */
310 KERNEL_DEBUG(DBG_ADSP_RCV
, 2, sp
, 0, 0, 0);
311 trace_mbufs(D_M_ADSP
, " exRXD m", sp
->rbuf_mb
);
312 dPrintf(D_M_ADSP
, D_L_TRACE
, (" End RXData - missed a packet\n"));
317 if (LTE(PktFirstByteSeq
+ len
+ eom
, sp
->recvSeq
)) { /* duplicate data? */
318 ATENABLE(s
, sp
->lock
);
319 CheckRecvSeq(sp
, f
); /* Will set send ACK flag if requested */
323 KERNEL_DEBUG(DBG_ADSP_RCV
, 3, sp
, 0, 0, 0);
324 trace_mbufs(D_M_ADSP
, " exRXD m", sp
->rbuf_mb
);
325 dPrintf(D_M_ADSP
, D_L_TRACE
, (" End RXData - duplicate data\n"));
330 sp
->badSeqCnt
= 0; /* reset out of sequence pckt counter */
332 cnt
= sp
->recvSeq
- PktFirstByteSeq
; /* # bytes we've seen already */
334 offset
= ((unsigned char *)&f
->data
[cnt
]) - (unsigned char *)gbuf_rptr(mp
);
335 gbuf_rinc(mp
,offset
);
336 /* point recv mblk to data (past headers) */
338 len
-= cnt
; /* # of new data bytes */
340 cnt
= len
; /* # bytes left to deal with */
342 if (!sp
->rData
) /* Recv bfr is empty */
344 sp
->rData
= 1; /* Not empty any more */
346 if ((sp
->rpb
)->ioc
== (caddr_t
)mp
) {
347 dPrintf(D_M_ADSP
, D_L_TRACE
,
348 ("RXData: (pb->ioc == mp) no stored data\n"));
349 KERNEL_DEBUG(DBG_ADSP_RCV
, 4, sp
, sp
->rpb
, 0, 0);
355 } /* Recv queue is empty */
358 * Else, there's already stored data.
363 * Is this a new "message?"
367 gbuf_linkb(sp
->crbuf_mb
, mp
);
371 if (rmp
= sp
->rbuf_mb
) {
375 while(gbuf_next(rmp
))
376 rmp
= gbuf_next(rmp
);
380 } else if (sp
->crbuf_mb
)
381 gbuf_linkb(sp
->crbuf_mb
, mp
);
385 sp
->recvSeq
+= (cnt
+ eom
); /* We've got these bytes */
387 /* %%% We really should call check recv seq first, but let's
388 * continue to do it down here. We really want to service the
389 * received packet first, and maybe reenable scc ints before
390 * doing anything that might take a long while
393 ATENABLE(s
, sp
->lock
);
394 CheckRecvSeq(sp
, f
); /* Will set send ACK flag if requested */
396 KERNEL_DEBUG(DBG_ADSP_RCV
, 5, sp
, sp
->rbuf_mb
, 0, 0);
397 trace_mbufs(D_M_ADSP
, " eRXD m", sp
->rbuf_mb
);