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