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