Annotation of XNU/bsd/netat/adsp_Read.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:  *
                     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.