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