Annotation of XNU/bsd/netat/adsp_RxData.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             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.
        !            11:  * 
        !            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
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /* 
        !            23:  * RxData.c 
        !            24:  *
        !            25:  * From v01.28   Handle an incoming Data Packet       06/21/90 mbs
        !            26:  */
        !            27: /*
        !            28:  * Change log:
        !            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.
        !            32:  */
        !            33: 
        !            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>
        !            40: #include <sys/proc.h>
        !            41: #include <sys/filedesc.h>
        !            42: #include <sys/fcntl.h>
        !            43: #include <sys/mbuf.h>
        !            44: #include <sys/socket.h>
        !            45: #include <sys/socketvar.h>
        !            46: #include <sys/time.h>
        !            47: 
        !            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>
        !            54: 
        !            55: gbuf_t *releaseData(mp, len)
        !            56:     gbuf_t *mp;
        !            57:     int len;
        !            58: {
        !            59:     register gbuf_t *tmp;
        !            60:     register int cnt;
        !            61:     int freeit;
        !            62: 
        !            63:     dPrintf(D_M_ADSP, D_L_TRACE, 
        !            64:            ("releaseData: mbuf=0x%x, len=%d\n", (unsigned)mp, len));
        !            65: 
        !            66:     KERNEL_DEBUG(DBG_ADSP_RCV, 0, mp, len, 0, 0);
        !            67: 
        !            68:     do {
        !            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 */
        !            72:            cnt = len;
        !            73:        }
        !            74:        gbuf_rinc(mp,cnt);
        !            75:        len -= cnt;
        !            76:        tmp = mp;
        !            77:        mp = gbuf_cont(mp);
        !            78:        if (freeit) {
        !            79:            gbuf_freeb(tmp);
        !            80:        } else
        !            81:            return tmp;         /* if we don't use the whole block */
        !            82:                                /* pass back the partial gbuf_t pointer */
        !            83:     } while (len && mp);
        !            84:     return mp;
        !            85: }
        !            86: 
        !            87: /*
        !            88:  * CheckRecvSeq
        !            89:  *
        !            90:  * We just got a non-attention packet.  Check the pktNextRecvSeq field
        !            91:  * to see if it acknowledges any of our sent data.
        !            92:  *
        !            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
        !            96:  *
        !            97:  * Always called as the result of receiving a packet.  Interrupts 
        !            98:  * are completely masked when this routine is called.
        !            99:  *
        !           100:  * INPUTS:
        !           101:  *    sp stream
        !           102:  *    f  pointer to ASDP header
        !           103:  * OUTPUTS:
        !           104:  *    none
        !           105:  */
        !           106: void CheckRecvSeq(sp, f)       /* (CCBPtr sp, ADSP_FRAMEPtr f) */
        !           107:     register CCBPtr sp;
        !           108:     register ADSP_FRAMEPtr f;
        !           109: {
        !           110:     int s;
        !           111:     int pktNextRecvSeq;
        !           112:     int sendWdwSeq;
        !           113:     int eom;
        !           114:     int hlen;
        !           115:     register gbuf_t *mp;
        !           116:        
        !           117:     ATDISABLE(s, sp->lock);
        !           118:     if (f->descriptor & ADSP_ACK_REQ_BIT) { /* He wants an Ack */
        !           119:        sp->sendDataAck = 1;
        !           120:        sp->callSend = 1;
        !           121:     }
        !           122:        
        !           123:     pktNextRecvSeq = netdw(UAL_VALUE(f->pktNextRecvSeq)); /* Local copy */
        !           124: 
        !           125:     /*
        !           126:      * Make sure the sequence number corresponds to reality -- i.e. for 
        !           127:      * unacknowledged data that we have sent
        !           128:      */
        !           129: 
        !           130:     if (GT(pktNextRecvSeq, sp->maxSendSeq)) /* We've never sent this seq #! */
        !           131:        goto noack;
        !           132: 
        !           133:     if (GTE(pktNextRecvSeq, sp->timerSeq) && sp->waitingAck) {
        !           134:        /* This acks our Ack Request */
        !           135:        sp->waitingAck = 0;     /* Allow sending more */
        !           136:        sp->pktSendCnt = 0;     /* Reset packet count */
        !           137:        /* Remove retry timer */
        !           138:        RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer); 
        !           139:                
        !           140:        if (!sp->resentData) {  /* Data sent without retries */
        !           141:            short diff;         /* Signed!! */
        !           142:            /* All timings done in 6th second base */
        !           143:            /* The contortions here are to prevent C from promoting 
        !           144:             * everything to longs and then using a library routine 
        !           145:             * to do the division. As 16-bit words, a DIVU instruction 
        !           146:             * is used. 
        !           147:             */
        !           148:            
        !           149:            diff = (((word)(SysTicks() - sp->sendStamp)) / (word)10) - 
        !           150:                sp->roundTrip + 1;
        !           151: 
        !           152:            sp->roundTrip += diff >> 3; /* Update average */
        !           153: 
        !           154:            if (diff < 0)       /* Take absolute value */
        !           155:                diff = -diff;
        !           156:            sp->deviation += (diff - sp->deviation) >> 2; /* Update deviation*/
        !           157: 
        !           158:            sp->rtmtInterval = sp->roundTrip + 
        !           159:                ((short)2 * (short)sp->deviation);
        !           160: 
        !           161:            if (!sp->noXmitFlow && 
        !           162:                sp->pktSendMax < 50) /* Bump # of sequential */
        !           163:                sp->pktSendMax++; /* Packets we'll send */
        !           164:                                
        !           165:            sp->noXmitFlow = 0;
        !           166:        }
        !           167:        else
        !           168:            sp->resentData = 0;
        !           169:                        
        !           170:     }                          /* Acked our data */
        !           171: 
        !           172:     if (LTE(pktNextRecvSeq, 
        !           173:            sp->firstRtmtSeq)) /* Was duplicate ack, so ignore */
        !           174:        goto noack;
        !           175:                
        !           176:     if (!sp->sData)            /* If nothing in send queue, ignore */
        !           177:        goto noack;
        !           178: 
        !           179: 
        !           180:     do {                       /* This acks bytes in our buffer */
        !           181:        if (mp = sp->sbuf_mb) { /* Get ptr to oldest data header */
        !           182:            sp->sbuf_mb = gbuf_next(mp); /* unlink it from send queue */
        !           183:            eom = 1;
        !           184:        } else {
        !           185:            mp = sp->csbuf_mb;
        !           186:            sp->csbuf_mb = 0;
        !           187:            eom = 0;
        !           188:        }
        !           189: 
        !           190:        if (mp == 0) {          /* shouldn't happen! */
        !           191:            sp->sData = 0;
        !           192:            goto noack;
        !           193:        }
        !           194:        /*
        !           195:         * Does this ack the entire data block we're now pointing at?
        !           196:         */
        !           197:        if (LTE((sp->firstRtmtSeq + eom + (hlen = gbuf_msgsize(mp))),
        !           198:                 pktNextRecvSeq)) {
        !           199: 
        !           200:            gbuf_freem(mp);
        !           201: 
        !           202:            /* Update seq # of oldest byte in bfr */
        !           203:            sp->firstRtmtSeq += eom + hlen; 
        !           204: 
        !           205:            if ((sp->sbuf_mb == 0) && (sp->csbuf_mb == 0)) {
        !           206:                /* If this was only block, then ... */
        !           207:                sp->sData = 0;  /* ... no data in queue */
        !           208:                sp->writeFlush = 0;
        !           209:                if (sp->state == sClosing) /* this may allow us to close... */
        !           210:                    CheckOkToClose(sp);
        !           211:                atalk_enablew(sp->gref);
        !           212:                break;
        !           213:            }
        !           214:        }                       /* whole data block acked */
        !           215:        else                    /* Only some of the data was acked */
        !           216:        {
        !           217:            short acked;
        !           218: 
        !           219:            acked = (pktNextRecvSeq - sp->firstRtmtSeq);
        !           220:            mp = releaseData(mp, acked);
        !           221:            if (eom) {
        !           222:                if (mp) {
        !           223:                        gbuf_next(mp) = sp->sbuf_mb;
        !           224:                        sp->sbuf_mb = mp;
        !           225:                }
        !           226:            } else
        !           227:                sp->csbuf_mb = mp;
        !           228:                        
        !           229:            sp->firstRtmtSeq = pktNextRecvSeq; /* Update seq # oldest byte */
        !           230:            break;
        !           231:        }
        !           232:     } while (LT(sp->firstRtmtSeq, pktNextRecvSeq));
        !           233: 
        !           234:     if (sp->sData)             /* We've got stuff to send */
        !           235:        sp->callSend = 1;
        !           236: 
        !           237: noack:
        !           238:     sendWdwSeq = netw(UAS_VALUE(f->pktRecvWdw)) - 1 + pktNextRecvSeq;
        !           239: 
        !           240:     if (GT(sendWdwSeq, sp->sendWdwSeq))        /* Don't make send window smaller */
        !           241:     {
        !           242:        sp->callSend = 1;       /* His recv wdw opened, so see */
        !           243:                                /* if we can send more data */
        !           244:        sp->sendWdwSeq  = sendWdwSeq;
        !           245:     }
        !           246:     ATENABLE(s, sp->lock);
        !           247: }
        !           248: 
        !           249: /*
        !           250:  * RXData
        !           251:  *
        !           252:  * We just got a Data Packet
        !           253:  * See if it came from anybody we know.
        !           254:  *
        !           255:  * Called from ADSP Packet with interrupts masked completely OFF
        !           256:  *  *** In MacOSX interrupts do not seem to be off! ***
        !           257:  * 
        !           258:  * INPUTS:
        !           259:  *    Stream pointer
        !           260:  *    gbuf_t pointer
        !           261:  *    Pointer to ADSP header, (part of the mblk pointer to by mp)
        !           262:  *    Length of header plus data
        !           263:  * OUTPUTS:
        !           264:  *    Returns 1 if packet was ignored
        !           265:  */
        !           266: int RXData(sp, mp, f, len)     /* (CCBPtr sp, ADSP_FRAMEPtr f, word len) */
        !           267:     CCBPtr sp;
        !           268:     register gbuf_t *mp;
        !           269:     ADSP_FRAMEPtr f;
        !           270:     int len;
        !           271: {
        !           272:     int s, offset;
        !           273:     int PktFirstByteSeq;
        !           274:     short cnt;
        !           275:     char eom;
        !           276: 
        !           277:     len        -= ADSP_FRAME_LEN;
        !           278: 
        !           279:     /* Does packet have eom bit set? */
        !           280:     eom = (f->descriptor & ADSP_EOM_BIT) ? 1 : 0; 
        !           281: 
        !           282:     dPrintf(D_M_ADSP, D_L_TRACE, 
        !           283:            ("RXData: sp=0x%x, mbuf=0x%x, f=0x%x, len=%d, eom=%d\n", 
        !           284:             (unsigned)sp, (unsigned)mp, (unsigned)f, len, eom));
        !           285: 
        !           286:     KERNEL_DEBUG(DBG_ADSP_RCV, 1, sp, mp, len, eom);
        !           287: 
        !           288:     trace_mbufs(D_M_ADSP, "  mp", mp);
        !           289: 
        !           290:     PktFirstByteSeq = netdw(UAL_VALUE(f->pktFirstByteSeq)); /* Local copy */
        !           291: 
        !           292:     ATDISABLE(s, sp->lock);
        !           293:     if (GT(PktFirstByteSeq, sp->recvSeq)) /* missed a packet (out of order) */
        !           294:     {
        !           295:        if (sp->badSeqCnt++ > sp->badSeqCnt) /* Need to send rexmit advice */
        !           296:            sp->sendCtl |= B_CTL_RETRANSMIT;
        !           297:        ATENABLE(s, sp->lock);
        !           298:        CheckRecvSeq(sp, f);    /* Will set send ACK flag if requested */
        !           299:        CheckReadQueue(sp);
        !           300:        gbuf_freem(mp);
        !           301: 
        !           302:        KERNEL_DEBUG(DBG_ADSP_RCV, 2, sp, 0, 0, 0);
        !           303:        trace_mbufs(D_M_ADSP, "  exRXD m", sp->rbuf_mb);
        !           304:        dPrintf(D_M_ADSP, D_L_TRACE, ("    End RXData - missed a packet\n"));
        !           305: 
        !           306:        return 0;
        !           307:     }
        !           308:        
        !           309:     if (LTE(PktFirstByteSeq + len + eom, sp->recvSeq)) { /* duplicate data? */
        !           310:        ATENABLE(s, sp->lock);
        !           311:        CheckRecvSeq(sp, f);    /* Will set send ACK flag if requested */
        !           312:        CheckReadQueue(sp);
        !           313:        gbuf_freem(mp);
        !           314: 
        !           315:        KERNEL_DEBUG(DBG_ADSP_RCV, 3, sp, 0, 0, 0);
        !           316:        trace_mbufs(D_M_ADSP, "  exRXD m", sp->rbuf_mb);
        !           317:        dPrintf(D_M_ADSP, D_L_TRACE, ("    End RXData - duplicate data\n"));
        !           318: 
        !           319:        return 0;
        !           320:     }
        !           321: 
        !           322:     sp->badSeqCnt = 0;         /* reset out of sequence pckt counter */
        !           323: 
        !           324:     cnt = sp->recvSeq - PktFirstByteSeq; /* # bytes we've seen already */
        !           325:        
        !           326:     offset = ((unsigned char *)&f->data[cnt]) - (unsigned char *)gbuf_rptr(mp);
        !           327:     gbuf_rinc(mp,offset);
        !           328:                                /* point recv mblk to data (past headers) */
        !           329: 
        !           330:     len -= cnt;                        /* # of new data bytes */
        !           331: 
        !           332:     cnt = len;                 /* # bytes left to deal with */
        !           333:     
        !           334:     if (!sp->rData)            /* Recv bfr is empty */
        !           335:     {
        !           336:        sp->rData = 1;          /* Not empty any more */
        !           337: 
        !           338:        if ((sp->rpb)->ioc == mp) {
        !           339:           dPrintf(D_M_ADSP, D_L_TRACE, 
        !           340:                   ("RXData: (pb->ioc == mp) no stored data\n"));
        !           341:           KERNEL_DEBUG(DBG_ADSP_RCV, 4, sp, sp->rpb, 0, 0);
        !           342:        }
        !           343:        if (eom)
        !           344:            sp->rbuf_mb = mp;
        !           345:        else
        !           346:            sp->crbuf_mb = mp;
        !           347:     }                          /* Recv queue is empty */
        !           348:        
        !           349:     /*
        !           350:      * Else, there's already stored data.
        !           351:      */
        !           352:     else {
        !           353:         gbuf_t *rmp;
        !           354:        /*
        !           355:         * Is this a new "message?"
        !           356:         */
        !           357:        if (eom) {
        !           358:            if (sp->crbuf_mb) {
        !           359:                gbuf_linkb(sp->crbuf_mb, mp);
        !           360:                mp = sp->crbuf_mb;
        !           361:                sp->crbuf_mb = 0;
        !           362:            }
        !           363:            if (rmp = sp->rbuf_mb) {
        !           364:                /*
        !           365:                 * Add it to the end
        !           366:                 */
        !           367:                while(gbuf_next(rmp))
        !           368:                    rmp = gbuf_next(rmp);
        !           369:                gbuf_next(rmp) = mp;
        !           370:            } else
        !           371:                sp->rbuf_mb = mp;
        !           372:        } else if (sp->crbuf_mb) 
        !           373:            gbuf_linkb(sp->crbuf_mb, mp);
        !           374:        else
        !           375:            sp->crbuf_mb = mp;
        !           376:     }
        !           377:     sp->recvSeq += (cnt + eom);        /* We've got these bytes */
        !           378: 
        !           379:     /* %%% We really should call check recv seq first, but let's 
        !           380:      * continue to do it down here.  We really want to service the 
        !           381:      * received packet first, and maybe reenable scc ints before
        !           382:      * doing anything that might take a long while
        !           383:      */
        !           384: 
        !           385:     ATENABLE(s, sp->lock);
        !           386:     CheckRecvSeq(sp, f);       /* Will set send ACK flag if requested */
        !           387:     CheckReadQueue(sp);
        !           388:     KERNEL_DEBUG(DBG_ADSP_RCV, 5, sp, sp->rbuf_mb, 0, 0);
        !           389:     trace_mbufs(D_M_ADSP, "  eRXD m", sp->rbuf_mb);
        !           390:     return 0;
        !           391: } /* RXData */

unix.superglobalmegacorp.com

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