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