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