]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netat/adsp_stream.c
cd23ec2ac5b7975d86aa300fbceb60f744a49519
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_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 License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1995-1998 Apple Computer, Inc.
30 * All Rights Reserved.
34 * 09/07/95 - Modified for performance (Tuyen Nguyen)
35 * Modified for MP, 1996 by Tuyen Nguyen
36 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
38 #include <sys/errno.h>
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <machine/spl.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
45 #include <sys/filedesc.h>
46 #include <sys/fcntl.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
51 #include <sys/ioctl.h>
52 #include <sys/malloc.h>
56 #include <netat/sysglue.h>
57 #include <netat/appletalk.h>
58 #include <netat/ddp.h>
59 #include <netat/at_snmp.h>
60 #include <netat/at_pcb.h>
61 #include <netat/debug.h>
62 #include <netat/at_var.h>
63 #include <netat/adsp.h>
64 #include <netat/adsp_internal.h>
68 static void adsp_iocack();
69 static void adsp_iocnak();
70 void adsp_dequeue_ccb();
71 unsigned char adspAssignSocket();
72 int adspallocate(), adsprelease();
75 atlock_t adspall_lock
;
76 atlock_t adspgen_lock
;
82 char adsp_inputC
[256];
83 CCB
*adsp_inputQ
[256];
85 extern at_ifaddr_t
*ifID_home
;
98 switch (gbuf_type(mp
)) {
100 p
= (at_ddp_t
*)gbuf_rptr(mp
);
101 ATDISABLE(s
, adspall_lock
);
102 sp
= adsp_inputQ
[p
->dst_socket
];
103 if ((sp
== 0) || (sp
->gref
==0) || (sp
->state
==sClosed
))
105 ATENABLE(s
, adspall_lock
);
109 else if (sp
->otccbLink
!= 0) {
111 if ((sp
->remoteAddress
.a
.node
== p
->src_node
)
112 && (sp
->remoteAddress
.a
.socket
== p
->src_socket
)
113 && (sp
->remoteAddress
.a
.net
== NET_VALUE(p
->src_net
)))
115 } while ((sp
= sp
->otccbLink
) != 0);
118 ATENABLE(s
, adspall_lock
);
125 if (sp
->deferred_mb
) {
126 for (mb
=sp
->deferred_mb
; gbuf_next(mb
); mb
=gbuf_next(mb
)) ;
129 sp
->deferred_mb
= mp
;
130 ATENABLE(s
, adspall_lock
);
133 ATDISABLE(l
, sp
->lockRemove
);
135 ATENABLE(l
, adspall_lock
);
137 adsp_rput(sp
->gref
, mp
);
138 if ((mp
= sp
->deferred_mb
) != 0) {
139 sp
->deferred_mb
= gbuf_next(mp
);
144 ATENABLE(s
, sp
->lockRemove
);
149 gref
= (gref_t
*)((ioc_t
*)gbuf_rptr(mp
))->ioc_private
;
153 #ifdef APPLETALK_DEBUG
154 kprintf("unexpected MSG_IOCTL in adsp_input()");
167 int adsp_readable(gref
)
175 * we don't have the structure we need to determine
176 * if there's data available... we return readable in
177 * this case to keep from hanging up in the select
178 * a subsequent read will run into the same missing data
179 * structure and return an error... the ATselect code does
180 * this if it can't retrieve the 'gref' structure from the
181 * file table for the fd specified
185 sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
191 int adsp_writeable(gref
)
199 * we don't have the structure we need to determine
200 * if there's room available... we return writeable in
201 * this case to keep from hanging up in the select
202 * a subsequent write will run into the same missing data
203 * structure and return an error... the ATselect code does
204 * this if it can't retrieve the 'gref' structure from the
205 * file table for the fd specified
209 sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
210 ATDISABLE(s
, sp
->lock
);
211 rc
= CalcSendQFree(sp
);
212 ATENABLE(s
, sp
->lock
);
217 static void adsp_init()
222 bzero(adsp_pidM
, sizeof(adsp_pidM
));
223 bzero(adsp_inputC
, sizeof(adsp_inputC
));
224 bzero(adsp_inputQ
, sizeof(adsp_inputQ
));
229 * ADSP open and close routines. These routines
230 * initalize and release the ADSP structures. They do not
231 * have anything to do with "connections"
243 if (!adspAllocateCCB(gref
))
244 return(ENOBUFS
); /* can't get buffers */
246 sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
247 gref
->readable
= adsp_readable
;
248 gref
->writeable
= adsp_writeable
;
249 ATDISABLE(s
, adspall_lock
);
250 if ((sp
->otccbLink
= ccb_used_list
) != 0)
251 sp
->otccbLink
->ccbLink
= sp
;
253 ATENABLE(s
, adspall_lock
);
261 unsigned char localSocket
;
263 /* make sure we've not yet removed the CCB (e.g., due to TrashSession) */
264 ATDISABLE(l
, adspgen_lock
);
266 CCBPtr sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
267 ATDISABLE(s
, sp
->lock
);
268 ATENABLE(s
, adspgen_lock
);
269 localSocket
= sp
->localSocket
;
270 ATENABLE(l
, sp
->lock
);
275 adsp_dequeue_ccb(sp
);
276 gbuf_freeb((gbuf_t
*)gref
->info
);
279 ATENABLE(l
, adspgen_lock
);
289 * ADSP streams read put and service routines.
292 void adsp_rput(gref
, mp
)
293 gref_t
*gref
; /* READ queue */
296 switch (gbuf_type(mp
)) {
300 switch (adspReadHandler(gref
, mp
)) {
302 atalk_putnext(gref
, mp
);
309 #ifdef APPLETALK_DEBUG
310 kprintf("adsp_rput received MSG_ERROR");
314 CheckReadQueue(gbuf_rptr(((gbuf_t
*)gref
->info
)));
315 CheckSend(gbuf_rptr(((gbuf_t
*)gref
->info
)));
317 switch (gbuf_type(mp
)) {
321 if (adspReadHandler(gref
, mp
) == STR_PUTNEXT
)
322 atalk_putnext(gref
, mp
);
325 atalk_putnext(gref
, mp
);
336 * ADSP streams write put and service routines.
340 int adsp_wput(gref
, mp
)
341 gref_t
*gref
; /* WRITE queue */
351 sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
355 if (gbuf_type(mp
) == MSG_IOCTL
) {
356 iocbp
= (ioc_t
*)gbuf_rptr(mp
);
357 switch (iocbp
->ioc_cmd
) {
362 if (gbuf_cont(mp
) == NULL
) {
363 iocbp
->ioc_rval
= -1;
364 adsp_iocnak(gref
, mp
, EINVAL
);
366 v
= *(unsigned char *)gbuf_rptr(gbuf_cont(mp
));
367 ATDISABLE(s
, adspall_lock
);
369 && ((v
> DDP_SOCKET_LAST
) || (v
< 2)
370 || ddp_socket_inuse(v
, DDP_ADSP
))) {
371 ATENABLE(s
, adspall_lock
);
372 iocbp
->ioc_rval
= -1;
373 adsp_iocnak(gref
, mp
, EINVAL
);
377 ATENABLE(s
, adspall_lock
);
378 if ((v
= adspAssignSocket(gref
, 0)) == 0) {
379 iocbp
->ioc_rval
= -1;
380 adsp_iocnak(gref
, mp
, EINVAL
);
386 adsp_pidM
[v
] = sp
->pid
;
387 ATENABLE(s
, adspall_lock
);
388 adsp_dequeue_ccb(sp
);
390 *(unsigned char *)gbuf_rptr(gbuf_cont(mp
)) = v
;
393 adsp_iocack(gref
, mp
);
403 if (((xm
= gbuf_cont(mp
)) == NULL
)
404 && ((xm
= gbuf_alloc(sizeof(at_inet_t
), PRI_MED
)) == NULL
)) {
405 iocbp
->ioc_rval
= -1;
406 adsp_iocnak(gref
, mp
, ENOBUFS
);
410 gbuf_wset(xm
,sizeof(at_inet_t
));
411 addr
= (at_inet_t
*)gbuf_rptr(xm
);
412 if (iocbp
->ioc_cmd
== ADSPGETSOCK
) {
413 /* Obtain Network and Node Id's from DDP */
414 /* *** was ddp_get_cfg() *** */
415 addr
->net
= ifID_home
->ifThisNode
.s_net
;
416 addr
->node
= ifID_home
->ifThisNode
.s_node
;
417 addr
->socket
= (sp
)? sp
->localSocket
: 0;
420 *addr
= sp
->remoteAddress
.a
;
427 adsp_iocack(gref
, mp
);
430 case DDP_IOC_GET_CFG
:
431 /* respond to an DDP_IOC_GET_CFG sent on an adsp fd */
432 if (((xm
= gbuf_cont(mp
)) == NULL
) &&
433 (xm
= gbuf_alloc(sizeof(ddp_addr_t
), PRI_MED
)) == NULL
) {
434 iocbp
->ioc_rval
= -1;
435 adsp_iocnak(gref
, mp
, ENOBUFS
);
439 gbuf_wset(xm
, sizeof(ddp_addr_t
));
440 /* Obtain Network and Node Id's from DDP */
442 /* *** was ddp_get_cfg() *** */
444 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(mp
));
445 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
446 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
447 cfgp
->inet
.socket
= (sp
)? sp
->localSocket
: 0;
448 cfgp
->ddptype
= DDP_ADSP
;
451 adsp_iocack(gref
, mp
);
459 ATDISABLE(s
, sp
->lockClose
);
460 rc
= adspWriteHandler(gref
, mp
);
461 ATENABLE(s
, sp
->lockClose
);
465 if (gbuf_type(mp
) == MSG_IOCTL
) {
466 iocbp
= (ioc_t
*)gbuf_rptr(mp
);
467 iocbp
->ioc_private
= (void *)gref
;
483 void adspioc_ack(errno
, m
, gref
)
492 iocbp
= (ioc_t
*) gbuf_rptr(m
);
494 iocbp
->ioc_error
= errno
; /* set the errno */
495 iocbp
->ioc_count
= gbuf_msgsize(gbuf_cont(m
));
496 if (gbuf_type(m
) == MSG_IOCTL
) /* if an ioctl, this is an ack */
497 gbuf_set_type(m
, MSG_IOCACK
); /* and ALWAYS update the user */
498 /* ioctl structure */
499 trace_mbufs(D_M_ADSP
,"A ", m
);
503 static void adsp_iocack(gref
, m
)
507 if (gbuf_type(m
) == MSG_IOCTL
)
508 gbuf_set_type(m
, MSG_IOCACK
);
511 ((ioc_t
*)gbuf_rptr(m
))->ioc_count
= gbuf_msgsize(gbuf_cont(m
));
513 ((ioc_t
*)gbuf_rptr(m
))->ioc_count
= 0;
519 static void adsp_iocnak(gref
, m
, err
)
524 if (gbuf_type(m
) == MSG_IOCTL
)
525 gbuf_set_type(m
, MSG_IOCNAK
);
526 ((ioc_t
*)gbuf_rptr(m
))->ioc_count
= 0;
530 ((ioc_t
*)gbuf_rptr(m
))->ioc_error
= err
;
533 gbuf_freem(gbuf_cont(m
));
540 adspAssignSocket(gref
, flag
)
544 unsigned char sVal
, sMax
, sMin
, sSav
, inputC
;
548 sMax
= flag
? DDP_SOCKET_LAST
-46 : DDP_SOCKET_LAST
-6;
549 sMin
= DDP_SOCKET_1st_DYNAMIC
;
551 ATDISABLE(s
, adspall_lock
);
552 for (inputC
=255, sVal
=sMax
; sVal
>= sMin
; sVal
--) {
553 if (!ddp_socket_inuse(sVal
, DDP_ADSP
))
556 if (adsp_inputC
[sVal
] &&
557 /* meaning that raw DDP doesn't have it */
558 (adsp_inputC
[sVal
] < inputC
)
559 && (adsp_inputQ
[sVal
]->state
== sOpen
)) {
560 inputC
= adsp_inputC
[sVal
];
566 if (!flag
|| (inputC
== 255)) {
567 ATENABLE(s
, adspall_lock
);
572 sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
573 ATENABLE(s
, adspall_lock
);
574 adsp_dequeue_ccb(sp
);
575 ATDISABLE(s
, adspall_lock
);
577 sp
->otccbLink
= adsp_inputQ
[sVal
];
578 adsp_inputQ
[sVal
] = sp
;
580 adsp_pidM
[sVal
] = sp
->pid
;
581 ATENABLE(s
, adspall_lock
);
586 adspDeassignSocket(sp
)
595 dPrintf(D_M_ADSP
, D_L_TRACE
, ("adspDeassignSocket: pid=%d,s=%d\n",
596 sp
->pid
, sp
->localSocket
));
597 ATDISABLE(s
, adspall_lock
);
598 sVal
= sp
->localSocket
;
599 if ((curr_sp
= adsp_inputQ
[sVal
]) != 0) {
601 while (curr_sp
!= sp
) {
603 curr_sp
= curr_sp
->otccbLink
;
606 ATDISABLE(l
, sp
->lockRemove
);
608 prev_sp
->otccbLink
= sp
->otccbLink
;
610 adsp_inputQ
[sVal
] = sp
->otccbLink
;
611 ATENABLE(l
, sp
->lockRemove
);
612 if (adsp_inputQ
[sVal
])
615 pid
= adsp_pidM
[sVal
];
616 adsp_inputC
[sVal
] = 0;
622 ATENABLE(s
, adspall_lock
);
626 ATENABLE(s
, adspall_lock
);
628 dPrintf(D_M_ADSP
, D_L_ERROR
,
629 ("adspDeassignSocket: closing, no CCB block, trouble ahead\n"));
631 } /* adspDeassignSocket */
634 * remove CCB from the use list
642 ATDISABLE(s
, adspall_lock
);
643 if (sp
== ccb_used_list
) {
644 if ((ccb_used_list
= sp
->otccbLink
) != 0)
645 sp
->otccbLink
->ccbLink
= 0;
646 } else if (sp
->ccbLink
) {
647 if ((sp
->ccbLink
->otccbLink
= sp
->otccbLink
) != 0)
648 sp
->otccbLink
->ccbLink
= sp
->ccbLink
;
653 ATENABLE(s
, adspall_lock
);
656 void SndMsgUp(gref
, mp
)
657 gref_t
*gref
; /* WRITE queue */
661 dPrintf(D_M_ADSP, D_L_TRACE,
662 ("SndMsgUp: gref=0x%x, mbuf=0x%x\n", (unsigned)gref, (unsigned)mp));
663 trace_mbufs(D_M_ADSP, " m", mp);
665 atalk_putnext(gref
, mp
);