|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Copyright (c) 1995 Apple Computer, Inc. ! 27: * ! 28: * The information contained herein is subject to change without ! 29: * notice and should not be construed as a commitment by Apple ! 30: * Computer, Inc. Apple Computer, Inc. assumes no responsibility ! 31: * for any errors that may appear. ! 32: * ! 33: * Confidential and Proprietary to Apple Computer, Inc. ! 34: * ! 35: */ ! 36: #ifdef _AIX ! 37: #include <sys/sleep.h> ! 38: #include <sys/poll.h> ! 39: #endif ! 40: #include <sys/ioccom.h> ! 41: #include <h/sysglue.h> ! 42: #include <at/appletalk.h> ! 43: #include <at/elap.h> ! 44: #include <at/ddp.h> ! 45: #include <at/at_lap.h> ! 46: #include <at_elap.h> ! 47: #include <h/at_ddp.h> ! 48: #undef e_sleep_thread ! 49: ! 50: /*definition of dbgBits moved here to avoid multiple redefinition */ ! 51: dbgBits_t dbgBits; ! 52: ! 53: int _ATsocket(proto, err, proc) ! 54: int proto; ! 55: int *err; ! 56: void *proc; ! 57: { ! 58: int fd; ! 59: gref_t *gref; ! 60: ! 61: /* make sure the specified protocol id is valid */ ! 62: switch (proto) { ! 63: case ATPROTO_DDP: ! 64: case ATPROTO_LAP: ! 65: case ATPROTO_ATP: ! 66: case ATPROTO_ASP: ! 67: case ATPROTO_AURP: ! 68: case ATPROTO_ADSP: ! 69: break; ! 70: default: ! 71: *err = EPROTOTYPE; ! 72: #ifdef APPLETALK_DEBUG ! 73: kprintf("_ATsocket: error EPROTOTYPE =%d\n", *err); ! 74: #endif ! 75: return -1; ! 76: } ! 77: ! 78: /* allocate a protocol channel */ ! 79: if ((*err = gref_open(&gref)) != 0) { ! 80: #ifdef APPLETALK_DEBUG ! 81: kprintf("_ATsocket: error gref_open =%d\n", *err); ! 82: #endif ! 83: return -1; ! 84: } ! 85: gref->proto = proto; ! 86: #ifdef NEXT ! 87: gref->pid = ((struct proc *)proc)->p_pid; ! 88: #endif ! 89: ! 90: /* open the specified protocol */ ! 91: switch (gref->proto) { ! 92: case ATPROTO_DDP: ! 93: *err = ddp_open(gref); break; ! 94: case ATPROTO_LAP: ! 95: *err = lap_open(gref); break; ! 96: case ATPROTO_ATP: ! 97: *err = atp_open(gref, 1); break; ! 98: case ATPROTO_ASP: ! 99: *err = asp_open(gref); break; ! 100: #ifdef AURP_SUPPORT ! 101: case ATPROTO_AURP: ! 102: *err = aurp_open(gref); break; ! 103: #endif ! 104: case ATPROTO_ADSP: ! 105: *err = adsp_open(gref); break; ! 106: } ! 107: ! 108: /* create the descriptor for the channel */ ! 109: if (*err) ! 110: gref->proto = ATPROTO_NONE; ! 111: if (*err || (*err = atalk_openref(gref, &fd, proc))) { ! 112: #ifdef APPLETALK_DEBUG ! 113: kprintf("_ATsocket: error atalk_openref =%d\n", *err); ! 114: #endif ! 115: gref_close(gref); ! 116: return -1; ! 117: } ! 118: /* ! 119: kprintf("_ATsocket: proto=%d return=%d fd=%d\n", proto, *err, fd); ! 120: */ ! 121: return fd; ! 122: } ! 123: ! 124: int _ATgetmsg(fd, ctlptr, datptr, flags, err, proc) ! 125: int fd; ! 126: strbuf_t *ctlptr; ! 127: strbuf_t *datptr; ! 128: int *flags; ! 129: int *err; ! 130: void *proc; ! 131: { ! 132: int rc = -1; ! 133: gref_t *gref; ! 134: ! 135: if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) { ! 136: switch (gref->proto) { ! 137: case ATPROTO_ASP: ! 138: rc = ASPgetmsg(gref, ctlptr, datptr, flags, err); break; ! 139: case ATPROTO_AURP: ! 140: #ifdef AURP_SUPPORT ! 141: rc = AURPgetmsg(err); break; ! 142: #endif ! 143: default: ! 144: *err = EPROTONOSUPPORT; break; ! 145: } ! 146: } ! 147: ! 148: ! 149: /* kprintf("_ATgetmsg: return=%d\n", *err);*/ ! 150: return rc; ! 151: } ! 152: ! 153: int _ATputmsg(fd, ctlptr, datptr, flags, err, proc) ! 154: int fd; ! 155: strbuf_t *ctlptr; ! 156: strbuf_t *datptr; ! 157: int flags; ! 158: int *err; ! 159: void *proc; ! 160: { ! 161: int rc = -1; ! 162: gref_t *gref; ! 163: ! 164: if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) { ! 165: switch (gref->proto) { ! 166: case ATPROTO_ASP: ! 167: rc = ASPputmsg(gref, ctlptr, datptr, flags, err); break; ! 168: default: ! 169: *err = EPROTONOSUPPORT; break; ! 170: } ! 171: } ! 172: ! 173: /* kprintf("_ATputmsg: return=%d\n", *err); */ ! 174: return rc; ! 175: } ! 176: ! 177: int _ATclose(fp, proc) ! 178: void *fp; ! 179: void *proc; ! 180: { ! 181: int err; ! 182: gref_t *gref; ! 183: ! 184: if ((err = atalk_closeref(fp, &gref)) != 0) ! 185: return err; ! 186: ! 187: gref_close(gref); ! 188: return 0; ! 189: } ! 190: ! 191: int _ATrw(fp, rw, uio, ext) ! 192: void *fp; ! 193: enum uio_rw rw; ! 194: struct uio *uio; ! 195: int ext; ! 196: { ! 197: void gref_wput(); ! 198: int s, err, len, rlen, clen, res; ! 199: gref_t *gref; ! 200: gbuf_t *m, *mhead, *mprev; ! 201: ! 202: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) ! 203: return err; ! 204: ! 205: if ((len = uio->uio_resid) == 0) ! 206: return 0; ! 207: ! 208: ATDISABLE(s, gref->lock); ! 209: if (gref->errno) { ! 210: ATENABLE(s, gref->lock); ! 211: return (int)gref->errno; ! 212: } ! 213: ! 214: if (rw == UIO_READ) { ! 215: while ((gref->errno == 0) && ((mhead = gref->rdhead) == 0)) { ! 216: gref->sevents |= POLLMSG; ! 217: err = tsleep(&gref->event, PSOCK | PCATCH, "AT read", 0); ! 218: gref->sevents &= ~POLLMSG; ! 219: if (err != 0) { ! 220: ATENABLE(s, gref->lock); ! 221: return err; ! 222: } ! 223: } ! 224: ! 225: if (gref->errno) { ! 226: ATENABLE(s, gref->lock); ! 227: return EPIPE; ! 228: } ! 229: if ((gref->rdhead = gbuf_next(mhead)) == 0) ! 230: gref->rdtail = 0; ! 231: ! 232: ATENABLE(s, gref->lock); ! 233: ! 234: gbuf_next(mhead) = 0; ! 235: ! 236: for (mprev=0, m=mhead, rlen=0; m && len; rlen+=clen, len-=clen) { ! 237: if ((clen = gbuf_len(m)) > 0) { ! 238: if (clen > len) ! 239: clen = len; ! 240: #ifdef _AIX ! 241: if (uiomove((caddr_t)gbuf_rptr(m), clen, UIO_READ, uio) == -1) ! 242: break; ! 243: #else ! 244: uio->uio_rw = UIO_READ; ! 245: res= uiomove((caddr_t)gbuf_rptr(m), clen, uio); ! 246: /* kprintf("_ATrw: UIO_READ: res=%d\n", res); */ ! 247: if (res == -1) ! 248: break; ! 249: #endif ! 250: if (gbuf_len(m) > len) { ! 251: gbuf_rinc(m,clen); ! 252: break; ! 253: } ! 254: } ! 255: mprev = m; ! 256: m = gbuf_cont(m); ! 257: } ! 258: if (m) { ! 259: if (mprev) ! 260: gbuf_cont(mprev) = 0; ! 261: else ! 262: mhead = 0; ! 263: ATDISABLE(s, gref->lock); ! 264: if (gref->rdhead == 0) ! 265: gref->rdtail = m; ! 266: gbuf_next(m) = gref->rdhead; ! 267: gref->rdhead = m; ! 268: ATENABLE(s, gref->lock); ! 269: } ! 270: if (mhead) ! 271: gbuf_freem(mhead); ! 272: ! 273: } else { ! 274: if (gref->writeable) { ! 275: while (!(*gref->writeable)(gref)) { ! 276: /* flow control on, wait to be enabled to write */ ! 277: gref->sevents |= POLLSYNC; ! 278: err = tsleep(&gref->event, PSOCK | PCATCH, "AT write", 0); ! 279: gref->sevents &= ~POLLSYNC; ! 280: if (err != 0) { ! 281: ATENABLE(s, gref->lock); ! 282: return err; ! 283: } ! 284: } ! 285: } ! 286: ! 287: ATENABLE(s, gref->lock); ! 288: ! 289: /* allocate a buffer to copy in the write data */ ! 290: if ((m = gbuf_alloc(AT_WR_OFFSET+len, PRI_MED)) == 0) ! 291: return ENOBUFS; ! 292: gbuf_rinc(m,AT_WR_OFFSET); ! 293: gbuf_wset(m,len); ! 294: ! 295: /* copy in the write data */ ! 296: #ifdef _AIX ! 297: if (uiomove((caddr_t)gbuf_rptr(m), len, UIO_WRITE, uio) == -1) { ! 298: #else ! 299: uio->uio_rw = UIO_WRITE; ! 300: res= uiomove((caddr_t)gbuf_rptr(m), len, uio); ! 301: /* kprintf("_ATrw: UIO_WRITE: res=%d\n", res); */ ! 302: if (res == -1) { ! 303: #endif ! 304: gbuf_freeb(m); ! 305: return EIO; ! 306: } ! 307: ! 308: /* forward the write data to the appropriate protocol module */ ! 309: gref_wput(gref, m); ! 310: } ! 311: ! 312: return 0; ! 313: } ! 314: ! 315: int _ATread(fp, uio, cred) ! 316: void *fp; ! 317: struct uio *uio; ! 318: void *cred; ! 319: { ! 320: return _ATrw(fp, UIO_READ, uio, 0); ! 321: } ! 322: ! 323: int _ATwrite(fp, uio, cred) ! 324: void *fp; ! 325: struct uio *uio; ! 326: void *cred; ! 327: { ! 328: return _ATrw(fp, UIO_WRITE, uio, 0); ! 329: } ! 330: /* ! 331: struct at_ioctl_args { ! 332: int fdes; ! 333: u_long cmd; ! 334: caddr_t arg; ! 335: }; ! 336: int _ATioctl(p, uap, retval) ! 337: struct proc *p; ! 338: register struct at_ioctl_args *uap; ! 339: register_t *retval; ! 340: */ ! 341: int _ATioctl(fp, cmd, arg, proc) ! 342: void *fp; ! 343: u_long cmd; ! 344: register caddr_t arg; ! 345: void *proc; ! 346: { ! 347: void gref_wput(); ! 348: int s, err, len; ! 349: gref_t *gref; ! 350: gbuf_t *m, *mdata; ! 351: ioc_t *ioc; ! 352: ioccmd_t ioccmd; ! 353: ! 354: ! 355: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) { ! 356: #ifdef APPLETALK_DEBUG ! 357: kprintf("_ATioctl: atalk_getref=%d\n", err); ! 358: #endif ! 359: return err; ! 360: } ! 361: ! 362: /* error if not for us */ ! 363: if ((cmd & 0xffff) != 0xff99) ! 364: return EOPNOTSUPP; ! 365: ! 366: /* copy in ioc command info */ ! 367: /* ! 368: kprintf("_ATioctl: arg ioccmd.ic_cmd=%x ic_len=%x gref->lock=%x, gref->event=%x\n", ! 369: ((ioccmd_t *)arg)->ic_cmd, ((ioccmd_t *)arg)->ic_len, gref->lock, gref->event); ! 370: */ ! 371: if ((err = copyin((caddr_t)arg, ! 372: (caddr_t)&ioccmd, sizeof(ioccmd_t))) != 0) { ! 373: #ifdef APPLETALK_DEBUG ! 374: kprintf("_ATioctl: err = %d, copyin(%x, %x, %d)\n", err, (caddr_t)arg, ! 375: (caddr_t)&ioccmd, sizeof(ioccmd_t)); ! 376: #endif ! 377: return err; ! 378: } ! 379: ! 380: /* allocate a buffer to create an ioc command */ ! 381: if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0) ! 382: return ENOBUFS; ! 383: gbuf_wset(m,sizeof(ioc_t)); ! 384: gbuf_set_type(m, MSG_IOCTL); ! 385: ! 386: /* create the ioc command */ ! 387: if (ioccmd.ic_len) { ! 388: if ((gbuf_cont(m) = gbuf_alloc(ioccmd.ic_len, PRI_HI)) == 0) { ! 389: gbuf_freem(m); ! 390: #ifdef APPLETALK_DEBUG ! 391: kprintf("_ATioctl: gbuf_alloc err=%d\n",ENOBUFS); ! 392: #endif ! 393: return ENOBUFS; ! 394: } ! 395: gbuf_wset(gbuf_cont(m),ioccmd.ic_len); ! 396: if ((err = copyin((caddr_t)ioccmd.ic_dp, ! 397: (caddr_t)gbuf_rptr(gbuf_cont(m)), ioccmd.ic_len)) != 0) { ! 398: gbuf_freem(m); ! 399: return err; ! 400: } ! 401: } ! 402: ioc = (ioc_t *)gbuf_rptr(m); ! 403: ioc->ioc_cmd = ioccmd.ic_cmd; ! 404: ioc->ioc_count = ioccmd.ic_len; ! 405: ioc->ioc_error = 0; ! 406: ioc->ioc_rval = 0; ! 407: ! 408: /* send the ioc command to the appropriate recipient */ ! 409: gref_wput(gref, m); ! 410: ! 411: /* wait for the ioc ack */ ! 412: ATDISABLE(s, gref->lock); ! 413: while ((m = gref->ichead) == 0) { ! 414: gref->sevents |= POLLPRI; ! 415: err = tsleep(&gref->iocevent, PSOCK | PCATCH, "AT ioctl", 0); ! 416: gref->sevents &= ~POLLPRI; ! 417: if (err != 0) { ! 418: ATENABLE(s, gref->lock); ! 419: #ifdef APPLETALK_DEBUG ! 420: kprintf("_ATioctl: EINTR\n"); ! 421: #endif ! 422: return err; ! 423: } ! 424: } ! 425: ! 426: /* PR-2224797 */ ! 427: if (gbuf_next(m) == m) /* error case */ ! 428: gbuf_next(m) = 0; ! 429: ! 430: gref->ichead = gbuf_next(m); ! 431: ! 432: ATENABLE(s, gref->lock); ! 433: ! 434: ! 435: /* kprintf("_ATioctl: woke up from tread sleep\n"); */ ! 436: /* process the ioc response */ ! 437: ioc = (ioc_t *)gbuf_rptr(m); ! 438: if ((err = ioc->ioc_error) == 0) { ! 439: ioccmd.ic_timout = ioc->ioc_rval; ! 440: ioccmd.ic_len = 0; ! 441: mdata = gbuf_cont(m); ! 442: if (mdata && ioccmd.ic_dp) { ! 443: ioccmd.ic_len = gbuf_msgsize(mdata); ! 444: for (len=0; mdata; mdata=gbuf_cont(mdata)) { ! 445: if ((err = copyout((caddr_t)gbuf_rptr(mdata), ! 446: (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata))) < 0) { ! 447: #ifdef APPLETALK_DEBUG ! 448: kprintf("_ATioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n", ! 449: len, err, (caddr_t)gbuf_rptr(mdata), ! 450: (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata)); ! 451: #endif ! 452: goto l_done; ! 453: } ! 454: len += gbuf_len(mdata); ! 455: } ! 456: } ! 457: if ((err = copyout((caddr_t)&ioccmd, ! 458: (caddr_t)arg, sizeof(ioccmd_t))) != 0) { ! 459: #ifdef APPLETALK_DEBUG ! 460: kprintf("_ATioctl: error copyout2=%d from=%x to=%x len=%d\n", ! 461: err, &ioccmd, arg, sizeof(ioccmd_t)); ! 462: #endif ! 463: goto l_done; ! 464: } ! 465: } ! 466: ! 467: l_done: ! 468: gbuf_freem(m); ! 469: /*kprintf("_ATioctl: I_done=%d\n", err);*/ ! 470: return err; ! 471: } ! 472: ! 473: #ifndef _AIX ! 474: int _ATselect(fp, which, proc) ! 475: void *fp; ! 476: int which; ! 477: void *proc; ! 478: { ! 479: int s, err, rc = 0; ! 480: gref_t *gref; ! 481: ! 482: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) ! 483: return err; ! 484: ! 485: ATDISABLE(s, gref->lock); ! 486: if (which == FREAD) { ! 487: if (gref->rdhead || (gref->readable && (*gref->readable)(gref))) ! 488: rc = 1; ! 489: else { ! 490: gref->sevents |= POLLIN; ! 491: selrecord(proc, &gref->si); ! 492: } ! 493: } ! 494: ! 495: else if (which == POLLOUT) { ! 496: if (gref->writeable) { ! 497: if ((*gref->writeable)(gref)) ! 498: rc = 1; ! 499: else { ! 500: gref->sevents |= POLLOUT; ! 501: selrecord(proc, &gref->si); ! 502: } ! 503: } else ! 504: rc = 1; ! 505: } ! 506: ATENABLE(s, gref->lock); ! 507: ! 508: return rc; ! 509: } ! 510: ! 511: #else /* AIX code is no longer supported. */ ! 512: ! 513: int _ATselect(fp, corl, reqevents, retevents, notify) ! 514: void *fp; ! 515: int corl; ! 516: unsigned short reqevents; ! 517: unsigned short *retevents; ! 518: void (*notify)(); ! 519: { ! 520: int s, err, rc = 0; ! 521: gref_t *gref; ! 522: unsigned short sevents = 0; ! 523: ! 524: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) ! 525: return err; ! 526: ! 527: ATDISABLE(s, gref->lock); ! 528: if (reqevents & POLLIN) { ! 529: if (gref->rdhead || (gref->readable && (*gref->readable)(gref))) ! 530: sevents |= POLLIN; ! 531: } ! 532: ! 533: if (reqevents & POLLOUT) { ! 534: if (gref->writeable) { ! 535: if ((*gref->writeable)(gref)) ! 536: sevents |= POLLOUT; ! 537: } else ! 538: sevents |= POLLOUT; ! 539: } ! 540: ! 541: if ((sevents == 0) && ((reqevents & POLLSYNC) == 0)) { ! 542: if (rc = selreg(corl, 99, gref, reqevents, notify)) { ! 543: ATENABLE(s, gref->lock); ! 544: goto l_done; ! 545: } ! 546: ! 547: if (reqevents & POLLIN) { ! 548: if (gref->rdhead || (gref->readable && (*gref->readable)(gref))) ! 549: sevents |= POLLIN; ! 550: else ! 551: gref->sevents |= POLLIN; ! 552: } ! 553: ! 554: if (reqevents & POLLOUT) { ! 555: if (gref->writeable) { ! 556: if ((*gref->writeable)(gref)) ! 557: sevents |= POLLOUT; ! 558: else ! 559: gref->sevents |= POLLOUT; ! 560: } else ! 561: sevents |= POLLOUT; ! 562: } ! 563: } ! 564: ATENABLE(s, gref->lock); ! 565: *retevents = sevents; ! 566: ! 567: l_done: ! 568: return rc; ! 569: } ! 570: ! 571: int _ATstat() ! 572: { ! 573: return 0; ! 574: } ! 575: #endif /* end AIX section */ ! 576: ! 577: void atalk_putnext(gref, m) ! 578: gref_t *gref; ! 579: gbuf_t *m; ! 580: { ! 581: int s; ! 582: ! 583: ATDISABLE(s, gref->lock); ! 584: ! 585: gbuf_next(m) = 0; ! 586: ! 587: if ((gbuf_type(m) == MSG_IOCACK) || (gbuf_type(m) == MSG_IOCNAK)) { ! 588: if (gref->ichead) ! 589: gbuf_next(gref->ichead) = m; ! 590: else { ! 591: gref->ichead = m; ! 592: if (gref->sevents & POLLPRI) { ! 593: /*kprintf("atalk_putnext: wake up gref->event=%x\n", &gref->event);*/ ! 594: thread_wakeup(&gref->iocevent); ! 595: } ! 596: atalk_notify_sel(gref); ! 597: } ! 598: ! 599: } else { ! 600: if (gref->errno == 0) { ! 601: if (gbuf_type(m) == MSG_ERROR) { ! 602: gref->errno = *gbuf_rptr(m); ! 603: if (gref->rdhead) { ! 604: gbuf_freel(gref->rdhead); ! 605: gref->rdhead = 0; ! 606: } ! 607: if (gref->sevents & POLLMSG) { ! 608: gref->sevents &= ~POLLMSG; ! 609: /*kprintf("atalk_putnext: wake up gref->event=%x\n", &gref->event);*/ ! 610: thread_wakeup(&gref->event); ! 611: } ! 612: if (gref->sevents & POLLIN) { ! 613: gref->sevents &= ~POLLIN; ! 614: /*kprintf("atalk_putnext: selwakeup gref->si=%x\n", &gref->si); */ ! 615: selwakeup(&gref->si); ! 616: } ! 617: } else if (gref->rdhead) { ! 618: gbuf_next(gref->rdtail) = m; ! 619: gref->rdtail = m; ! 620: } else { ! 621: gref->rdhead = m; ! 622: if (gref->sevents & POLLMSG) { ! 623: gref->sevents &= ~POLLMSG; ! 624: /*kprintf("atalk_putnext: wake up2 gref->event=%x\n", &gref->event);*/ ! 625: thread_wakeup(&gref->event); ! 626: } ! 627: if (gref->sevents & POLLIN) { ! 628: gref->sevents &= ~POLLIN; ! 629: /*kprintf("atalk_putnext: selwakeup2 gref->si=%x\n", &gref->si);*/ ! 630: selwakeup(&gref->si); ! 631: } ! 632: gref->rdtail = m; ! 633: } ! 634: } ! 635: } ! 636: ! 637: ATENABLE(s, gref->lock); ! 638: } ! 639: ! 640: void atalk_enablew(gref) ! 641: gref_t *gref; ! 642: { ! 643: if (gref->sevents & POLLSYNC) ! 644: #ifdef _AIX ! 645: e_wakeup(&gref->event); ! 646: #else ! 647: thread_wakeup(&gref->event); ! 648: #endif ! 649: } ! 650: ! 651: void atalk_flush(gref) ! 652: gref_t *gref; ! 653: { ! 654: int s; ! 655: ! 656: ATDISABLE(s, gref->lock); ! 657: if (gref->rdhead) { ! 658: gbuf_freel(gref->rdhead); ! 659: gref->rdhead = 0; ! 660: } ! 661: if (gref->ichead) { ! 662: gbuf_freel(gref->ichead); ! 663: gref->ichead = 0; ! 664: } ! 665: ATENABLE(s, gref->lock); ! 666: } ! 667: ! 668: void atalk_notify_sel(gref) ! 669: gref_t *gref; ! 670: { ! 671: int s; ! 672: ! 673: ATDISABLE(s, gref->lock); ! 674: if (gref->sevents & POLLIN) { ! 675: gref->sevents &= ~POLLIN; ! 676: selwakeup(&gref->si); ! 677: } ! 678: ATENABLE(s, gref->lock); ! 679: } ! 680: ! 681: int atalk_peek(gref, event) ! 682: gref_t *gref; ! 683: unsigned char *event; ! 684: { ! 685: int s, rc; ! 686: ! 687: ATDISABLE(s, gref->lock); ! 688: if (gref->rdhead) { ! 689: *event = *gbuf_rptr(gref->rdhead); ! 690: rc = 0; ! 691: } else ! 692: rc = -1; ! 693: ATENABLE(s, gref->lock); ! 694: ! 695: return rc; ! 696: } ! 697: ! 698: static gbuf_t *trace_msg; ! 699: ! 700: void atalk_settrace(str, p1, p2, p3, p4, p5) ! 701: char *str; ! 702: { ! 703: int len; ! 704: gbuf_t *m, *nextm; ! 705: char trace_buf[256]; ! 706: ! 707: sprintf(trace_buf, str, p1, p2, p3, p4, p5); ! 708: len = strlen(trace_buf); ! 709: #ifdef APPLETALK_DEBUG ! 710: kprintf("atalk_settrace: gbufalloc size=%d\n", len+1); ! 711: #endif ! 712: if ((m = gbuf_alloc(len+1, PRI_MED)) == 0) ! 713: return; ! 714: gbuf_wset(m,len); ! 715: strcpy(gbuf_rptr(m), trace_buf); ! 716: if (trace_msg) { ! 717: for (nextm=trace_msg; gbuf_cont(nextm); nextm=gbuf_cont(nextm)) ; ! 718: gbuf_cont(nextm) = m; ! 719: } else ! 720: trace_msg = m; ! 721: } ! 722: ! 723: void atalk_gettrace(m) ! 724: gbuf_t *m; ! 725: { ! 726: if (trace_msg) { ! 727: gbuf_cont(m) = trace_msg; ! 728: trace_msg = 0; ! 729: } ! 730: } ! 731: ! 732: #define GREF_PER_BLK 32 ! 733: static gref_t *gref_free_list = 0; ! 734: atlock_t refall_lock; ! 735: ! 736: void gref_init() ! 737: { ! 738: ATLOCKINIT(refall_lock); ! 739: } ! 740: ! 741: gref_t *gref_alloc() ! 742: { ! 743: extern gbuf_t *atp_resource_m; ! 744: int i, s; ! 745: gbuf_t *m; ! 746: gref_t *gref, *gref_array; ! 747: ! 748: ATDISABLE(s, refall_lock); ! 749: if (gref_free_list == 0) { ! 750: ATENABLE(s, refall_lock); ! 751: #ifdef APPLETALK_DEBUG ! 752: kprintf("gref_alloc: gbufalloc size=%d\n", GREF_PER_BLK*sizeof(gref_t)); ! 753: #endif ! 754: if ((m = gbuf_alloc(GREF_PER_BLK*sizeof(gref_t),PRI_HI)) == 0) ! 755: return (gref_t *)0; ! 756: bzero(gbuf_rptr(m), GREF_PER_BLK*sizeof(gref_t)); ! 757: gref_array = (gref_t *)gbuf_rptr(m); ! 758: for (i=0; i < GREF_PER_BLK-1; i++) ! 759: gref_array[i].next = (gref_t *)&gref_array[i+1]; ! 760: ATDISABLE(s, refall_lock); ! 761: gbuf_cont(m) = atp_resource_m; ! 762: atp_resource_m = m; ! 763: gref_array[i].next = gref_free_list; ! 764: gref_free_list = (gref_t *)&gref_array[0]; ! 765: } ! 766: ! 767: gref = gref_free_list; ! 768: gref_free_list = gref->next; ! 769: ATENABLE(s, refall_lock); ! 770: ATLOCKINIT(gref->lock); ! 771: ATEVENTINIT(gref->event); ! 772: ATEVENTINIT(gref->iocevent); ! 773: ! 774: return gref; ! 775: } ! 776: ! 777: void gref_free(gref) ! 778: gref_t *gref; ! 779: { ! 780: int s; ! 781: ! 782: ATDISABLE(s, refall_lock); ! 783: bzero((char *)gref, sizeof(gref_t)); ! 784: gref->next = gref_free_list; ! 785: gref_free_list = gref; ! 786: ATENABLE(s, refall_lock); ! 787: } ! 788: ! 789: int gref_open(grefp) ! 790: gref_t **grefp; ! 791: { ! 792: gref_t *gref; ! 793: ! 794: /* ! 795: * if no gref structure available, return failure ! 796: */ ! 797: if ((gref = (gref_t *)gref_alloc()) == 0) ! 798: return ENOBUFS; ! 799: #ifndef NEXT ! 800: gref->pid = getpid(); ! 801: #endif ! 802: *grefp = gref; ! 803: ! 804: return 0; ! 805: } ! 806: ! 807: int gref_close(gref) ! 808: gref_t *gref; ! 809: { ! 810: int rc; ! 811: ! 812: switch (gref->proto) { ! 813: case ATPROTO_DDP: ! 814: rc = ddp_close(gref); break; ! 815: case ATPROTO_LAP: ! 816: rc = lap_close(gref); break; ! 817: case ATPROTO_ATP: ! 818: rc = atp_close(gref, 1); break; ! 819: case ATPROTO_ASP: ! 820: rc = asp_close(gref); break; ! 821: #ifdef AURP_SUPPORT ! 822: case ATPROTO_AURP: ! 823: rc = aurp_close(gref); break; ! 824: break; ! 825: #endif ! 826: case ATPROTO_ADSP: ! 827: rc = adsp_close(gref); break; ! 828: default: ! 829: rc = 0; ! 830: break; ! 831: } ! 832: ! 833: if (rc == 0) { ! 834: atalk_flush(gref); ! 835: selthreadclear(&gref->si); ! 836: gref_free(gref); ! 837: } ! 838: ! 839: return rc; ! 840: } ! 841: ! 842: void gref_wput(gref, m) ! 843: gref_t *gref; ! 844: gbuf_t *m; ! 845: { ! 846: ! 847: switch (gref->proto) { ! 848: case ATPROTO_DDP: ! 849: ddp_putmsg(gref, m); break; ! 850: case ATPROTO_LAP: ! 851: elap_wput(gref, m); break; ! 852: case ATPROTO_ATP: ! 853: atp_wput(gref, m); break; ! 854: case ATPROTO_ASP: ! 855: asp_wput(gref, m); break; ! 856: #ifdef AURP_SUPPORT ! 857: case ATPROTO_AURP: ! 858: aurp_wput(gref, m); break; ! 859: #endif ! 860: case ATPROTO_ADSP: ! 861: adsp_wput(gref, m); break; ! 862: case ATPROTO_NONE: ! 863: if (gbuf_type(m) == MSG_IOCTL) { ! 864: gbuf_freem(gbuf_cont(m)); ! 865: gbuf_cont(m) = 0; ! 866: ((ioc_t *)gbuf_rptr(m))->ioc_rval = -1; ! 867: ((ioc_t *)gbuf_rptr(m))->ioc_error = EPROTO; ! 868: gbuf_set_type(m, MSG_IOCNAK); ! 869: atalk_putnext(gref, m); ! 870: } else ! 871: gbuf_freem(m); ! 872: break; ! 873: default: ! 874: gbuf_freem(m); ! 875: break; ! 876: } ! 877: } ! 878: ! 879: int gbuf_msgsize(m) ! 880: gbuf_t *m; ! 881: { ! 882: int size; ! 883: ! 884: for (size=0; m; m=gbuf_cont(m)) ! 885: size += gbuf_len(m); ! 886: return size; ! 887: } ! 888: ! 889: /* Duplicate a single mbuf, attaching existing external storage. */ ! 890: gbuf_t *gbuf_dupb(m) ! 891: gbuf_t *m; ! 892: { ! 893: return((gbuf_t *)m_copym(m, 0, gbuf_len(m), M_DONTWAIT)); ! 894: } ! 895: ! 896: gbuf_t *gbuf_dupb_wait(m, wait) ! 897: gbuf_t *m; ! 898: int wait; ! 899: { ! 900: return((gbuf_t *)m_copym(m, 0, gbuf_len(m), (wait)? M_WAIT: M_DONTWAIT)); ! 901: } ! 902: ! 903: /* Duplicate an mbuf chain, attaching existing external storage. */ ! 904: gbuf_t *gbuf_dupm(mlist) ! 905: gbuf_t *mlist; ! 906: { ! 907: return((gbuf_t *)m_copym(mlist, 0, M_COPYALL, M_DONTWAIT)); ! 908: } ! 909: ! 910: gbuf_t *gbuf_copym(mlist) ! 911: gbuf_t *mlist; ! 912: { ! 913: int len, offset; ! 914: gbuf_t *m, *mcurr, *mprev, *mhead; ! 915: ! 916: offset = AT_WR_OFFSET; ! 917: for (mhead = 0, m = mlist; m; m = gbuf_cont(m)) { ! 918: if ((len = gbuf_len(m)) == 0) ! 919: continue; ! 920: if ((mcurr = gbuf_alloc(offset+len, PRI_MED)) == 0) { ! 921: if (mhead) ! 922: gbuf_freem(mhead); ! 923: return (gbuf_t *)0; ! 924: } ! 925: gbuf_rinc(mcurr,offset); ! 926: gbuf_wset(mcurr,len); ! 927: gbuf_set_type(mcurr, gbuf_type(m)); ! 928: bcopy(gbuf_rptr(m), gbuf_rptr(mcurr), len); ! 929: if (mhead) ! 930: gbuf_cont(mprev) = mcurr; ! 931: else { ! 932: mhead = mcurr; ! 933: offset = 0; ! 934: } ! 935: mprev = mcurr; ! 936: } ! 937: ! 938: return (gbuf_t *)mhead; ! 939: } ! 940: ! 941: void gbuf_freem(mlist) ! 942: gbuf_t *mlist; ! 943: { ! 944: m_freem((struct mbuf *)mlist); ! 945: } ! 946: ! 947: void gbuf_linkb(m1, m2) ! 948: gbuf_t *m1; ! 949: gbuf_t *m2; ! 950: { ! 951: while (gbuf_cont(m1) != 0) ! 952: m1 = gbuf_cont(m1); ! 953: gbuf_cont(m1) = m2; ! 954: } ! 955: ! 956: /**************************************/ ! 957: ! 958: int ddp_adjmsg(m, len) ! 959: gbuf_t *m; ! 960: int len; ! 961: { ! 962: int buf_len; ! 963: gbuf_t *curr_m, *prev_m; ! 964: ! 965: if (m == (gbuf_t *)0) ! 966: return 0; ! 967: ! 968: if (len > 0) { ! 969: for (curr_m=m; curr_m;) { ! 970: buf_len = gbuf_len(curr_m); ! 971: if (len < buf_len) { ! 972: gbuf_rinc(curr_m,len); ! 973: return 1; ! 974: } ! 975: len -= buf_len; ! 976: gbuf_rinc(curr_m,buf_len); ! 977: if ((curr_m = gbuf_cont(curr_m)) == 0) { ! 978: gbuf_freem(m); ! 979: return 0; ! 980: } ! 981: } ! 982: ! 983: } else if (len < 0) { ! 984: len = -len; ! 985: l_cont: prev_m = 0; ! 986: for (curr_m=m; gbuf_cont(curr_m); ! 987: prev_m=curr_m, curr_m=gbuf_cont(curr_m)) ; ! 988: buf_len = gbuf_len(curr_m); ! 989: if (len < buf_len) { ! 990: gbuf_wdec(curr_m,len); ! 991: return 1; ! 992: } ! 993: if (prev_m == 0) ! 994: return 0; ! 995: gbuf_cont(prev_m) = 0; ! 996: gbuf_freeb(curr_m); ! 997: len -= buf_len; ! 998: goto l_cont; ! 999: ! 1000: } else ! 1001: return 1; ! 1002: } ! 1003: ! 1004: /* ! 1005: * The message chain, m is grown in size by len contiguous bytes. ! 1006: * If len is non-negative, len bytes are added to the ! 1007: * end of the gbuf_t chain. If len is negative, the ! 1008: * bytes are added to the front. ddp_growmsg only adds bytes to ! 1009: * message blocks of the same type. ! 1010: * It returns a pointer to the new gbuf_t on sucess, 0 on failure. ! 1011: */ ! 1012: ! 1013: gbuf_t *ddp_growmsg(mp, len) ! 1014: gbuf_t *mp; ! 1015: int len; ! 1016: { ! 1017: gbuf_t *m, *d; ! 1018: ! 1019: if ((m = mp) == (gbuf_t *) 0) ! 1020: return ((gbuf_t *) 0); ! 1021: ! 1022: if (len <= 0) { ! 1023: len = -len; ! 1024: if ((d = gbuf_alloc(len, PRI_MED)) == 0) ! 1025: return ((gbuf_t *) 0); ! 1026: gbuf_set_type(d, gbuf_type(m)); ! 1027: gbuf_wset(d,len); ! 1028: /* link in new gbuf_t */ ! 1029: gbuf_cont(d) = m; ! 1030: return (d); ! 1031: ! 1032: } else { ! 1033: register int count; ! 1034: /* ! 1035: * Add to tail. ! 1036: */ ! 1037: if ((count = gbuf_msgsize(m)) < 0) ! 1038: return ((gbuf_t *) 0); ! 1039: /* find end of chain */ ! 1040: for ( ; m; m = gbuf_cont(m)) { ! 1041: if (gbuf_len(m) >= count) ! 1042: break; ! 1043: count -= gbuf_len(m); ! 1044: } ! 1045: /* m now points to gbuf_t to add to */ ! 1046: if ((d = gbuf_alloc(len, PRI_MED)) == 0) ! 1047: return ((gbuf_t *) 0); ! 1048: gbuf_set_type(d, gbuf_type(m)); ! 1049: /* link in new gbuf_t */ ! 1050: gbuf_cont(d) = gbuf_cont(m); ! 1051: gbuf_cont(m) = d; ! 1052: gbuf_wset(d,len); ! 1053: return (d); ! 1054: } ! 1055: } ! 1056: ! 1057: ! 1058: ! 1059: /* ! 1060: * return an MSG_ERROR on the read stream. Note that the same message ! 1061: * block that caused the problem is used as the vehicle. So chained ! 1062: * blocks to this message will be free'd; i.e. ASSUMES no multiple ! 1063: * references. ! 1064: * Used by other appletalk modules, so it is not static! ! 1065: */ ! 1066: ! 1067: void data_error(errno,mp,gref) ! 1068: int errno; ! 1069: register gbuf_t *mp; ! 1070: register gref_t *gref; ! 1071: { ! 1072: ! 1073: gbuf_set_type(mp, MSG_ERROR); ! 1074: ! 1075: *gbuf_rptr(mp) = (unsigned char)errno; ! 1076: gbuf_wset(mp,1); ! 1077: if (gbuf_cont(mp)) { ! 1078: gbuf_freem(gbuf_cont(mp)); ! 1079: gbuf_cont(mp) = 0; ! 1080: } ! 1081: ! 1082: atalk_putnext(gref, mp); ! 1083: } ! 1084: ! 1085: /* ! 1086: * return the MSG_IOCACK/MSG_IOCNAK. Note that the same message ! 1087: * block is used as the vehicle, and that if there is an error return, ! 1088: * then linked blocks are lopped off. BEWARE of multiple references. ! 1089: * Used by other appletalk modules, so it is not static! ! 1090: */ ! 1091: ! 1092: void ioc_ack(errno, m, gref) ! 1093: int errno; ! 1094: register gbuf_t *m; ! 1095: register gref_t *gref; ! 1096: ! 1097: { ! 1098: ioc_t *iocbp = (ioc_t *)gbuf_rptr(m); ! 1099: ! 1100: /*kprintf("ioc_ack: m=%x gref=%x errno=%d\n", m, gref, errno);*/ ! 1101: ! 1102: if (gref->info == NULL) { ! 1103: gbuf_freem(m); ! 1104: #ifdef APPLETALK_DEBUG ! 1105: kprintf("ioc_ack: gref->info == NULL: free m\n"); ! 1106: #endif ! 1107: return; ! 1108: } ! 1109: if ((iocbp->ioc_error = errno) != 0) ! 1110: { /* errno != 0, then there is an error, get rid of linked blocks! */ ! 1111: ! 1112: if (gbuf_cont(m)) { ! 1113: gbuf_freem(gbuf_cont(m)); ! 1114: gbuf_cont(m) = 0; ! 1115: } ! 1116: gbuf_set_type(m, MSG_IOCNAK); ! 1117: iocbp->ioc_count = 0; /* only make zero length if error */ ! 1118: iocbp->ioc_rval = -1; ! 1119: } else ! 1120: gbuf_set_type(m, MSG_IOCACK); ! 1121: ! 1122: atalk_putnext(gref, m); ! 1123: } ! 1124: ! 1125: /* Queue management functions */ ! 1126: ! 1127: void ! 1128: ddp_remque(elem) ! 1129: register LIB_QELEM_T *elem; ! 1130: { ! 1131: elem->q_back->q_forw = elem->q_forw; ! 1132: elem->q_forw->q_back = elem->q_back; ! 1133: } ! 1134: ! 1135: void ! 1136: ddp_insque(elem, prev) ! 1137: register LIB_QELEM_T *elem, *prev; ! 1138: { ! 1139: elem->q_back = prev; ! 1140: elem->q_forw = prev->q_forw; ! 1141: prev->q_forw->q_back = elem; ! 1142: prev->q_forw = elem; ! 1143: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.