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

unix.superglobalmegacorp.com

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