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