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