Annotation of kernel/bsd/netat/adsp_Read.c, revision 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: /*
        !            29:  * CheckReadQueue
        !            30:  *
        !            31:  * Checks to see if there is any data in the receive queue.  If there
        !            32:  * is data, a pb and the data are queued to the user.
        !            33:  * 
        !            34:  *     
        !            35:  */
        !            36: extern int adsp_check;
        !            37: 
        !            38: int CheckReadQueue(sp)         /* (CCBPtr sp) */
        !            39:     register CCBPtr sp;
        !            40: {
        !            41:     register struct adspcmd *pb;
        !            42:     int s;
        !            43:     unsigned short cnt;
        !            44:     char eom;
        !            45:     register gbuf_t *mp;
        !            46:     register gbuf_t *tmp;
        !            47:        gref_t *gref;
        !            48:        
        !            49:     ATDISABLE(s, sp->lock);
        !            50:     while (sp->rData && (pb = sp->rpb)) {              /* have data */
        !            51:        if (pb->u.ioParams.reqCount == 0) {
        !            52:            pb->ioResult = 0;
        !            53:            sp->rpb = pb->qLink;
        !            54:            if (pb->ioc) {
        !            55:                adspioc_ack(0, pb->ioc, pb->gref);
        !            56:            } else {
        !            57:                completepb(sp, pb);
        !            58:            }
        !            59:            continue;
        !            60:        }
        !            61:            
        !            62:        if (mp = sp->rbuf_mb) { /* Get header for oldest data */
        !            63:            sp->rbuf_mb = gbuf_next(mp);
        !            64:            gbuf_next(mp) = 0;
        !            65:            eom = 1;
        !            66:        } else if (mp = sp->crbuf_mb) {
        !            67:            sp->crbuf_mb = 0;
        !            68:            eom = 0;
        !            69:        }
        !            70:        cnt = gbuf_msgsize(mp); /* # of data bytes in it. */
        !            71:        if (cnt > (unsigned short) (pb->u.ioParams.reqCount - pb->u.ioParams.actCount)) {
        !            72:            cnt = pb->u.ioParams.reqCount - pb->u.ioParams.actCount;
        !            73:            pb->u.ioParams.actCount += cnt;
        !            74:            while (cnt >= (unsigned short) gbuf_len(mp)) {
        !            75:                cnt -= gbuf_len(mp);
        !            76:                tmp = mp;
        !            77:                mp = gbuf_cont(mp);
        !            78:                gbuf_cont(tmp) = 0;
        !            79:                gbuf_linkb(pb->mp,tmp);
        !            80:            }
        !            81:            if (cnt) {
        !            82:                tmp = gbuf_dupb(mp);
        !            83:                if (tmp == NULL) {
        !            84:                    pb->u.ioParams.actCount -= cnt; /* can't deliver it now */
        !            85:                } else {
        !            86:                        gbuf_wset(tmp,cnt);
        !            87:                        gbuf_rinc(mp,cnt);
        !            88:                        gbuf_linkb(pb->mp,tmp);
        !            89:                }
        !            90:            }
        !            91:            if (eom) {
        !            92:                gbuf_next(mp) = sp->rbuf_mb;
        !            93:                sp->rbuf_mb = mp;
        !            94:                eom = 0;
        !            95:            } else
        !            96:                sp->crbuf_mb = mp;
        !            97:        } else {
        !            98:            pb->u.ioParams.actCount += cnt;
        !            99:            gbuf_linkb(pb->mp,mp);
        !           100:        }
        !           101:        pb->u.ioParams.eom = eom;
        !           102:            
        !           103:        /*
        !           104:         * Now clean up receive buffer to remove all of the data 
        !           105:         * we just copied
        !           106:         */
        !           107:        if ((sp->rbuf_mb == 0) && 
        !           108:            (sp->crbuf_mb == 0)) /* no more data blocks */
        !           109:            sp->rData = 0;
        !           110:        
        !           111:        /*
        !           112:         * If we've filled the parameter block, unlink it from read 
        !           113:         * queue and complete it. We also need to do this if the connection
        !           114:         * is closed && there is no more stuff to read.
        !           115:         */
        !           116:        if (eom || (pb->u.ioParams.actCount >= pb->u.ioParams.reqCount) ||
        !           117:            ((sp->state == sClosed) && (!sp->rData))) {
        !           118:                                /* end of message, message is full, connection
        !           119:                                 * is closed and all data has been delivered,
        !           120:                                 * or we are not to "delay" data delivery.
        !           121:                                 */
        !           122:            pb->ioResult = 0;
        !           123:            sp->rpb = pb->qLink; /* dequeue request */
        !           124:            if (pb->ioc) {      /* data to be delivered at the time of the */
        !           125:                mp = gbuf_cont(pb->mp); /* ioctl call */
        !           126:                gbuf_cont(pb->mp) = 0;
        !           127:                gref = (gref_t *)pb->gref;
        !           128:                adspioc_ack(0, pb->ioc, pb->gref);
        !           129:                SndMsgUp(gref, mp);
        !           130:            } else              /* complete an queued async request */
        !           131:                completepb(sp, pb);
        !           132:        } 
        !           133:     }                          /* while */
        !           134: 
        !           135:     if (pb = sp->rpb) {                /* if there is an outstanding request */
        !           136:        if (sp->state == sClosed) {
        !           137:            while (pb) {
        !           138:                    pb->ioResult = 0;
        !           139:                    pb->u.ioParams.actCount = 0;
        !           140:                    pb->u.ioParams.eom = 0;
        !           141:                    sp->rpb = pb->qLink;
        !           142:                    if (pb->ioc) {
        !           143:                            adspioc_ack(0, pb->ioc, pb->gref);
        !           144:                    } else {
        !           145:                            completepb(sp, pb);
        !           146:                    }
        !           147:                    pb = sp->rpb;
        !           148:            }
        !           149:        } else if (pb->ioc) {   /* if request not complete and this
        !           150:                                 * is an active ioctl, release user */
        !           151:            sp->rpb = pb->qLink;
        !           152:            pb->ioResult = 1;
        !           153:            tmp = gbuf_cont(pb->mp); /* detatch perhaps delayed data */
        !           154:            gbuf_cont(pb->mp) = 0;
        !           155:            if (mp = gbuf_copym(pb->mp)) { /* otherwise, duplicate user request */
        !           156:                    adspioc_ack(0, pb->ioc, pb->gref);  /* release user */
        !           157:                    pb = (struct adspcmd *)gbuf_rptr(mp);       /* get new parameter block */
        !           158:                    pb->ioc = 0;
        !           159:                    pb->mp = mp;
        !           160:                    gbuf_cont(pb->mp) = tmp; /* reattach data */
        !           161:                    pb->qLink = sp->rpb; /* requeue the duplicate at the head */
        !           162:                    sp->rpb = pb;
        !           163:            } else {            /* there is no data left, but no space
        !           164:                                 * to duplicate the parameter block, so
        !           165:                                 * put what must be a non EOM message 
        !           166:                                 * back on the current receive queue, and
        !           167:                                 * error out the user
        !           168:                                 */
        !           169:                    if (tmp) {
        !           170:                            sp->crbuf_mb = tmp;
        !           171:                            sp->rData = 1;
        !           172:                    }
        !           173:                    pb->ioResult = errDSPQueueSize;
        !           174:                    adspioc_ack(ENOBUFS, pb->ioc, pb->gref);
        !           175:            }
        !           176:        } 
        !           177:     }
        !           178:     /* 
        !           179:      * The receive window has opened.  If was previously closed, then we
        !           180:      * need to notify the other guy that we now have room to receive more
        !           181:      * data.  But, in order to cut down on lots of small data packets,
        !           182:      * we'll wait until the recieve buffer  is /14 empy before telling
        !           183:      * him that there's room in our receive buffer.
        !           184:      */
        !           185:     if (sp->rbufFull && (CalcRecvWdw(sp) > (sp->rbuflen >> 2))) {
        !           186:        sp->rbufFull = 0;
        !           187:        sp->sendDataAck = 1;
        !           188:        sp->callSend = 1;
        !           189:     }
        !           190: 
        !           191:     ATENABLE(s, sp->lock);
        !           192:     return 0;
        !           193: }
        !           194: 
        !           195: /*
        !           196:  * CheckAttn
        !           197:  *
        !           198:  * Checks to see if there is any attention data and passes the data back
        !           199:  * in the passed in pb.
        !           200:  * 
        !           201:  * INPUTS:
        !           202:  *     sp
        !           203:  *     pb
        !           204:  *     
        !           205:  * OUTPUTS:
        !           206:  *     
        !           207:  */
        !           208: int CheckAttn(sp, pb)          /* (CCBPtr sp) */
        !           209:     register CCBPtr sp;
        !           210:     register struct adspcmd *pb;
        !           211: {
        !           212:     int s;
        !           213:     gbuf_t *mp;
        !           214:        gref_t *gref;
        !           215:        
        !           216:     ATDISABLE(s, sp->lock);
        !           217:     if (mp = sp->attn_mb) {
        !           218: 
        !           219:        /*
        !           220:         * Deliver the attention data to the user. 
        !           221:         */
        !           222:        gref = (gref_t *)pb->gref;
        !           223:        pb->u.attnParams.attnSize = sp->attnSize;
        !           224:        pb->u.attnParams.attnCode = sp->attnCode;
        !           225:        if (!sp->attnSize) {
        !           226:            gbuf_freem(mp);
        !           227:            mp = 0;
        !           228:        }
        !           229:        sp->userFlags &= ~eAttention;
        !           230:        /*
        !           231:         * Now clean up receive buffer to remove all of the data 
        !           232:         * we just copied
        !           233:         */
        !           234:        sp->attn_mb = 0;
        !           235:        pb->ioResult = 0;
        !           236:     } else {
        !           237:        /*
        !           238:         * No data...
        !           239:         */
        !           240:        pb->u.attnParams.attnSize = 0;
        !           241:        pb->u.attnParams.attnCode = 0;
        !           242:        pb->ioResult = 1;       /* not done */
        !           243:     }
        !           244:     adspioc_ack(0, pb->ioc, pb->gref);
        !           245:     if (mp) {
        !           246:        SndMsgUp(gref, mp);
        !           247:        }
        !           248:     ATENABLE(s, sp->lock);
        !           249:     return 0;
        !           250: }
        !           251: 
        !           252: /*
        !           253:  * adspRead
        !           254:  * 
        !           255:  * INPUTS:
        !           256:  *     --> sp                  stream pointer
        !           257:  *     --> pb                  user request parameter block
        !           258:  *
        !           259:  * OUTPUTS:
        !           260:  *     <-- actCount            actual number of bytes read
        !           261:  *     <-- eom                 one if end-of-message, zero otherwise
        !           262:  *
        !           263:  * ERRORS:
        !           264:  *     errRefNum               bad connection refnum
        !           265:  *     errState
        !           266:  *     errFwdReset             read terminated by forward reset
        !           267:  *     errAborted              request aborted by Remove or Close call
        !           268:  */
        !           269: int adspRead(sp, pb)           /* (DSPPBPtr pb) */
        !           270:     register CCBPtr sp;
        !           271:     register struct adspcmd *pb;
        !           272: {
        !           273:     register gbuf_t *mp;
        !           274:     int        s;
        !           275: 
        !           276:     if (sp == 0) {
        !           277:        pb->ioResult = errRefNum;
        !           278:        return EINVAL;
        !           279:     }
        !           280:        
        !           281:     /*
        !           282:      * It's OK to read on a closed, or closing session
        !           283:      */
        !           284:     ATDISABLE(s, sp->lock);
        !           285:     if (sp->state != sOpen && sp->state != sClosing && sp->state != sClosed) {
        !           286:        ATENABLE(s, sp->lock);
        !           287:        pb->ioResult = errState;
        !           288:        return EINVAL;
        !           289:     }
        !           290: 
        !           291:     if (sp->rData && (sp->rpb == 0)) { /* if data, and no queue of pbs */
        !           292:        qAddToEnd(&sp->rpb, pb); /* deliver data to user directly */
        !           293:        ATENABLE(s, sp->lock);
        !           294:        CheckReadQueue(sp);
        !           295:     } else if ((pb->u.ioParams.reqCount == 0) && (sp->rpb == 0)) {
        !           296:            /* empty read */
        !           297:            ATENABLE(s, sp->lock);
        !           298:            pb->ioResult = 0;
        !           299:            adspioc_ack(0, pb->ioc, pb->gref);
        !           300:            return 0;
        !           301:     } else {
        !           302:        pb->ioResult = 1;
        !           303:        if (mp = gbuf_copym(pb->mp)) { /* otherwise, duplicate user request */
        !           304:                adspioc_ack(0, pb->ioc, pb->gref);      /* release user */
        !           305:                pb = (struct adspcmd *)gbuf_rptr(mp);   /* get new parameter block */
        !           306:                pb->ioc = 0;
        !           307:                pb->mp = mp;
        !           308:                qAddToEnd(&sp->rpb, pb); /* and queue it for later */
        !           309:                ATENABLE(s, sp->lock);
        !           310:        } else {
        !           311:                ATENABLE(s, sp->lock);
        !           312:                pb->ioResult = errDSPQueueSize;
        !           313:                return ENOBUFS;
        !           314:        }
        !           315:     }
        !           316:     if (sp->callSend) {
        !           317:        CheckSend(sp);          /* If recv window opened, we might */
        !           318:                                /* send an unsolicited ACK. */
        !           319:     }
        !           320:     return 0;
        !           321: }
        !           322: 
        !           323: /*
        !           324:  * dspReadAttention
        !           325:  * 
        !           326:  * INPUTS:
        !           327:  *     --> sp                  stream pointer
        !           328:  *     --> pb                  user request parameter block
        !           329:  *
        !           330:  * OUTPUTS:
        !           331:  *     <-- NONE
        !           332:  *
        !           333:  * ERRORS:
        !           334:  *     errRefNum               bad connection refnum
        !           335:  *     errState                connection is not in the right state
        !           336:  */
        !           337: int adspReadAttention(sp, pb)          /* (DSPPBPtr pb) */
        !           338:     register CCBPtr sp;
        !           339:     register struct adspcmd *pb;
        !           340: {
        !           341:     OSErr err;
        !           342: 
        !           343:     if (sp == 0) {
        !           344:        pb->ioResult = errRefNum;
        !           345:        return EINVAL;
        !           346:     }
        !           347:        
        !           348:     /*
        !           349:      * It's OK to read on a closed, or closing session
        !           350:      */
        !           351:     if (sp->state != sOpen && sp->state != sClosing && sp->state != sClosed) {
        !           352:        pb->ioResult = errState;
        !           353:        return EINVAL;
        !           354:     }
        !           355: 
        !           356:     CheckAttn(sp, pb);         /* Anything in the attention queue */
        !           357:     CheckReadQueue(sp);                /* check to see if receive window has opened */
        !           358:     if (sp->callSend) {
        !           359:        CheckSend(sp);          /* If recv window opened, we might */
        !           360:                                /* send an unsolicited ACK. */
        !           361:        }
        !           362:     return 0;
        !           363: }

unix.superglobalmegacorp.com

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