]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netat/adsp_Read.c
a6438d0169abe6bda9b53ae2909d73f67193648e
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
34 * From v01.17 08/22/90 mbs
35 * Modified for MP, 1996 by Tuyen Nguyen
36 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
39 #include <sys/errno.h>
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <machine/spl.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
46 #include <sys/filedesc.h>
47 #include <sys/fcntl.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
52 #include <netat/sysglue.h>
53 #include <netat/appletalk.h>
54 #include <netat/at_pcb.h>
55 #include <netat/debug.h>
56 #include <netat/adsp.h>
57 #include <netat/adsp_internal.h>
62 * Checks to see if there is any data in the receive queue. If there
63 * is data, a pb and the data are queued to the user.
67 extern int adsp_check
;
69 int CheckReadQueue(sp
) /* (CCBPtr sp) */
72 register struct adspcmd
*pb
;
79 dPrintf(D_M_ADSP
, D_L_TRACE
, ("CheckReadQueue: sp=0x%x\n", (unsigned)sp
));
80 KERNEL_DEBUG(DBG_ADSP_READ
, 0, sp
, sp
->rbuf_mb
, sp
->rpb
, sp
->delay
);
81 trace_mbufs(D_M_ADSP_LOW
, " bCQR m", sp
->rbuf_mb
);
83 while (sp
->rData
&& (pb
= sp
->rpb
)) { /* have data */
84 dPrintf(D_M_ADSP
, D_L_TRACE
,
85 (" pb=0x%x, gref=0x%x, ioc=0x%x, reqCount=%d (have data)\n",
86 pb
, pb
->gref
, pb
->ioc
, pb
->u
.ioParams
.reqCount
));
87 KERNEL_DEBUG(DBG_ADSP_READ
, 1, pb
, pb
->gref
, pb
->ioc
, pb
->u
.ioParams
.reqCount
);
88 if (pb
->u
.ioParams
.reqCount
== 0) {
92 KERNEL_DEBUG(DBG_ADSP_READ
, 2, pb
, pb
->gref
, pb
->ioc
, 0);
93 adspioc_ack(0, pb
->ioc
, pb
->gref
);
95 KERNEL_DEBUG(DBG_ADSP_READ
, 3, pb
, pb
->gref
, 0, 0);
101 /* take the first packet off of sp->rbuf_mb or sp->crbuf_mb */
102 if (mp
= sp
->rbuf_mb
) { /* Get header for oldest data */
103 KERNEL_DEBUG(DBG_ADSP_READ
, 4, pb
, mp
, gbuf_msgsize(mp
), gbuf_next(mp
));
104 sp
->rbuf_mb
= gbuf_next(mp
);
107 } else if (mp
= sp
->crbuf_mb
) {
108 KERNEL_DEBUG(DBG_ADSP_READ
, 5, pb
, mp
, gbuf_msgsize(mp
), gbuf_next(mp
));
113 /* Get the first (reqCount-actCount) bytes and tack them onto
114 the end of pb->mp. If eom is set, put the remainder of the
115 data onto the front of sp->rbuf_mb, otherwise sp->crbuf_mb. */
116 cnt
= gbuf_msgsize(mp
); /* # of data bytes in it. */
117 if (cnt
> (unsigned short)(pb
->u
.ioParams
.reqCount
- pb
->u
.ioParams
.actCount
)) {
118 cnt
= pb
->u
.ioParams
.reqCount
- pb
->u
.ioParams
.actCount
;
119 /* m_split returns the tail */
120 if (!(tmp
= (gbuf_t
*)m_split(mp
, cnt
, M_DONTWAIT
))) {
125 gbuf_next(tmp
) = sp
->rbuf_mb
;
132 pb
->u
.ioParams
.actCount
+= cnt
;
133 gbuf_linkb(pb
->mp
, mp
);
136 pb
->u
.ioParams
.eom
= eom
;
138 * Now clean up receive buffer to remove all of the data
141 if ((sp
->rbuf_mb
== 0) &&
142 (sp
->crbuf_mb
== 0)) /* no more data blocks */
145 * If we've filled the parameter block, unlink it from read
146 * queue and complete it. We also need to do this if the connection
147 * is closed && there is no more stuff to read.
149 if (eom
|| (pb
->u
.ioParams
.actCount
>= pb
->u
.ioParams
.reqCount
) ||
150 ((sp
->state
== sClosed
) && (!sp
->rData
)) ) {
151 /* end of message, message is full, connection
152 * is closed and all data has been delivered,
153 * or we are not to "delay" data delivery.
156 sp
->rpb
= pb
->qLink
; /* dequeue request */
157 if (pb
->ioc
) { /* data to be delivered at the time of the */
158 mp
= gbuf_cont(pb
->mp
); /* ioctl call */
159 gbuf_cont(pb
->mp
) = 0;
160 gref
= (gref_t
*)pb
->gref
;
161 adspioc_ack(0, pb
->ioc
, pb
->gref
);
162 dPrintf(D_M_ADSP
, D_L_TRACE
, (" (pb->ioc) mp=%x\n", mp
));
163 KERNEL_DEBUG(DBG_ADSP_READ
, 0x0A, pb
, mp
,
164 gbuf_next(mp
), gbuf_cont(mp
));
166 dPrintf(D_M_ADSP
, D_L_TRACE
,
167 (" (data) size req=%d\n", pb
->u
.ioParams
.actCount
));
168 KERNEL_DEBUG(DBG_ADSP_READ
, 0x0B, pb
, pb
->ioc
,
169 pb
->u
.ioParams
.reqCount
, pb
->u
.ioParams
.actCount
);
170 } else { /* complete an queued async request */
171 KERNEL_DEBUG(DBG_ADSP_READ
, 0x0C, pb
, sp
,
172 pb
->u
.ioParams
.actCount
, sp
->delay
);
178 if (pb
= sp
->rpb
) { /* if there is an outstanding request */
179 dPrintf(D_M_ADSP
, D_L_TRACE
,
180 (" pb=0x%x, ioc=0x%x, reqCount=%d (no more data)\n",
181 pb
, pb
->ioc
, pb
->u
.ioParams
.reqCount
));
182 KERNEL_DEBUG(DBG_ADSP_READ
, 0x0D, pb
, pb
->ioc
,
183 pb
->u
.ioParams
.reqCount
, pb
->u
.ioParams
.actCount
);
185 if (sp
->state
== sClosed
) {
187 KERNEL_DEBUG(DBG_ADSP_READ
, 0x0E, pb
, sp
, pb
->ioc
, 0);
189 pb
->u
.ioParams
.actCount
= 0;
190 pb
->u
.ioParams
.eom
= 0;
193 adspioc_ack(0, pb
->ioc
, pb
->gref
);
199 } else if (pb
->ioc
) { /* if request not complete and this
200 * is an active ioctl, release user */
203 tmp
= gbuf_cont(pb
->mp
); /* detatch perhaps delayed data */
204 gbuf_cont(pb
->mp
) = 0;
205 if (mp
= gbuf_copym(pb
->mp
)) { /* otherwise, duplicate user request */
206 KERNEL_DEBUG(DBG_ADSP_READ
, 0x0F, pb
, sp
, pb
->mp
, 0);
207 adspioc_ack(0, pb
->ioc
, pb
->gref
); /* release user */
208 pb
= (struct adspcmd
*)gbuf_rptr(mp
); /* get new parameter block */
211 gbuf_cont(pb
->mp
) = tmp
; /* reattach data */
212 pb
->qLink
= sp
->rpb
; /* requeue the duplicate at the head */
214 } else { /* there is no data left, but no space
215 * to duplicate the parameter block, so
216 * put what must be a non EOM message
217 * back on the current receive queue, and
220 KERNEL_DEBUG(DBG_ADSP_READ
, 0x10, pb
, sp
, pb
->mp
, 0);
225 pb
->ioResult
= errDSPQueueSize
;
226 adspioc_ack(ENOBUFS
, pb
->ioc
, pb
->gref
);
231 * The receive window has opened. If was previously closed, then we
232 * need to notify the other guy that we now have room to receive more
233 * data. But, in order to cut down on lots of small data packets,
234 * we'll wait until the recieve buffer is /14 empy before telling
235 * him that there's room in our receive buffer.
237 if (sp
->rbufFull
&& (CalcRecvWdw(sp
) > (sp
->rbuflen
>> 2))) {
243 KERNEL_DEBUG(DBG_ADSP_READ
, 0x11, sp
, 0, 0, 0);
244 trace_mbufs(D_M_ADSP_LOW
, " eCQR m", sp
->rbuf_mb
);
251 * Checks to see if there is any attention data and passes the data back
252 * in the passed in pb.
261 int CheckAttn(sp
, pb
) /* (CCBPtr sp) */
263 register struct adspcmd
*pb
;
268 dPrintf(D_M_ADSP
, D_L_TRACE
,
269 ("CheckAttn: sp=0x%x, pb=0x%x\n", (unsigned)sp
, (unsigned)pb
));
271 if (mp
= sp
->attn_mb
) {
274 * Deliver the attention data to the user.
276 gref
= (gref_t
*)pb
->gref
;
277 pb
->u
.attnParams
.attnSize
= sp
->attnSize
;
278 pb
->u
.attnParams
.attnCode
= sp
->attnCode
;
283 sp
->userFlags
&= ~eAttention
;
285 * Now clean up receive buffer to remove all of the data
294 pb
->u
.attnParams
.attnSize
= 0;
295 pb
->u
.attnParams
.attnCode
= 0;
296 pb
->ioResult
= 1; /* not done */
298 adspioc_ack(0, pb
->ioc
, pb
->gref
);
309 * --> sp stream pointer
310 * --> pb user request parameter block
313 * <-- actCount actual number of bytes read
314 * <-- eom one if end-of-message, zero otherwise
317 * errRefNum bad connection refnum
319 * errFwdReset read terminated by forward reset
320 * errAborted request aborted by Remove or Close call
322 int adspRead(sp
, pb
) /* (DSPPBPtr pb) */
324 register struct adspcmd
*pb
;
328 dPrintf(D_M_ADSP
, D_L_TRACE
,
329 ("adspRead: sp=0x%x, pb=0x%x\n", (unsigned)sp
, (unsigned)pb
));
331 KERNEL_DEBUG(DBG_ADSP_READ
, 0x12, sp
, pb
, sp
->state
, sp
->rData
);
334 pb
->ioResult
= errRefNum
;
339 * It's OK to read on a closed, or closing session
341 if (sp
->state
!= sOpen
&& sp
->state
!= sClosing
&& sp
->state
!= sClosed
) {
342 pb
->ioResult
= errState
;
345 if (sp
->rData
&& (sp
->rpb
== 0)) { /* if data, and no queue of pbs */
346 qAddToEnd(&sp
->rpb
, pb
); /* deliver data to user directly */
348 } else if ((pb
->u
.ioParams
.reqCount
== 0) && (sp
->rpb
== 0)) {
351 adspioc_ack(0, pb
->ioc
, pb
->gref
);
355 if (mp
= gbuf_copym(pb
->mp
)) { /* otherwise, duplicate user request */
356 adspioc_ack(0, pb
->ioc
, pb
->gref
); /* release user */
357 pb
= (struct adspcmd
*)gbuf_rptr(mp
); /* get new parameter block */
360 qAddToEnd(&sp
->rpb
, pb
); /* and queue it for later */
362 pb
->ioResult
= errDSPQueueSize
;
368 CheckSend(sp
); /* If recv window opened, we might */
369 /* send an unsolicited ACK. */
378 * --> sp stream pointer
379 * --> pb user request parameter block
385 * errRefNum bad connection refnum
386 * errState connection is not in the right state
388 int adspReadAttention(sp
, pb
) /* (DSPPBPtr pb) */
390 register struct adspcmd
*pb
;
392 dPrintf(D_M_ADSP
, D_L_TRACE
,
393 ("adspReadAttention: sp=0x%x, pb=0x%x\n", (unsigned)sp
, (unsigned)pb
));
395 pb
->ioResult
= errRefNum
;
400 * It's OK to read on a closed, or closing session
402 if (sp
->state
!= sOpen
&& sp
->state
!= sClosing
&& sp
->state
!= sClosed
) {
403 pb
->ioResult
= errState
;
407 CheckAttn(sp
, pb
); /* Anything in the attention queue */
408 CheckReadQueue(sp
); /* check to see if receive window has opened */
410 CheckSend(sp
); /* If recv window opened, we might */
411 /* send an unsolicited ACK. */
414 } /* adspReadAttention */