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