Annotation of kernel/bsd/netat/adsp_RxData.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.