]> git.saurik.com Git - apple/xnu.git/blame - bsd/netat/adsp.c
xnu-792.13.8.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 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
1c79356b 5 *
8ad349bb
A
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@
1c79356b
A
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
57struct adsp_debug adsp_dtable[1025];
58int ad_entry = 0;
59#endif
60
1c79356b
A
61
62adspAllocateCCB(gref)
63 register gref_t *gref; /* READ queue */
64{
65 gbuf_t *ccb_mp;
66 register CCBPtr sp;
67
68 if (!(ccb_mp = gbuf_alloc(sizeof(CCB), PRI_LO))) {
69 return (0);
70 }
71 bzero((caddr_t) gbuf_rptr(ccb_mp), sizeof(CCB));
72 gbuf_wset(ccb_mp,sizeof(CCB));
73 gref->info = (caddr_t) ccb_mp;
74 sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
75
76 sp->pid = gref->pid; /* save the caller process pointer */
77 sp->gref = gref; /* save a back pointer to the WRITE queue */
78 sp->sp_mp = ccb_mp; /* and its message block */
1c79356b
A
79 return 1;
80}
81
82adspRelease(gref)
83 register gref_t *gref; /* READ queue */
84{
85 register CCBPtr sp;
1c79356b 86
1c79356b
A
87 if (gref->info) {
88 sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
1c79356b
A
89 /* Tells completion routine of close */
90 /* packet to remove us. */
91
92 if (sp->state == sPassive || sp->state == sClosed ||
93 sp->state == sOpening || sp->state == sListening) {
1c79356b
A
94 if (sp->state == sListening)
95 CompleteQueue(&sp->opb, errAborted);
96 sp->removing = 1; /* Prevent allowing another dspClose. */
97 DoClose(sp, errAborted, 0); /* will remove CCB */
98 return 0;
99 } else { /* sClosing & sOpen */
100 sp->state = sClosing;
101 }
1c79356b
A
102
103 if (CheckOkToClose(sp)) { /* going to close */
104 sp->sendCtl = B_CTL_CLOSE; /* Send close advice */
105 } else {
106 CheckSend(sp); /* try one more time to send out data */
107 if (sp->state != sClosed)
108 sp->sendCtl = B_CTL_CLOSE; /* Setup to send close advice */
109 }
110 CheckSend(sp); /* and force out the close */
1c79356b
A
111 sp->removing = 1; /* Prevent allowing another dspClose. */
112 sp->state = sClosed;
1c79356b 113 DoClose(sp, errAborted, 0); /* to closed and remove CCB */
5d5c5d0d 114 }
1c79356b
A
115}
116
117
118
119
120adspWriteHandler(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)) {
91447636
A
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));
1c79356b 144 switch(ap->csCode) {
91447636
A
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, ap)))
151 gbuf_freem(mp);
152 return(STR_IGNORE);
1c79356b 153 }
91447636
A
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, 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(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);
1c79356b
A
276 }
277}
278
279
280adspReadHandler(gref, mp)
281 gref_t *gref;
282 gbuf_t *mp;
283{
284 int error;
285
286 switch(gbuf_type(mp)) {
287 case MSG_DATA:
288 if ((error = adspPacket(gref, mp))) {
289 gbuf_freem(mp);
290 }
291 break;
292
293 case MSG_IOCTL:
294 default:
295 return(STR_PUTNEXT);
296 break;
297 }
298 return(STR_IGNORE);
299}
300
301/*
302 * adsp_sendddp()
303 *
304 * Description:
305 * This procedure a formats a DDP datagram header and calls the
306 * DDP module to queue it for routing and transmission according to
307 * the DDP parameters. We always take control of the datagram;
308 * if there is an error we free it, otherwise we pass it to the next
309 * layer. We don't need to set the src address fileds because the
310 * DDP layer fills these in for us.
311 *
312 * Calling Sequence:
313 * ret_status = adsp_sendddp(q, sp, mp, length, dstnetaddr, ddptype);
314 *
315 * Formal Parameters:
316 * sp Caller stream pointer
317 * mp gbuf_t chain containing the datagram to transmit
318 * The first mblk contains the ADSP header and space
319 * for the DDP header.
320 * length size of data portion of datagram
321 * dstnetaddr address of 4-byte destination internet address
322 * ddptype DDP protocol to assign to the datagram
323 *
324 * Completion Status:
325 * 0 Procedure successful completed.
326 * EMSGSIZE Specified datagram length is too big.
327 *
328 * Side Effects:
329 * NONE
330 */
331
332adsp_sendddp(sp, mp, length, dstnetaddr, ddptype)
333 CCBPtr sp;
334 gbuf_t *mp;
335 int length;
336 AddrUnion *dstnetaddr;
337 int ddptype;
338{
339 DDPX_FRAME *ddp;
340 gbuf_t *mlist = mp;
341
342 if (mp == 0)
343 return EINVAL;
344
345 if (length > DDP_DATA_SIZE) {
346 gbuf_freel(mlist);
347 return EMSGSIZE;
348 }
349
350 while (mp) {
351
352 if (length == 0)
353 length = gbuf_msgsize(mp) - DDPL_FRAME_LEN;
354 /* Set up the DDP header */
355
356 ddp = (DDPX_FRAME *) gbuf_rptr(mp);
5d5c5d0d 357 UAS_ASSIGN_HTON(ddp->ddpx_length, (length + DDPL_FRAME_LEN));
1c79356b
A
358 UAS_ASSIGN(ddp->ddpx_cksm, 0);
359 if (sp) {
360 if (sp->useCheckSum)
5d5c5d0d 361 UAS_ASSIGN_HTON(ddp->ddpx_cksm, 1);
1c79356b
A
362 }
363
364 NET_ASSIGN(ddp->ddpx_dnet, dstnetaddr->a.net);
365 ddp->ddpx_dnode = dstnetaddr->a.node;
366 ddp->ddpx_source = sp ? sp->localSocket : ddp->ddpx_dest;
367 ddp->ddpx_dest = dstnetaddr->a.socket;
368
369 ddp->ddpx_type = ddptype;
370 length = 0;
371 mp = gbuf_next(mp);
372
373 }
374
375 DDP_OUTPUT(mlist);
376 return 0;
377}
378
379void NotifyUser(sp)
380 register CCBPtr sp;
381
382{
383/*
384 pidsig(sp->pid, SIGIO);
385*/
386}
387
388void UrgentUser(sp)
389 register CCBPtr sp;
390{
391/*
392 pidsig(sp->pid, SIGURG);
393*/
394}