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