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