Annotation of XNU/bsd/netat/adsp_RxData.c, revision 1.1.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.