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