]> git.saurik.com Git - apple/xnu.git/blame - bsd/netat/adsp.c
xnu-792.24.17.tar.gz
[apple/xnu.git] / bsd / netat / adsp.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
6601e61a 4 * @APPLE_LICENSE_HEADER_START@
1c79356b 5 *
6601e61a
A
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.
8f6c56a5 11 *
6601e61a
A
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
8f6c56a5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
6601e61a
A
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.
8f6c56a5 19 *
6601e61a 20 * @APPLE_LICENSE_HEADER_END@
1c79356b
A
21 */
22/*
23 * Change log:
24 * 06/29/95 - Modified to handle flow control for writing (Tuyen Nguyen)
25 * Modified for MP, 1996 by Tuyen Nguyen
26 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
27 */
28#define RESOLVE_DBG
29#include <sys/errno.h>
30#include <sys/types.h>
31#include <sys/param.h>
32#include <machine/spl.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/proc.h>
36#include <sys/filedesc.h>
37#include <sys/fcntl.h>
38#include <sys/mbuf.h>
39#include <sys/socket.h>
40
41#include <netat/sysglue.h>
42#include <netat/appletalk.h>
43#include <netat/at_pcb.h>
44#include <netat/ddp.h>
45#include <netat/adsp.h>
46#include <netat/adsp_internal.h>
47
48#ifdef notdefn
49struct adsp_debug adsp_dtable[1025];
50int ad_entry = 0;
51#endif
52
6601e61a 53extern atlock_t adspgen_lock;
1c79356b
A
54
55adspAllocateCCB(gref)
56 register gref_t *gref; /* READ queue */
57{
58 gbuf_t *ccb_mp;
59 register CCBPtr sp;
60
61 if (!(ccb_mp = gbuf_alloc(sizeof(CCB), PRI_LO))) {
62 return (0);
63 }
64 bzero((caddr_t) gbuf_rptr(ccb_mp), sizeof(CCB));
65 gbuf_wset(ccb_mp,sizeof(CCB));
66 gref->info = (caddr_t) ccb_mp;
67 sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
68
69 sp->pid = gref->pid; /* save the caller process pointer */
70 sp->gref = gref; /* save a back pointer to the WRITE queue */
71 sp->sp_mp = ccb_mp; /* and its message block */
6601e61a
A
72 ATLOCKINIT(sp->lock);
73 ATLOCKINIT(sp->lockClose);
74 ATLOCKINIT(sp->lockRemove);
1c79356b
A
75 return 1;
76}
77
78adspRelease(gref)
79 register gref_t *gref; /* READ queue */
80{
81 register CCBPtr sp;
6601e61a 82 int s, l;
1c79356b 83
6601e61a 84 ATDISABLE(l, adspgen_lock);
1c79356b
A
85 if (gref->info) {
86 sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
6601e61a
A
87 ATDISABLE(s, sp->lock);
88 ATENABLE(s, adspgen_lock);
1c79356b
A
89 /* Tells completion routine of close */
90 /* packet to remove us. */
91
92 if (sp->state == sPassive || sp->state == sClosed ||
93 sp->state == sOpening || sp->state == sListening) {
6601e61a 94 ATENABLE(l, sp->lock);
1c79356b
A
95 if (sp->state == sListening)
96 CompleteQueue(&sp->opb, errAborted);
97 sp->removing = 1; /* Prevent allowing another dspClose. */
98 DoClose(sp, errAborted, 0); /* will remove CCB */
99 return 0;
100 } else { /* sClosing & sOpen */
101 sp->state = sClosing;
102 }
6601e61a 103 ATENABLE(l, sp->lock);
1c79356b
A
104
105 if (CheckOkToClose(sp)) { /* going to close */
106 sp->sendCtl = B_CTL_CLOSE; /* Send close advice */
107 } else {
108 CheckSend(sp); /* try one more time to send out data */
109 if (sp->state != sClosed)
110 sp->sendCtl = B_CTL_CLOSE; /* Setup to send close advice */
111 }
112 CheckSend(sp); /* and force out the close */
6601e61a 113 ATDISABLE(s, sp->lock);
1c79356b
A
114 sp->removing = 1; /* Prevent allowing another dspClose. */
115 sp->state = sClosed;
6601e61a 116 ATENABLE(s, sp->lock);
1c79356b 117 DoClose(sp, errAborted, 0); /* to closed and remove CCB */
6601e61a
A
118 } else
119 ATENABLE(l, adspgen_lock);
1c79356b
A
120}
121
122
123
124
125adspWriteHandler(gref, mp)
126 gref_t *gref; /* WRITE queue */
127 gbuf_t *mp;
128{
129
130 register ioc_t *iocbp;
131 register struct adspcmd *ap;
132 int error, flag;
133 void *sp;
134
135 switch(gbuf_type(mp)) {
91447636
A
136 case MSG_DATA:
137 if (gref->info == 0) {
138 gbuf_freem(mp);
139 return(STR_IGNORE);
140 }
141 /*
142 * Fill in the global stuff
143 */
144 ap = (struct adspcmd *)gbuf_rptr(mp);
145 ap->gref = gref;
146 ap->ioc = 0;
147 ap->mp = mp;
148 sp = (void *)gbuf_rptr(((gbuf_t *)gref->info));
1c79356b 149 switch(ap->csCode) {
91447636
A
150 case dspWrite:
151 if ((error = adspWrite(sp, ap)))
152 gbuf_freem(mp);
153 return(STR_IGNORE);
154 case dspAttention:
155 if ((error = adspAttention(sp, ap)))
156 gbuf_freem(mp);
157 return(STR_IGNORE);
1c79356b 158 }
91447636
A
159 case MSG_IOCTL:
160 if (gref->info == 0) {
161 adspioc_ack(EPROTOTYPE, mp, gref);
162 return(STR_IGNORE);
163 }
164 iocbp = (ioc_t *) gbuf_rptr(mp);
165 if (ADSP_IOCTL(iocbp->ioc_cmd)) {
166 iocbp->ioc_count = sizeof(*ap) - 1;
167 if (gbuf_cont(mp) == 0) {
168 adspioc_ack(EINVAL, mp, gref);
169 return(STR_IGNORE);
170 }
171 ap = (struct adspcmd *) gbuf_rptr(gbuf_cont(mp));
172 ap->gref = gref;
173 ap->ioc = (caddr_t) mp;
174 ap->mp = gbuf_cont(mp); /* request head */
175 ap->ioResult = 0;
176
177 if ((gref->info == 0) && ((iocbp->ioc_cmd != ADSPOPEN) &&
178 (iocbp->ioc_cmd != ADSPCLLISTEN))) {
179 ap->ioResult = errState;
180
181 adspioc_ack(EINVAL, mp, gref);
182 return(STR_IGNORE);
183 }
184 } else
185 return(STR_PUTNEXT); /* pass it on down */
186 sp = (void *)gbuf_rptr(((gbuf_t *)gref->info));
187 switch(iocbp->ioc_cmd) {
188 case ADSPOPEN:
189 case ADSPCLLISTEN:
190 ap->socket = ((CCBPtr)sp)->localSocket;
191 flag = (adspMode(ap) == ocAccept) ? 1 : 0;
192 if (flag && ap->socket) {
193 if (adspDeassignSocket((CCBPtr)sp) >= 0)
194 ap->socket = 0;
195 }
196 if ((ap->socket == 0) &&
197 ((ap->socket =
198 (at_socket)adspAssignSocket(gref, flag)) == 0)) {
199 adspioc_ack(EADDRNOTAVAIL, mp, gref);
200 return(STR_IGNORE);
201 }
202 ap->csCode = iocbp->ioc_cmd == ADSPOPEN ? dspInit : dspCLInit;
203 if ((error = adspInit(sp, ap)) == 0) {
204 switch(ap->csCode) {
205 case dspInit:
206 /* and open the connection */
207 ap->csCode = dspOpen;
208 error = adspOpen(sp, ap);
209 break;
210 case dspCLInit:
211 /* ADSPCLLISTEN */
212 ap->csCode = dspCLListen;
213 error = adspCLListen(sp, ap);
214 break;
215 }
216 }
217 if (error)
218 adspioc_ack(error, mp, gref); /* if this failed req complete */
219 return(STR_IGNORE);
220 case ADSPCLOSE:
221 ap->csCode = dspClose;
222 if ((error = adspClose(sp, ap))) {
223 adspioc_ack(error, mp, gref);
224 break;
225 }
226 break;
227 case ADSPCLREMOVE:
228 ap->csCode = dspCLRemove;
229 error = adspClose(sp, ap);
230 adspioc_ack(error, mp, gref);
231 return(STR_IGNORE);
232 case ADSPCLDENY:
233 ap->csCode = dspCLDeny;
234 if ((error = adspCLDeny(sp, ap))) {
235 adspioc_ack(error, mp, gref);
236 }
237 return(STR_IGNORE);
238 case ADSPSTATUS:
239 ap->csCode = dspStatus;
240 if ((error = adspStatus(sp, ap))) {
241 adspioc_ack(error, mp, gref);
242 }
243 return(STR_IGNORE);
244 case ADSPREAD:
245 ap->csCode = dspRead;
246 if ((error = adspRead(sp, ap))) {
247 adspioc_ack(error, mp, gref);
248 }
249 return(STR_IGNORE);
250 case ADSPATTENTION:
251 ap->csCode = dspAttention;
252 if ((error = adspReadAttention(sp, ap))) {
253 adspioc_ack(error, mp, gref);
254 }
255 return(STR_IGNORE);
256 case ADSPOPTIONS:
257 ap->csCode = dspOptions;
258 if ((error = adspOptions(sp, ap))) {
259 adspioc_ack(error, mp, gref);
260 }
261 return(STR_IGNORE);
262 case ADSPRESET:
263 ap->csCode = dspReset;
264 if ((error = adspReset(sp, ap))) {
265 adspioc_ack(error, mp, gref);
266 }
267 return(STR_IGNORE);
268 case ADSPNEWCID:
269 ap->csCode = dspNewCID;
270 if ((error = adspNewCID(sp, ap))) {
271 adspioc_ack(error, mp, gref);
272 }
273 return(STR_IGNORE);
274 default:
275 return(STR_PUTNEXT); /* pass it on down */
276 }
277 return(STR_IGNORE);
278 case MSG_PROTO:
279 default:
280 gbuf_freem(mp);
1c79356b
A
281 }
282}
283
284
285adspReadHandler(gref, mp)
286 gref_t *gref;
287 gbuf_t *mp;
288{
289 int error;
290
291 switch(gbuf_type(mp)) {
292 case MSG_DATA:
293 if ((error = adspPacket(gref, mp))) {
294 gbuf_freem(mp);
295 }
296 break;
297
298 case MSG_IOCTL:
299 default:
300 return(STR_PUTNEXT);
301 break;
302 }
303 return(STR_IGNORE);
304}
305
306/*
307 * adsp_sendddp()
308 *
309 * Description:
310 * This procedure a formats a DDP datagram header and calls the
311 * DDP module to queue it for routing and transmission according to
312 * the DDP parameters. We always take control of the datagram;
313 * if there is an error we free it, otherwise we pass it to the next
314 * layer. We don't need to set the src address fileds because the
315 * DDP layer fills these in for us.
316 *
317 * Calling Sequence:
318 * ret_status = adsp_sendddp(q, sp, mp, length, dstnetaddr, ddptype);
319 *
320 * Formal Parameters:
321 * sp Caller stream pointer
322 * mp gbuf_t chain containing the datagram to transmit
323 * The first mblk contains the ADSP header and space
324 * for the DDP header.
325 * length size of data portion of datagram
326 * dstnetaddr address of 4-byte destination internet address
327 * ddptype DDP protocol to assign to the datagram
328 *
329 * Completion Status:
330 * 0 Procedure successful completed.
331 * EMSGSIZE Specified datagram length is too big.
332 *
333 * Side Effects:
334 * NONE
335 */
336
337adsp_sendddp(sp, mp, length, dstnetaddr, ddptype)
338 CCBPtr sp;
339 gbuf_t *mp;
340 int length;
341 AddrUnion *dstnetaddr;
342 int ddptype;
343{
344 DDPX_FRAME *ddp;
345 gbuf_t *mlist = mp;
346
347 if (mp == 0)
348 return EINVAL;
349
350 if (length > DDP_DATA_SIZE) {
351 gbuf_freel(mlist);
352 return EMSGSIZE;
353 }
354
355 while (mp) {
356
357 if (length == 0)
358 length = gbuf_msgsize(mp) - DDPL_FRAME_LEN;
359 /* Set up the DDP header */
360
361 ddp = (DDPX_FRAME *) gbuf_rptr(mp);
6601e61a 362 UAS_ASSIGN(ddp->ddpx_length, (length + DDPL_FRAME_LEN));
1c79356b
A
363 UAS_ASSIGN(ddp->ddpx_cksm, 0);
364 if (sp) {
365 if (sp->useCheckSum)
6601e61a 366 UAS_ASSIGN(ddp->ddpx_cksm, 1);
1c79356b
A
367 }
368
369 NET_ASSIGN(ddp->ddpx_dnet, dstnetaddr->a.net);
370 ddp->ddpx_dnode = dstnetaddr->a.node;
371 ddp->ddpx_source = sp ? sp->localSocket : ddp->ddpx_dest;
372 ddp->ddpx_dest = dstnetaddr->a.socket;
373
374 ddp->ddpx_type = ddptype;
375 length = 0;
376 mp = gbuf_next(mp);
377
378 }
379
380 DDP_OUTPUT(mlist);
381 return 0;
382}
383
384void NotifyUser(sp)
385 register CCBPtr sp;
386
387{
388/*
389 pidsig(sp->pid, SIGIO);
390*/
391}
392
393void UrgentUser(sp)
394 register CCBPtr sp;
395{
396/*
397 pidsig(sp->pid, SIGURG);
398*/
399}