|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.