|
|
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.