]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netat/adsp_RxData.c
02d73204466ad6f4ae9952a45289a2e1cd7b6fc8
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
25 * From v01.28 Handle an incoming Data Packet 06/21/90 mbs
29 * 06/29/95 - Modified to handle flow control for writing (Tuyen Nguyen)
30 * Modified for MP, 1996 by Tuyen Nguyen
31 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
34 #include <sys/errno.h>
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <machine/spl.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
41 #include <sys/filedesc.h>
42 #include <sys/fcntl.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
48 #include <netat/sysglue.h>
49 #include <netat/appletalk.h>
50 #include <netat/at_pcb.h>
51 #include <netat/debug.h>
52 #include <netat/adsp.h>
53 #include <netat/adsp_internal.h>
55 gbuf_t
*releaseData(mp
, len
)
63 dPrintf(D_M_ADSP
, D_L_TRACE
,
64 ("releaseData: mbuf=0x%x, len=%d\n", (unsigned)mp
, len
));
66 KERNEL_DEBUG(DBG_ADSP_RCV
, 0, mp
, len
, 0, 0);
69 freeit
= 1; /* assume we use the whole mblk */
70 if ((cnt
= gbuf_len(mp
)) > len
) {
71 freeit
= 0; /* using only part of the mblk */
81 return tmp
; /* if we don't use the whole block */
82 /* pass back the partial gbuf_t pointer */
90 * We just got a non-attention packet. Check the pktNextRecvSeq field
91 * to see if it acknowledges any of our sent data.
93 * If any data was acked, check to see if we have anything to fill the
94 * newly opened up remote receive window. Otherwise, if the ACK request
95 * bit was set, we need to send an Ack Packet
97 * Always called as the result of receiving a packet. Interrupts
98 * are completely masked when this routine is called.
102 * f pointer to ASDP header
106 void CheckRecvSeq(sp
, f
) /* (CCBPtr sp, ADSP_FRAMEPtr f) */
108 register ADSP_FRAMEPtr f
;
116 if (f
->descriptor
& ADSP_ACK_REQ_BIT
) { /* He wants an Ack */
121 pktNextRecvSeq
= UAL_VALUE_NTOH(f
->pktNextRecvSeq
); /* Local copy */
124 * Make sure the sequence number corresponds to reality -- i.e. for
125 * unacknowledged data that we have sent
128 if (GT(pktNextRecvSeq
, sp
->maxSendSeq
)) /* We've never sent this seq #! */
131 if (GTE(pktNextRecvSeq
, sp
->timerSeq
) && sp
->waitingAck
) {
132 /* This acks our Ack Request */
133 sp
->waitingAck
= 0; /* Allow sending more */
134 sp
->pktSendCnt
= 0; /* Reset packet count */
135 /* Remove retry timer */
136 RemoveTimerElem(&adspGlobal
.fastTimers
, &sp
->RetryTimer
);
138 if (!sp
->resentData
) { /* Data sent without retries */
139 short diff
; /* Signed!! */
140 /* All timings done in 6th second base */
141 /* The contortions here are to prevent C from promoting
142 * everything to longs and then using a library routine
143 * to do the division. As 16-bit words, a DIVU instruction
147 diff
= (((word
)(SysTicks() - sp
->sendStamp
)) / (word
)10) -
150 sp
->roundTrip
+= diff
>> 3; /* Update average */
152 if (diff
< 0) /* Take absolute value */
154 sp
->deviation
+= (diff
- sp
->deviation
) >> 2; /* Update deviation*/
156 sp
->rtmtInterval
= sp
->roundTrip
+
157 ((short)2 * (short)sp
->deviation
);
159 if (!sp
->noXmitFlow
&&
160 sp
->pktSendMax
< 50) /* Bump # of sequential */
161 sp
->pktSendMax
++; /* Packets we'll send */
168 } /* Acked our data */
170 if (LTE(pktNextRecvSeq
,
171 sp
->firstRtmtSeq
)) /* Was duplicate ack, so ignore */
174 if (!sp
->sData
) /* If nothing in send queue, ignore */
178 do { /* This acks bytes in our buffer */
179 if (mp
= sp
->sbuf_mb
) { /* Get ptr to oldest data header */
180 sp
->sbuf_mb
= gbuf_next(mp
); /* unlink it from send queue */
188 if (mp
== 0) { /* shouldn't happen! */
193 * Does this ack the entire data block we're now pointing at?
195 if (LTE((sp
->firstRtmtSeq
+ eom
+ (hlen
= gbuf_msgsize(mp
))),
200 /* Update seq # of oldest byte in bfr */
201 sp
->firstRtmtSeq
+= eom
+ hlen
;
203 if ((sp
->sbuf_mb
== 0) && (sp
->csbuf_mb
== 0)) {
204 /* If this was only block, then ... */
205 sp
->sData
= 0; /* ... no data in queue */
207 if (sp
->state
== sClosing
) /* this may allow us to close... */
209 atalk_enablew(sp
->gref
);
212 } /* whole data block acked */
213 else /* Only some of the data was acked */
217 acked
= (pktNextRecvSeq
- sp
->firstRtmtSeq
);
218 mp
= releaseData(mp
, acked
);
221 gbuf_next(mp
) = sp
->sbuf_mb
;
227 sp
->firstRtmtSeq
= pktNextRecvSeq
; /* Update seq # oldest byte */
230 } while (LT(sp
->firstRtmtSeq
, pktNextRecvSeq
));
232 if (sp
->sData
) /* We've got stuff to send */
236 sendWdwSeq
= UAS_VALUE_NTOH(f
->pktRecvWdw
) - 1 + pktNextRecvSeq
;
238 if (GT(sendWdwSeq
, sp
->sendWdwSeq
)) /* Don't make send window smaller */
240 sp
->callSend
= 1; /* His recv wdw opened, so see */
241 /* if we can send more data */
242 sp
->sendWdwSeq
= sendWdwSeq
;
249 * We just got a Data Packet
250 * See if it came from anybody we know.
252 * Called from ADSP Packet with interrupts masked completely OFF
253 * *** In MacOSX interrupts do not seem to be off! ***
258 * Pointer to ADSP header, (part of the mblk pointer to by mp)
259 * Length of header plus data
261 * Returns 1 if packet was ignored
263 int RXData(sp
, mp
, f
, len
) /* (CCBPtr sp, ADSP_FRAMEPtr f, word len) */
274 len
-= ADSP_FRAME_LEN
;
276 /* Does packet have eom bit set? */
277 eom
= (f
->descriptor
& ADSP_EOM_BIT
) ? 1 : 0;
279 dPrintf(D_M_ADSP
, D_L_TRACE
,
280 ("RXData: sp=0x%x, mbuf=0x%x, f=0x%x, len=%d, eom=%d\n",
281 (unsigned)sp
, (unsigned)mp
, (unsigned)f
, len
, eom
));
283 KERNEL_DEBUG(DBG_ADSP_RCV
, 1, sp
, mp
, len
, eom
);
285 trace_mbufs(D_M_ADSP
, " mp", mp
);
287 PktFirstByteSeq
= UAL_VALUE_NTOH(f
->pktFirstByteSeq
); /* Local copy */
289 if (GT(PktFirstByteSeq
, sp
->recvSeq
)) /* missed a packet (out of order) */
291 if (sp
->badSeqCnt
++ > sp
->badSeqCnt
) /* Need to send rexmit advice */
292 sp
->sendCtl
|= B_CTL_RETRANSMIT
;
293 CheckRecvSeq(sp
, f
); /* Will set send ACK flag if requested */
297 KERNEL_DEBUG(DBG_ADSP_RCV
, 2, sp
, 0, 0, 0);
298 trace_mbufs(D_M_ADSP
, " exRXD m", sp
->rbuf_mb
);
299 dPrintf(D_M_ADSP
, D_L_TRACE
, (" End RXData - missed a packet\n"));
304 if (LTE(PktFirstByteSeq
+ len
+ eom
, sp
->recvSeq
)) { /* duplicate data? */
305 CheckRecvSeq(sp
, f
); /* Will set send ACK flag if requested */
309 KERNEL_DEBUG(DBG_ADSP_RCV
, 3, sp
, 0, 0, 0);
310 trace_mbufs(D_M_ADSP
, " exRXD m", sp
->rbuf_mb
);
311 dPrintf(D_M_ADSP
, D_L_TRACE
, (" End RXData - duplicate data\n"));
316 sp
->badSeqCnt
= 0; /* reset out of sequence pckt counter */
318 cnt
= sp
->recvSeq
- PktFirstByteSeq
; /* # bytes we've seen already */
320 offset
= ((unsigned char *)&f
->data
[cnt
]) - (unsigned char *)gbuf_rptr(mp
);
321 gbuf_rinc(mp
,offset
);
322 /* point recv mblk to data (past headers) */
324 len
-= cnt
; /* # of new data bytes */
326 cnt
= len
; /* # bytes left to deal with */
328 if (!sp
->rData
) /* Recv bfr is empty */
330 sp
->rData
= 1; /* Not empty any more */
332 if ((sp
->rpb
)->ioc
== (caddr_t
)mp
) {
333 dPrintf(D_M_ADSP
, D_L_TRACE
,
334 ("RXData: (pb->ioc == mp) no stored data\n"));
335 KERNEL_DEBUG(DBG_ADSP_RCV
, 4, sp
, sp
->rpb
, 0, 0);
341 } /* Recv queue is empty */
344 * Else, there's already stored data.
349 * Is this a new "message?"
353 gbuf_linkb(sp
->crbuf_mb
, mp
);
357 if (rmp
= sp
->rbuf_mb
) {
361 while(gbuf_next(rmp
))
362 rmp
= gbuf_next(rmp
);
366 } else if (sp
->crbuf_mb
)
367 gbuf_linkb(sp
->crbuf_mb
, mp
);
371 sp
->recvSeq
+= (cnt
+ eom
); /* We've got these bytes */
373 /* %%% We really should call check recv seq first, but let's
374 * continue to do it down here. We really want to service the
375 * received packet first, and maybe reenable scc ints before
376 * doing anything that might take a long while
379 CheckRecvSeq(sp
, f
); /* Will set send ACK flag if requested */
381 KERNEL_DEBUG(DBG_ADSP_RCV
, 5, sp
, sp
->rbuf_mb
, 0, 0);
382 trace_mbufs(D_M_ADSP
, " eRXD m", sp
->rbuf_mb
);