8dd2ec37434efa34f6660506bada4eda145a01a1
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1995-1998 Apple Computer, Inc.
24 * All Rights Reserved.
28 * 09/07/95 - Modified for performance (Tuyen Nguyen)
29 * Modified for MP, 1996 by Tuyen Nguyen
30 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
32 #include <sys/errno.h>
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <machine/spl.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
39 #include <sys/filedesc.h>
40 #include <sys/fcntl.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
45 #include <sys/ioctl.h>
46 #include <sys/malloc.h>
50 #include <netat/sysglue.h>
51 #include <netat/appletalk.h>
52 #include <netat/ddp.h>
53 #include <netat/at_snmp.h>
54 #include <netat/at_pcb.h>
55 #include <netat/debug.h>
56 #include <netat/at_var.h>
57 #include <netat/adsp.h>
58 #include <netat/adsp_internal.h>
62 static void adsp_iocack();
63 static void adsp_iocnak();
64 void adsp_dequeue_ccb();
65 unsigned char adspAssignSocket();
66 int adspallocate(), adsprelease();
69 atlock_t adspall_lock
;
70 atlock_t adspgen_lock
;
76 char adsp_inputC
[256];
77 CCB
*adsp_inputQ
[256];
79 extern at_ifaddr_t
*ifID_home
;
92 switch (gbuf_type(mp
)) {
94 p
= (at_ddp_t
*)gbuf_rptr(mp
);
95 ATDISABLE(s
, adspall_lock
);
96 sp
= adsp_inputQ
[p
->dst_socket
];
97 if ((sp
== 0) || (sp
->gref
==0) || (sp
->state
==sClosed
))
99 ATENABLE(s
, adspall_lock
);
103 else if (sp
->otccbLink
!= 0) {
105 if ((sp
->remoteAddress
.a
.node
== p
->src_node
)
106 && (sp
->remoteAddress
.a
.socket
== p
->src_socket
)
107 && (sp
->remoteAddress
.a
.net
== NET_VALUE(p
->src_net
)))
109 } while ((sp
= sp
->otccbLink
) != 0);
112 ATENABLE(s
, adspall_lock
);
119 if (sp
->deferred_mb
) {
120 for (mb
=sp
->deferred_mb
; gbuf_next(mb
); mb
=gbuf_next(mb
)) ;
123 sp
->deferred_mb
= mp
;
124 ATENABLE(s
, adspall_lock
);
127 ATDISABLE(l
, sp
->lockRemove
);
129 ATENABLE(l
, adspall_lock
);
131 adsp_rput(sp
->gref
, mp
);
132 if ((mp
= sp
->deferred_mb
) != 0) {
133 sp
->deferred_mb
= gbuf_next(mp
);
138 ATENABLE(s
, sp
->lockRemove
);
143 gref
= (gref_t
*)((ioc_t
*)gbuf_rptr(mp
))->ioc_private
;
147 #ifdef APPLETALK_DEBUG
148 kprintf("unexpected MSG_IOCTL in adsp_input()");
161 int adsp_readable(gref
)
169 * we don't have the structure we need to determine
170 * if there's data available... we return readable in
171 * this case to keep from hanging up in the select
172 * a subsequent read will run into the same missing data
173 * structure and return an error... the ATselect code does
174 * this if it can't retrieve the 'gref' structure from the
175 * file table for the fd specified
179 sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
185 int adsp_writeable(gref
)
193 * we don't have the structure we need to determine
194 * if there's room available... we return writeable in
195 * this case to keep from hanging up in the select
196 * a subsequent write will run into the same missing data
197 * structure and return an error... the ATselect code does
198 * this if it can't retrieve the 'gref' structure from the
199 * file table for the fd specified
203 sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
204 ATDISABLE(s
, sp
->lock
);
205 rc
= CalcSendQFree(sp
);
206 ATENABLE(s
, sp
->lock
);
211 static void adsp_init()
216 bzero(adsp_pidM
, sizeof(adsp_pidM
));
217 bzero(adsp_inputC
, sizeof(adsp_inputC
));
218 bzero(adsp_inputQ
, sizeof(adsp_inputQ
));
223 * ADSP open and close routines. These routines
224 * initalize and release the ADSP structures. They do not
225 * have anything to do with "connections"
237 if (!adspAllocateCCB(gref
))
238 return(ENOBUFS
); /* can't get buffers */
240 sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
241 gref
->readable
= adsp_readable
;
242 gref
->writeable
= adsp_writeable
;
243 ATDISABLE(s
, adspall_lock
);
244 if ((sp
->otccbLink
= ccb_used_list
) != 0)
245 sp
->otccbLink
->ccbLink
= sp
;
247 ATENABLE(s
, adspall_lock
);
255 unsigned char localSocket
;
257 /* make sure we've not yet removed the CCB (e.g., due to TrashSession) */
258 ATDISABLE(l
, adspgen_lock
);
260 CCBPtr sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
261 ATDISABLE(s
, sp
->lock
);
262 ATENABLE(s
, adspgen_lock
);
263 localSocket
= sp
->localSocket
;
264 ATENABLE(l
, sp
->lock
);
269 adsp_dequeue_ccb(sp
);
270 gbuf_freeb((gbuf_t
*)gref
->info
);
273 ATENABLE(l
, adspgen_lock
);
283 * ADSP streams read put and service routines.
286 void adsp_rput(gref
, mp
)
287 gref_t
*gref
; /* READ queue */
290 switch (gbuf_type(mp
)) {
294 switch (adspReadHandler(gref
, mp
)) {
296 atalk_putnext(gref
, mp
);
303 #ifdef APPLETALK_DEBUG
304 kprintf("adsp_rput received MSG_ERROR");
308 CheckReadQueue(gbuf_rptr(((gbuf_t
*)gref
->info
)));
309 CheckSend(gbuf_rptr(((gbuf_t
*)gref
->info
)));
311 switch (gbuf_type(mp
)) {
315 if (adspReadHandler(gref
, mp
) == STR_PUTNEXT
)
316 atalk_putnext(gref
, mp
);
319 atalk_putnext(gref
, mp
);
330 * ADSP streams write put and service routines.
334 int adsp_wput(gref
, mp
)
335 gref_t
*gref
; /* WRITE queue */
342 CCBPtr sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
344 if (gbuf_type(mp
) == MSG_IOCTL
) {
345 iocbp
= (ioc_t
*)gbuf_rptr(mp
);
346 switch (iocbp
->ioc_cmd
) {
351 if (gbuf_cont(mp
) == NULL
) {
352 iocbp
->ioc_rval
= -1;
353 adsp_iocnak(gref
, mp
, EINVAL
);
355 v
= *(unsigned char *)gbuf_rptr(gbuf_cont(mp
));
356 ATDISABLE(s
, adspall_lock
);
358 && ((v
> DDP_SOCKET_LAST
) || (v
< 2)
359 || ddp_socket_inuse(v
, DDP_ADSP
))) {
360 ATENABLE(s
, adspall_lock
);
361 iocbp
->ioc_rval
= -1;
362 adsp_iocnak(gref
, mp
, EINVAL
);
366 ATENABLE(s
, adspall_lock
);
367 if ((v
= adspAssignSocket(gref
, 0)) == 0) {
368 iocbp
->ioc_rval
= -1;
369 adsp_iocnak(gref
, mp
, EINVAL
);
375 adsp_pidM
[v
] = sp
->pid
;
376 ATENABLE(s
, adspall_lock
);
377 adsp_dequeue_ccb(sp
);
379 *(unsigned char *)gbuf_rptr(gbuf_cont(mp
)) = v
;
382 adsp_iocack(gref
, mp
);
392 if (((xm
= gbuf_cont(mp
)) == NULL
)
393 && ((xm
= gbuf_alloc(sizeof(at_inet_t
), PRI_MED
)) == NULL
)) {
394 iocbp
->ioc_rval
= -1;
395 adsp_iocnak(gref
, mp
, ENOBUFS
);
399 gbuf_wset(xm
,sizeof(at_inet_t
));
400 addr
= (at_inet_t
*)gbuf_rptr(xm
);
401 if (iocbp
->ioc_cmd
== ADSPGETSOCK
) {
402 /* Obtain Network and Node Id's from DDP */
403 /* *** was ddp_get_cfg() *** */
404 addr
->net
= ifID_home
->ifThisNode
.s_net
;
405 addr
->node
= ifID_home
->ifThisNode
.s_node
;
406 addr
->socket
= (sp
)? sp
->localSocket
: 0;
409 *addr
= sp
->remoteAddress
.a
;
416 adsp_iocack(gref
, mp
);
419 case DDP_IOC_GET_CFG
:
420 /* respond to an DDP_IOC_GET_CFG sent on an adsp fd */
421 if (((xm
= gbuf_cont(mp
)) == NULL
) &&
422 (xm
= gbuf_alloc(sizeof(at_inet_t
), PRI_MED
)) == NULL
) {
423 iocbp
->ioc_rval
= -1;
424 adsp_iocnak(gref
, mp
, ENOBUFS
);
428 gbuf_wset(xm
, sizeof(ddp_addr_t
));
429 /* Obtain Network and Node Id's from DDP */
431 /* *** was ddp_get_cfg() *** */
433 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(mp
));
434 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
435 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
436 cfgp
->inet
.socket
= (sp
)? sp
->localSocket
: 0;
437 cfgp
->ddptype
= DDP_ADSP
;
440 adsp_iocack(gref
, mp
);
448 ATDISABLE(s
, sp
->lockClose
);
449 rc
= adspWriteHandler(gref
, mp
);
450 ATENABLE(s
, sp
->lockClose
);
454 if (gbuf_type(mp
) == MSG_IOCTL
) {
455 iocbp
= (ioc_t
*)gbuf_rptr(mp
);
456 iocbp
->ioc_private
= (void *)gref
;
472 void adspioc_ack(errno
, m
, gref
)
481 iocbp
= (ioc_t
*) gbuf_rptr(m
);
483 iocbp
->ioc_error
= errno
; /* set the errno */
484 iocbp
->ioc_count
= gbuf_msgsize(gbuf_cont(m
));
485 if (gbuf_type(m
) == MSG_IOCTL
) /* if an ioctl, this is an ack */
486 gbuf_set_type(m
, MSG_IOCACK
); /* and ALWAYS update the user */
487 /* ioctl structure */
488 trace_mbufs(D_M_ADSP
,"A ", m
);
492 static void adsp_iocack(gref
, m
)
496 if (gbuf_type(m
) == MSG_IOCTL
)
497 gbuf_set_type(m
, MSG_IOCACK
);
500 ((ioc_t
*)gbuf_rptr(m
))->ioc_count
= gbuf_msgsize(gbuf_cont(m
));
502 ((ioc_t
*)gbuf_rptr(m
))->ioc_count
= 0;
508 static void adsp_iocnak(gref
, m
, err
)
513 if (gbuf_type(m
) == MSG_IOCTL
)
514 gbuf_set_type(m
, MSG_IOCNAK
);
515 ((ioc_t
*)gbuf_rptr(m
))->ioc_count
= 0;
519 ((ioc_t
*)gbuf_rptr(m
))->ioc_error
= err
;
522 gbuf_freem(gbuf_cont(m
));
529 adspAssignSocket(gref
, flag
)
533 unsigned char sVal
, sMax
, sMin
, sSav
, inputC
;
537 sMax
= flag
? DDP_SOCKET_LAST
-46 : DDP_SOCKET_LAST
-6;
538 sMin
= DDP_SOCKET_1st_DYNAMIC
-64;
540 ATDISABLE(s
, adspall_lock
);
541 for (inputC
=255, sVal
=sMax
; sVal
>= sMin
; sVal
--) {
542 if (!ddp_socket_inuse(sVal
, DDP_ADSP
))
545 if (adsp_inputC
[sVal
] &&
546 /* meaning that raw DDP doesn't have it */
547 (adsp_inputC
[sVal
] < inputC
)
548 && (adsp_inputQ
[sVal
]->state
== sOpen
)) {
549 inputC
= adsp_inputC
[sVal
];
555 if (!flag
|| (inputC
== 255)) {
556 ATENABLE(s
, adspall_lock
);
561 sp
= (CCBPtr
)gbuf_rptr(((gbuf_t
*)gref
->info
));
562 ATENABLE(s
, adspall_lock
);
563 adsp_dequeue_ccb(sp
);
564 ATDISABLE(s
, adspall_lock
);
566 sp
->otccbLink
= adsp_inputQ
[sVal
];
567 adsp_inputQ
[sVal
] = sp
;
569 adsp_pidM
[sVal
] = sp
->pid
;
570 ATENABLE(s
, adspall_lock
);
575 adspDeassignSocket(sp
)
584 dPrintf(D_M_ADSP
, D_L_TRACE
, ("adspDeassignSocket: pid=%d,s=%d\n",
585 sp
->pid
, sp
->localSocket
));
586 ATDISABLE(s
, adspall_lock
);
587 sVal
= sp
->localSocket
;
588 if ((curr_sp
= adsp_inputQ
[sVal
]) != 0) {
590 while (curr_sp
!= sp
) {
592 curr_sp
= curr_sp
->otccbLink
;
595 ATDISABLE(l
, sp
->lockRemove
);
597 prev_sp
->otccbLink
= sp
->otccbLink
;
599 adsp_inputQ
[sVal
] = sp
->otccbLink
;
600 ATENABLE(l
, sp
->lockRemove
);
601 if (adsp_inputQ
[sVal
])
604 pid
= adsp_pidM
[sVal
];
605 adsp_inputC
[sVal
] = 0;
611 ATENABLE(s
, adspall_lock
);
615 ATENABLE(s
, adspall_lock
);
617 dPrintf(D_M_ADSP
, D_L_ERROR
,
618 ("adspDeassignSocket: closing, no CCB block, trouble ahead\n"));
620 } /* adspDeassignSocket */
623 * remove CCB from the use list
631 ATDISABLE(s
, adspall_lock
);
632 if (sp
== ccb_used_list
) {
633 if ((ccb_used_list
= sp
->otccbLink
) != 0)
634 sp
->otccbLink
->ccbLink
= 0;
635 } else if (sp
->ccbLink
) {
636 if ((sp
->ccbLink
->otccbLink
= sp
->otccbLink
) != 0)
637 sp
->otccbLink
->ccbLink
= sp
->ccbLink
;
642 ATENABLE(s
, adspall_lock
);
645 void SndMsgUp(gref
, mp
)
646 gref_t
*gref
; /* WRITE queue */
650 dPrintf(D_M_ADSP, D_L_TRACE,
651 ("SndMsgUp: gref=0x%x, mbuf=0x%x\n", (unsigned)gref, (unsigned)mp));
652 trace_mbufs(D_M_ADSP, " m", mp);
654 atalk_putnext(gref
, mp
);