]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/adsp.c
02d01c9632c7d41d98f59d3e5ddfe5cb67cdf84c
[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(EPROTO, 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 }
185 sp = (void *)gbuf_rptr(((gbuf_t *)gref->info));
186 switch(iocbp->ioc_cmd) {
187 case ADSPOPEN:
188 case ADSPCLLISTEN:
189 ap->socket = ((CCBPtr)sp)->localSocket;
190 flag = (adspMode(ap) == ocAccept) ? 1 : 0;
191 if (flag && ap->socket) {
192 if (adspDeassignSocket((CCBPtr)sp) >= 0)
193 ap->socket = 0;
194 }
195 if ((ap->socket == 0) &&
196 ((ap->socket =
197 (at_socket)adspAssignSocket(gref, flag)) == 0)) {
198 adspioc_ack(EADDRNOTAVAIL, mp, gref);
199 return(STR_IGNORE);
200 }
201 ap->csCode = iocbp->ioc_cmd == ADSPOPEN ? dspInit : dspCLInit;
202 if ((error = adspInit(sp, ap)) == 0) {
203 switch(ap->csCode) {
204 case dspInit:
205 /* and open the connection */
206 ap->csCode = dspOpen;
207 error = adspOpen(sp, ap);
208 break;
209 case dspCLInit:
210 /* ADSPCLLISTEN */
211 ap->csCode = dspCLListen;
212 error = adspCLListen(sp, ap);
213 break;
214 }
215 }
216 if (error)
217 adspioc_ack(error, mp, gref); /* if this failed req complete */
218 return(STR_IGNORE);
219 case ADSPCLOSE:
220 ap->csCode = dspClose;
221 if ((error = adspClose(sp, ap))) {
222 adspioc_ack(error, mp, gref);
223 break;
224 }
225 break;
226 case ADSPCLREMOVE:
227 ap->csCode = dspCLRemove;
228 error = adspClose(sp, ap);
229 adspioc_ack(error, mp, gref);
230 return(STR_IGNORE);
231 case ADSPCLDENY:
232 ap->csCode = dspCLDeny;
233 if ((error = adspCLDeny(sp, ap))) {
234 adspioc_ack(error, mp, gref);
235 }
236 return(STR_IGNORE);
237 case ADSPSTATUS:
238 ap->csCode = dspStatus;
239 if ((error = adspStatus(sp, ap))) {
240 adspioc_ack(error, mp, gref);
241 }
242 return(STR_IGNORE);
243 case ADSPREAD:
244 ap->csCode = dspRead;
245 if ((error = adspRead(sp, ap))) {
246 adspioc_ack(error, mp, gref);
247 }
248 return(STR_IGNORE);
249 case ADSPATTENTION:
250 ap->csCode = dspAttention;
251 if ((error = adspReadAttention(sp, ap))) {
252 adspioc_ack(error, mp, gref);
253 }
254 return(STR_IGNORE);
255 case ADSPOPTIONS:
256 ap->csCode = dspOptions;
257 if ((error = adspOptions(sp, ap))) {
258 adspioc_ack(error, mp, gref);
259 }
260 return(STR_IGNORE);
261 case ADSPRESET:
262 ap->csCode = dspReset;
263 if ((error = adspReset(sp, ap))) {
264 adspioc_ack(error, mp, gref);
265 }
266 return(STR_IGNORE);
267 case ADSPNEWCID:
268 ap->csCode = dspNewCID;
269 if ((error = adspNewCID(sp, ap))) {
270 adspioc_ack(error, mp, gref);
271 }
272 return(STR_IGNORE);
273 default:
274 return(STR_PUTNEXT); /* pass it on down */
275 }
276 return(STR_IGNORE);
277 case MSG_PROTO:
278 default:
279 gbuf_freem(mp);
280 }
281 }
282
283
284 adspReadHandler(gref, mp)
285 gref_t *gref;
286 gbuf_t *mp;
287 {
288 int error;
289
290 switch(gbuf_type(mp)) {
291 case MSG_DATA:
292 if ((error = adspPacket(gref, mp))) {
293 gbuf_freem(mp);
294 }
295 break;
296
297 case MSG_IOCTL:
298 default:
299 return(STR_PUTNEXT);
300 break;
301 }
302 return(STR_IGNORE);
303 }
304
305 /*
306 * adsp_sendddp()
307 *
308 * Description:
309 * This procedure a formats a DDP datagram header and calls the
310 * DDP module to queue it for routing and transmission according to
311 * the DDP parameters. We always take control of the datagram;
312 * if there is an error we free it, otherwise we pass it to the next
313 * layer. We don't need to set the src address fileds because the
314 * DDP layer fills these in for us.
315 *
316 * Calling Sequence:
317 * ret_status = adsp_sendddp(q, sp, mp, length, dstnetaddr, ddptype);
318 *
319 * Formal Parameters:
320 * sp Caller stream pointer
321 * mp gbuf_t chain containing the datagram to transmit
322 * The first mblk contains the ADSP header and space
323 * for the DDP header.
324 * length size of data portion of datagram
325 * dstnetaddr address of 4-byte destination internet address
326 * ddptype DDP protocol to assign to the datagram
327 *
328 * Completion Status:
329 * 0 Procedure successful completed.
330 * EMSGSIZE Specified datagram length is too big.
331 *
332 * Side Effects:
333 * NONE
334 */
335
336 adsp_sendddp(sp, mp, length, dstnetaddr, ddptype)
337 CCBPtr sp;
338 gbuf_t *mp;
339 int length;
340 AddrUnion *dstnetaddr;
341 int ddptype;
342 {
343 DDPX_FRAME *ddp;
344 gbuf_t *mlist = mp;
345
346 if (mp == 0)
347 return EINVAL;
348
349 if (length > DDP_DATA_SIZE) {
350 gbuf_freel(mlist);
351 return EMSGSIZE;
352 }
353
354 while (mp) {
355
356 if (length == 0)
357 length = gbuf_msgsize(mp) - DDPL_FRAME_LEN;
358 /* Set up the DDP header */
359
360 ddp = (DDPX_FRAME *) gbuf_rptr(mp);
361 UAS_ASSIGN(ddp->ddpx_length, (length + DDPL_FRAME_LEN));
362 UAS_ASSIGN(ddp->ddpx_cksm, 0);
363 if (sp) {
364 if (sp->useCheckSum)
365 UAS_ASSIGN(ddp->ddpx_cksm, 1);
366 }
367
368 NET_ASSIGN(ddp->ddpx_dnet, dstnetaddr->a.net);
369 ddp->ddpx_dnode = dstnetaddr->a.node;
370 ddp->ddpx_source = sp ? sp->localSocket : ddp->ddpx_dest;
371 ddp->ddpx_dest = dstnetaddr->a.socket;
372
373 ddp->ddpx_type = ddptype;
374 length = 0;
375 mp = gbuf_next(mp);
376
377 }
378
379 DDP_OUTPUT(mlist);
380 return 0;
381 }
382
383 void NotifyUser(sp)
384 register CCBPtr sp;
385
386 {
387 /*
388 pidsig(sp->pid, SIGIO);
389 */
390 }
391
392 void UrgentUser(sp)
393 register CCBPtr sp;
394 {
395 /*
396 pidsig(sp->pid, SIGURG);
397 */
398 }