|
|
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) 1996-1998 Apple Computer, Inc. ! 27: * All Rights Reserved. ! 28: * ! 29: * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF APPLE COMPUTER, INC. ! 30: * The copyright notice above does not evidence any actual or ! 31: * intended publication of such source code. ! 32: */ ! 33: ! 34: #define RESOLVE_DBG ! 35: ! 36: #include <appletalk.h> ! 37: #include <atp.h> ! 38: #include <at_atp.h> ! 39: #include <atp_inc.h> ! 40: #include <lap.h> ! 41: #include <at_lap.h> ! 42: #include <ddp.h> ! 43: #include <at_ddp.h> ! 44: #include <at_asp.h> ! 45: #include <adsp_frames.h> ! 46: #include <atlog.h> ! 47: ! 48: static void atp_pack_bdsp(struct atp_trans *, struct atpBDS *); ! 49: static int atp_unpack_bdsp(struct atp_state *, gbuf_t *, struct atp_rcb *, ! 50: int, int); ! 51: ! 52: extern struct atp_rcb_qhead atp_need_rel; ! 53: extern int atp_inited; ! 54: extern char atp_off_flag; ! 55: extern struct atp_state *atp_used_list; ! 56: extern atlock_t atpgen_lock; ! 57: extern atlock_t atpall_lock; ! 58: extern atlock_t atptmo_lock; ! 59: ! 60: extern gref_t *atp_inputQ[]; ! 61: extern int atp_pidM[]; ! 62: extern char ot_atp_socketM[]; ! 63: extern char ddp_off_flag; ! 64: extern int ot_protoCnt; ! 65: extern char ot_protoT[]; ! 66: ! 67: static struct atp_trans *trp_tmo_list; ! 68: struct atp_trans *trp_tmo_rcb; ! 69: ! 70: /* ! 71: * write queue put routine .... filter out other than IOCTLs ! 72: * Version 1.8 of atp_write.c on 89/02/09 17:53:26 ! 73: */ ! 74: ! 75: void ! 76: atp_wput(gref, m) ! 77: register gref_t *gref; ! 78: register gbuf_t *m; ! 79: { ! 80: register ioc_t *iocbp; ! 81: int i, xcnt, s; ! 82: struct atp_state *atp; ! 83: struct atp_trans *trp; ! 84: struct atp_rcb *rcbp; ! 85: at_socket skt; ! 86: ! 87: atp = (struct atp_state *)gref->info; ! 88: if (atp->dflag) ! 89: atp = (struct atp_state *)atp->atp_msgq; ! 90: ! 91: switch(gbuf_type(m)) { ! 92: case MSG_DATA: ! 93: if (atp->atp_msgq) { ! 94: gbuf_freem(m); ! 95: dPrintf(D_M_ATP, D_L_WARNING, ! 96: ("atp_wput: atp_msgq discarded\n")); ! 97: } else ! 98: atp->atp_msgq = m; ! 99: break; ! 100: ! 101: case MSG_IOCTL: ! 102: /* Need to ensure that all copyin/copyout calls are made at ! 103: * put routine time which should be in the user context. (true when ! 104: * we are the stream head). The service routine can be called on an ! 105: * unpredictable context and copyin/copyout calls will get wrong results ! 106: * or even panic the kernel. ! 107: */ ! 108: iocbp = (ioc_t *)gbuf_rptr(m); ! 109: ! 110: switch (iocbp->ioc_cmd) { ! 111: case AT_ATP_LINK: ! 112: atp_dequeue_atp(atp); ! 113: ot_protoT[DDP_ATP] = 1; ! 114: ot_protoCnt++; ! 115: ! 116: iocbp->ioc_rval = 0; ! 117: atp_iocack(atp, m); ! 118: trp_tmo_list = 0; ! 119: trp_tmo_rcb = atp_trans_alloc(0); ! 120: atp_timout(atp_rcb_timer, trp_tmo_rcb, 10 * HZ); ! 121: atp_trp_timer(&atp_inited, 0); ! 122: asp_timer(&atp_inited, 0); ! 123: return; ! 124: ! 125: case AT_ATP_UNLINK: ! 126: ot_protoT[DDP_ATP] = 0; ! 127: ot_protoCnt--; ! 128: ddp_off_flag = 0; /* why clear this in an unlink? */ ! 129: ! 130: trp_tmo_list = 0; ! 131: atp_trp_timer(&atp_inited, 1); ! 132: asp_timer(&atp_inited, 1); ! 133: atp_inited = 0; ! 134: iocbp->ioc_rval = 0; ! 135: atp_iocack(atp, m); ! 136: return; ! 137: ! 138: case AT_ATP_BIND_REQ: ! 139: if (gbuf_cont(m) == NULL) { ! 140: iocbp->ioc_rval = -1; ! 141: atp_iocnak(atp, m, EINVAL); ! 142: return; ! 143: } ! 144: skt = *(at_socket *)gbuf_rptr(gbuf_cont(m)); ! 145: if ((skt = (at_socket)atp_bind(gref, (unsigned int)skt, 0)) == 0) ! 146: atp_iocnak(atp, m, EINVAL); ! 147: else { ! 148: *(at_socket *)gbuf_rptr(gbuf_cont(m)) = skt; ! 149: iocbp->ioc_rval = 0; ! 150: atp_iocack(atp, m); ! 151: atp_dequeue_atp(atp); ! 152: } ! 153: return; ! 154: ! 155: case AT_ATP_GET_CHANID: ! 156: if (gbuf_cont(m) == NULL) { ! 157: iocbp->ioc_rval = -1; ! 158: atp_iocnak(atp, m, EINVAL); ! 159: return; ! 160: } ! 161: *(gref_t **)gbuf_rptr(gbuf_cont(m)) = gref; ! 162: atp_iocack(atp, m); ! 163: return; ! 164: ! 165: case AT_ATP_ISSUE_REQUEST_DEF: ! 166: /* case AT_ATP_ISSUE_REQUEST_DEF_NOTE: not actually XO */ ! 167: /* AT_ATP_ISSUE_REQUEST_DEF_NOTE is used just for tickle ! 168: so it's not appropriate to check for it here ! 169: */ ! 170: { ! 171: #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX) ! 172: gbuf_t *bds, *tmp; ! 173: ! 174: if ((tmp = gbuf_cont(m)) != 0) { ! 175: if ((bds = gbuf_dupb(tmp)) == NULL) { ! 176: atp_iocnak(atp, m, ENOBUFS); ! 177: return; ! 178: } ! 179: gbuf_rinc(tmp,atpBDSsize); ! 180: gbuf_wset(bds,atpBDSsize); ! 181: iocbp->ioc_count -= atpBDSsize; ! 182: gbuf_cont(tmp) = bds; ! 183: } ! 184: /* FALL THRU */ ! 185: } ! 186: ! 187: case AT_ATP_SEND_FULL_RESPONSE: { ! 188: gbuf_t *m2; ! 189: struct atp_rcb *rcbp; ! 190: at_ddp_t *ddp; ! 191: at_atp_t *athp; ! 192: ! 193: /* ! 194: * send a response to a transaction ! 195: * first check it out ! 196: */ ! 197: if (iocbp->ioc_count < TOTAL_ATP_HDR_SIZE) { ! 198: atp_iocnak(atp, m, EINVAL); ! 199: break; ! 200: } ! 201: ! 202: /* ! 203: * remove the response from the message ! 204: */ ! 205: m2 = gbuf_cont(m); ! 206: gbuf_cont(m) = NULL; ! 207: iocbp->ioc_count = 0; ! 208: ddp = AT_DDP_HDR(m2); ! 209: athp = AT_ATP_HDR(m2); ! 210: if (atp->atp_msgq) { ! 211: gbuf_cont(m2) = atp->atp_msgq; ! 212: atp->atp_msgq = 0; ! 213: } ! 214: ! 215: ATDISABLE(s, atp->atp_lock); ! 216: /* ! 217: * search for the corresponding rcb ! 218: */ ! 219: for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) { ! 220: if (rcbp->rc_tid == UAS_VALUE(athp->tid) && ! 221: rcbp->rc_socket.node == ddp->dst_node && ! 222: rcbp->rc_socket.net == NET_VALUE(ddp->dst_net) && ! 223: rcbp->rc_socket.socket == ddp->dst_socket) ! 224: break; ! 225: } ! 226: ATENABLE(s, atp->atp_lock); ! 227: ! 228: /* ! 229: * If it has already been sent then return an error ! 230: */ ! 231: if ((rcbp && rcbp->rc_state != RCB_NOTIFIED) || ! 232: (rcbp == NULL && athp->xo)) { ! 233: atp_iocnak(atp, m, ENOENT); ! 234: gbuf_freem(m2); ! 235: return; ! 236: } ! 237: if (rcbp == NULL) { /* a response for an ALO transaction */ ! 238: if ((rcbp = atp_rcb_alloc(atp)) == NULL) { ! 239: atp_iocnak(atp, m, ENOBUFS); ! 240: gbuf_freem(m2); ! 241: return; ! 242: } ! 243: rcbp->rc_ioctl = 0; ! 244: rcbp->rc_socket.socket = ddp->dst_socket; ! 245: rcbp->rc_socket.node = ddp->dst_node; ! 246: rcbp->rc_socket.net = NET_VALUE(ddp->dst_net); ! 247: rcbp->rc_tid = UAS_VALUE(athp->tid); ! 248: rcbp->rc_bitmap = 0xff; ! 249: rcbp->rc_xo = 0; ! 250: ATDISABLE(s, atp->atp_lock); ! 251: rcbp->rc_state = RCB_SENDING; ! 252: ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list); ! 253: ATENABLE(s, atp->atp_lock); ! 254: } ! 255: /* first bds entry gives number of bds ! 256: * entries in total (hack) ! 257: */ ! 258: if (gbuf_len(m2) > TOTAL_ATP_HDR_SIZE) ! 259: xcnt = UAS_VALUE(((struct atpBDS *) ! 260: (AT_ATP_HDR(m2)->data))->bdsDataSz); ! 261: else ! 262: xcnt = 0; ! 263: if ((i = atp_unpack_bdsp(atp, m2, rcbp, xcnt, FALSE))) { ! 264: if ( !rcbp->rc_xo) ! 265: atp_rcb_free(rcbp); ! 266: atp_iocnak(atp, m, i); ! 267: return; ! 268: } ! 269: atp_send_replies(atp, rcbp); ! 270: ! 271: /* ! 272: * send the ack back to the responder ! 273: */ ! 274: atp_iocack(atp, m); ! 275: return; ! 276: } ! 277: ! 278: case AT_ATP_GET_POLL: { ! 279: if (gbuf_cont(m)) { ! 280: gbuf_freem(gbuf_cont(m)); ! 281: gbuf_cont(m) = NULL; ! 282: iocbp->ioc_count = 0; ! 283: } ! 284: ! 285: /* ! 286: * search for a waiting request ! 287: */ ! 288: ATDISABLE(s, atp->atp_lock); ! 289: if ((rcbp = atp->atp_attached.head)) { ! 290: /* ! 291: * Got one, move it to the active response Q ! 292: */ ! 293: gbuf_cont(m) = rcbp->rc_ioctl; ! 294: rcbp->rc_ioctl = NULL; ! 295: if (rcbp->rc_xo) { ! 296: ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list); ! 297: rcbp->rc_state = RCB_NOTIFIED; ! 298: ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list); ! 299: } else { ! 300: /* detach rcbp from attached queue, ! 301: * and free any outstanding resources ! 302: */ ! 303: atp_rcb_free(rcbp); ! 304: } ! 305: ATENABLE(s, atp->atp_lock); ! 306: atp_iocack(atp, m); ! 307: } else { ! 308: /* ! 309: * None available - can out ! 310: */ ! 311: ATENABLE(s, atp->atp_lock); ! 312: atp_iocnak(atp, m, EAGAIN); ! 313: } ! 314: break; ! 315: } ! 316: ! 317: case AT_ATP_CANCEL_REQUEST: { ! 318: /* ! 319: * Cancel a pending request ! 320: */ ! 321: if (iocbp->ioc_count != sizeof(int)) { ! 322: atp_iocnak(atp, m, EINVAL); ! 323: break; ! 324: } ! 325: i = *(int *)gbuf_rptr(gbuf_cont(m)); ! 326: gbuf_freem(gbuf_cont(m)); ! 327: gbuf_cont(m) = NULL; ! 328: ATDISABLE(s, atp->atp_lock); ! 329: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) { ! 330: if (trp->tr_tid == i) ! 331: break; ! 332: } ! 333: if (trp == NULL) { ! 334: ATENABLE(s, atp->atp_lock); ! 335: atp_iocnak(atp, m, ENOENT); ! 336: } else { ! 337: ATENABLE(s, atp->atp_lock); ! 338: atp_free(trp); ! 339: atp_iocack(atp, m); ! 340: } ! 341: break; ! 342: } ! 343: ! 344: case AT_ATP_PEEK: { ! 345: unsigned char event; ! 346: if (atalk_peek(gref, &event) == -1) ! 347: atp_iocnak(atp, m, ENOMSG); ! 348: else { ! 349: *gbuf_rptr(gbuf_cont(m)) = event; ! 350: atp_iocack(atp, m); ! 351: } ! 352: break; ! 353: } ! 354: ! 355: default: ! 356: /* ! 357: * Otherwise pass it on, if possible ! 358: */ ! 359: iocbp->ioc_private = (void *)gref; ! 360: if (iocbp->ioc_cmd == DDP_IOC_GET_CFG) { ! 361: iocbp->ioc_count = atp->atp_socket_no; ! 362: iocbp->ioc_error = 3; ! 363: } ! 364: DDP_OUTPUT(m); ! 365: break; ! 366: } ! 367: break; ! 368: ! 369: default: ! 370: gbuf_freem(m); ! 371: break; ! 372: } ! 373: } /* atp_wput */ ! 374: ! 375: gbuf_t *atp_build_release(trp) ! 376: register struct atp_trans *trp; ! 377: { ! 378: register gbuf_t *m; ! 379: register at_ddp_t *ddp; ! 380: register at_atp_t *athp; ! 381: ! 382: /* ! 383: * Now try and allocate enough space to send the message ! 384: * if none is available the caller will schedule ! 385: * a timeout so we can retry for more space soon ! 386: */ ! 387: if ((m = (gbuf_t *)gbuf_alloc(AT_WR_OFFSET+ATP_HDR_SIZE, PRI_HI)) != NULL) { ! 388: gbuf_rinc(m,AT_WR_OFFSET); ! 389: gbuf_wset(m,TOTAL_ATP_HDR_SIZE); ! 390: ddp = AT_DDP_HDR(m); ! 391: ddp->type = DDP_ATP; ! 392: UAS_ASSIGN(ddp->checksum, 0); ! 393: ddp->dst_socket = trp->tr_socket.socket; ! 394: ddp->dst_node = trp->tr_socket.node; ! 395: NET_ASSIGN(ddp->dst_net, trp->tr_socket.net); ! 396: ddp->src_node = trp->tr_local_node; ! 397: NET_NET(ddp->src_net, trp->tr_local_net); ! 398: ! 399: /* ! 400: * clear the cmd/xo/eom/sts/unused fields ! 401: */ ! 402: athp = AT_ATP_HDR(m); ! 403: ATP_CLEAR_CONTROL(athp); ! 404: athp->cmd = ATP_CMD_TREL; ! 405: UAS_ASSIGN(athp->tid, trp->tr_tid); ! 406: } ! 407: ! 408: return (m); ! 409: } ! 410: ! 411: void atp_send_replies(atp, rcbp) ! 412: register struct atp_state *atp; ! 413: register struct atp_rcb *rcbp; ! 414: { register gbuf_t *m; ! 415: register int i, len; ! 416: int s_gen, s, cnt; ! 417: unsigned char *m0_rptr = NULL, *m0_wptr = NULL; ! 418: register at_atp_t *athp; ! 419: register struct atpBDS *bdsp; ! 420: register gbuf_t *m2, *m1, *m0; ! 421: gbuf_t *mprev, *mlist = 0; ! 422: at_socket src_socket = (at_socket)atp->atp_socket_no; ! 423: gbuf_t *rc_xmt[ATP_TRESP_MAX]; ! 424: struct ddp_atp { ! 425: char ddp_atp_hdr[TOTAL_ATP_HDR_SIZE]; ! 426: }; ! 427: ! 428: ATDISABLE(s, atp->atp_lock); ! 429: if (rcbp->rc_queue != atp) { ! 430: ATENABLE(s, atp->atp_lock); ! 431: return; ! 432: } ! 433: if (rcbp->rc_not_sent_bitmap == 0) ! 434: goto nothing_to_send; ! 435: ! 436: dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ("atp_send_replies\n")); ! 437: /* ! 438: * Do this for each message that hasn't been sent ! 439: */ ! 440: cnt = rcbp->rc_pktcnt; ! 441: for (i = 0; i < cnt; i++) { ! 442: rc_xmt[i] = 0; ! 443: if (rcbp->rc_snd[i]) { ! 444: if ((rc_xmt[i] = gbuf_alloc(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,PRI_MED)) == NULL) { ! 445: for (cnt = 0; cnt < i; cnt++) ! 446: if (rc_xmt[cnt]) ! 447: gbuf_freeb(rc_xmt[cnt]); ! 448: goto nothing_to_send; ! 449: } ! 450: } ! 451: } ! 452: ! 453: m = rcbp->rc_xmt; ! 454: m0 = gbuf_cont(m); ! 455: if (m0) { ! 456: m0_rptr = gbuf_rptr(m0); ! 457: m0_wptr = gbuf_wptr(m0); ! 458: } ! 459: if (gbuf_len(m) > TOTAL_ATP_HDR_SIZE) ! 460: bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data); ! 461: else ! 462: bdsp = 0; ! 463: ! 464: for (i = 0; i < cnt; i++) { ! 465: if (rcbp->rc_snd[i] == 0) { ! 466: if ((len = UAS_VALUE(bdsp->bdsBuffSz))) ! 467: gbuf_rinc(m0,len); ! 468: ! 469: } else { ! 470: m2 = rc_xmt[i]; ! 471: gbuf_rinc(m2,AT_WR_OFFSET); ! 472: gbuf_wset(m2,TOTAL_ATP_HDR_SIZE); ! 473: *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m)); ! 474: athp = AT_ATP_HDR(m2); ! 475: ATP_CLEAR_CONTROL(athp); ! 476: athp->cmd = ATP_CMD_TRESP; ! 477: athp->bitmap = i; ! 478: if (i == (cnt - 1)) ! 479: athp->eom = 1; /* for the last fragment */ ! 480: if (bdsp) ! 481: UAL_UAL(athp->user_bytes, bdsp->bdsUserData); ! 482: ! 483: if (bdsp) ! 484: if (len = UAS_VALUE(bdsp->bdsBuffSz)) { /* copy in data */ ! 485: if (m0 && gbuf_len(m0)) { ! 486: if ((m1 = gbuf_dupb(m0)) == NULL) { ! 487: for (i = 0; i < cnt; i++) ! 488: if (rc_xmt[i]) ! 489: gbuf_freem(rc_xmt[i]); ! 490: gbuf_rptr(m0) = m0_rptr; ! 491: gbuf_wset(m0,(m0_wptr-m0_rptr)); ! 492: goto nothing_to_send; ! 493: } ! 494: gbuf_wset(m1,len); ! 495: gbuf_rinc(m0,len); ! 496: if ((len = gbuf_len(m0)) < 0) { ! 497: gbuf_rdec(m0,len); ! 498: gbuf_wdec(m1,len); ! 499: if (NULL == (gbuf_cont(m1) = gbuf_dupb(gbuf_cont(m0)))) { ! 500: for (i = 0; i < cnt; i++) ! 501: if (rc_xmt[i]) ! 502: gbuf_freem(rc_xmt[i]); ! 503: gbuf_rptr(m0) = m0_rptr; ! 504: gbuf_wset(m0,(m0_wptr-m0_rptr)); ! 505: goto nothing_to_send; ! 506: } ! 507: } else ! 508: gbuf_cont(m1) = 0; ! 509: gbuf_cont(m2) = m1; ! 510: } ! 511: } ! 512: ! 513: AT_DDP_HDR(m2)->src_socket = src_socket; ! 514: dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ! 515: ("atp_send_replies: %d, socket=%d, size=%d\n", ! 516: i, atp->atp_socket_no, gbuf_msgsize(gbuf_cont(m2)))); ! 517: ! 518: if (mlist) ! 519: gbuf_next(mprev) = m2; ! 520: else ! 521: mlist = m2; ! 522: mprev = m2; ! 523: ! 524: rcbp->rc_snd[i] = 0; ! 525: rcbp->rc_not_sent_bitmap &= ~atp_mask[i]; ! 526: if (rcbp->rc_not_sent_bitmap == 0) ! 527: break; ! 528: } ! 529: /* ! 530: * on to the next frag ! 531: */ ! 532: bdsp++; ! 533: } ! 534: if (m0) { ! 535: gbuf_rptr(m0) = m0_rptr; ! 536: gbuf_wset(m0,(m0_wptr-m0_rptr)); ! 537: } ! 538: ! 539: if (mlist) { ! 540: ATENABLE(s, atp->atp_lock); ! 541: DDP_OUTPUT(mlist); ! 542: ATDISABLE(s, atp->atp_lock); ! 543: } ! 544: ! 545: nothing_to_send: ! 546: /* ! 547: * If all replies from this reply block have been sent then ! 548: * remove it from the queue and mark it so ! 549: */ ! 550: if (rcbp->rc_queue != atp) { ! 551: ATENABLE(s, atp->atp_lock); ! 552: return; ! 553: } ! 554: rcbp->rc_rep_waiting = 0; ! 555: ! 556: /* ! 557: * If we are doing execute once re-set the rcb timeout ! 558: * each time we send back any part of the response. Note ! 559: * that this timer is started when an initial request is ! 560: * received. Each response reprimes the timer. Duplicate ! 561: * requests do not reprime the timer. ! 562: * ! 563: * We have sent all of a response so free the ! 564: * resources. ! 565: */ ! 566: if (rcbp->rc_xo && rcbp->rc_state != RCB_RELEASED) { ! 567: ATDISABLE(s_gen, atpgen_lock); ! 568: if (rcbp->rc_timestamp == 0) { ! 569: rcbp->rc_timestamp = time.tv_sec; ! 570: if (rcbp->rc_timestamp == 0) ! 571: rcbp->rc_timestamp = 1; ! 572: ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist); ! 573: } ! 574: rcbp->rc_state = RCB_RESPONSE_FULL; ! 575: ATENABLE(s_gen, atpgen_lock); ! 576: } else ! 577: atp_rcb_free(rcbp); ! 578: ATENABLE(s, atp->atp_lock); ! 579: } /* atp_send_replies */ ! 580: ! 581: ! 582: static void ! 583: atp_pack_bdsp(trp, bdsp) ! 584: register struct atp_trans *trp; ! 585: register struct atpBDS *bdsp; ! 586: { ! 587: register gbuf_t *m = NULL; ! 588: register int i, datsize = 0; ! 589: struct atpBDS *bdsbase = bdsp; ! 590: ! 591: dPrintf(D_M_ATP, D_L_INFO, ("atp_pack_bdsp: socket=%d\n", ! 592: trp->tr_queue->atp_socket_no)); ! 593: ! 594: for (i = 0; i < ATP_TRESP_MAX; i++, bdsp++) { ! 595: short bufsize = UAS_VALUE(bdsp->bdsBuffSz); ! 596: long bufaddr = UAL_VALUE(bdsp->bdsBuffAddr); ! 597: ! 598: if ((m = trp->tr_rcv[i]) == NULL) ! 599: break; ! 600: ! 601: /* discard ddp hdr on first packet */ ! 602: if (i == 0) ! 603: gbuf_rinc(m,DDP_X_HDR_SIZE); ! 604: ! 605: /* this field may contain control information even when ! 606: no data is present */ ! 607: UAL_UAL(bdsp->bdsUserData, ! 608: (((at_atp_t *)(gbuf_rptr(m)))->user_bytes)); ! 609: gbuf_rinc(m, ATP_HDR_SIZE); ! 610: ! 611: if ((bufsize != 0) && (bufaddr != 0)) { ! 612: /* user expects data back */ ! 613: short tmp = 0; ! 614: register char *buf = (char *)bufaddr; ! 615: ! 616: while (m) { ! 617: short len = (short)(gbuf_len(m)); ! 618: if (len) { ! 619: if (len > bufsize) ! 620: len = bufsize; ! 621: copyout((caddr_t)gbuf_rptr(m), ! 622: (caddr_t)&buf[tmp], ! 623: len); ! 624: bufsize -= len; ! 625: tmp =+ len; ! 626: } ! 627: m = gbuf_cont(m); ! 628: } ! 629: ! 630: UAS_ASSIGN(bdsp->bdsDataSz, tmp); ! 631: datsize += (int)tmp; ! 632: } ! 633: gbuf_freem(trp->tr_rcv[i]); ! 634: trp->tr_rcv[i] = NULL; ! 635: } ! 636: ! 637: /* report the number of packets */ ! 638: UAS_ASSIGN(((struct atpBDS *)bdsbase)->bdsBuffSz, i); ! 639: ! 640: dPrintf(D_M_ATP, D_L_INFO, (" : size=%d\n", ! 641: datsize)); ! 642: } /* atp_pack_bdsp */ ! 643: ! 644: ! 645: static int ! 646: atp_unpack_bdsp(atp, m, rcbp, cnt, wait) ! 647: struct atp_state *atp; ! 648: gbuf_t *m; /* ddp, atp and bdsp gbuf_t */ ! 649: register struct atp_rcb *rcbp; ! 650: register int cnt, wait; ! 651: { ! 652: register struct atpBDS *bdsp; ! 653: register gbuf_t *m2, *m1, *m0; ! 654: register at_atp_t *athp; ! 655: register int i, len, s_gen; ! 656: at_socket src_socket; ! 657: struct ddp_atp { ! 658: char ddp_atp_hdr[TOTAL_ATP_HDR_SIZE]; ! 659: }; ! 660: gbuf_t *mprev, *mlist = 0; ! 661: gbuf_t *rc_xmt[ATP_TRESP_MAX]; ! 662: unsigned char *m0_rptr, *m0_wptr; ! 663: ! 664: /* ! 665: * get the user data structure pointer ! 666: */ ! 667: bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data); ! 668: ! 669: /* ! 670: * Guard against bogus count argument. ! 671: */ ! 672: if ((unsigned) cnt > ATP_TRESP_MAX) { ! 673: dPrintf(D_M_ATP, D_L_ERROR, ! 674: ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt)); ! 675: gbuf_freem(m); ! 676: return(EINVAL); ! 677: } ! 678: if ((src_socket = (at_socket)atp->atp_socket_no) == 0xFF) { ! 679: /* comparison was to -1, however src_socket is a u_char */ ! 680: gbuf_freem(m); ! 681: return EPIPE; ! 682: } ! 683: ! 684: m0 = gbuf_cont(m); ! 685: rcbp->rc_xmt = m; ! 686: rcbp->rc_pktcnt = cnt; ! 687: rcbp->rc_state = RCB_SENDING; ! 688: rcbp->rc_not_sent_bitmap = 0; ! 689: ! 690: if (cnt <= 1) { ! 691: /* ! 692: * special case this to ! 693: * improve AFP write transactions to the server ! 694: */ ! 695: rcbp->rc_pktcnt = 1; ! 696: if ((m2 = gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE, ! 697: wait)) == NULL) ! 698: return 0; ! 699: gbuf_rinc(m2,AT_WR_OFFSET); ! 700: gbuf_wset(m2,TOTAL_ATP_HDR_SIZE); ! 701: *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m)); ! 702: athp = AT_ATP_HDR(m2); ! 703: ATP_CLEAR_CONTROL(athp); ! 704: athp->cmd = ATP_CMD_TRESP; ! 705: athp->bitmap = 0; ! 706: athp->eom = 1; /* there's only 1 fragment */ ! 707: ! 708: /* *** why only if cnt > 0? *** */ ! 709: if (cnt > 0) ! 710: UAL_UAL(athp->user_bytes, bdsp->bdsUserData); ! 711: if (m0) ! 712: if ((gbuf_cont(m2) = gbuf_dupb_wait(m0, wait)) == NULL) { ! 713: gbuf_freeb(m2); ! 714: return 0; ! 715: } ! 716: /* ! 717: * send the message and mark it as sent ! 718: */ ! 719: AT_DDP_HDR(m2)->src_socket = src_socket; ! 720: dPrintf(D_M_ATP_LOW, D_L_INFO, ! 721: ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n", ! 722: 0,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(m2)),cnt)); ! 723: mlist = m2; ! 724: goto l_send; ! 725: } ! 726: ! 727: for (i = 0; i < cnt; i++) { ! 728: /* all hdrs, packet data and dst addr storage */ ! 729: if ((rc_xmt[i] = ! 730: gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE, ! 731: wait)) == NULL) { ! 732: for (cnt = 0; cnt < i; cnt++) ! 733: if (rc_xmt[cnt]) ! 734: gbuf_freeb(rc_xmt[cnt]); ! 735: return 0; ! 736: } ! 737: } ! 738: ! 739: if (m0) { ! 740: m0_rptr = gbuf_rptr(m0); ! 741: m0_wptr = gbuf_wptr(m0); ! 742: } ! 743: ! 744: for (i = 0; i < cnt; i++) { ! 745: m2 = rc_xmt[i]; ! 746: gbuf_rinc(m2,AT_WR_OFFSET); ! 747: gbuf_wset(m2,TOTAL_ATP_HDR_SIZE); ! 748: *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m)); ! 749: athp = AT_ATP_HDR(m2); ! 750: ATP_CLEAR_CONTROL(athp); ! 751: athp->cmd = ATP_CMD_TRESP; ! 752: athp->bitmap = i; ! 753: if (i == (cnt - 1)) ! 754: athp->eom = 1; /* for the last fragment */ ! 755: UAL_UAL(athp->user_bytes, bdsp->bdsUserData); ! 756: ! 757: if ((len = UAS_VALUE(bdsp->bdsBuffSz))) { /* copy in data */ ! 758: if (m0 && gbuf_len(m0)) { ! 759: if ((m1 = gbuf_dupb_wait(m0, wait)) == NULL) { ! 760: for (i = 0; i < cnt; i++) ! 761: if (rc_xmt[i]) ! 762: gbuf_freem(rc_xmt[i]); ! 763: gbuf_rptr(m0) = m0_rptr; ! 764: gbuf_wset(m0,(m0_wptr-m0_rptr)); ! 765: return 0; ! 766: } ! 767: gbuf_wset(m1,len); ! 768: gbuf_rinc(m0,len); ! 769: if ((len = gbuf_len(m0)) < 0) { ! 770: gbuf_rdec(m0,len); ! 771: gbuf_wdec(m1,len); ! 772: if ((gbuf_cont(m1) = gbuf_dupb_wait(gbuf_cont(m0), wait)) == NULL) { ! 773: for (i = 0; i < cnt; i++) ! 774: if (rc_xmt[i]) ! 775: gbuf_freem(rc_xmt[i]); ! 776: gbuf_rptr(m0) = m0_rptr; ! 777: gbuf_wset(m0,(m0_wptr-m0_rptr)); ! 778: return 0; ! 779: } ! 780: } else ! 781: gbuf_cont(m1) = 0; ! 782: gbuf_cont(m2) = m1; ! 783: } ! 784: } ! 785: ! 786: AT_DDP_HDR(m2)->src_socket = src_socket; ! 787: dPrintf(D_M_ATP_LOW,D_L_INFO, ! 788: ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n", ! 789: i,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(m2)),cnt)); ! 790: if (mlist) ! 791: gbuf_next(mprev) = m2; ! 792: else ! 793: mlist = m2; ! 794: mprev = m2; ! 795: /* ! 796: * on to the next frag ! 797: */ ! 798: bdsp++; ! 799: } ! 800: if (m0) { ! 801: gbuf_rptr(m0) = m0_rptr; ! 802: gbuf_wset(m0,(m0_wptr-m0_rptr)); ! 803: } ! 804: /* ! 805: * send the message ! 806: */ ! 807: l_send: ! 808: if (rcbp->rc_xo) { ! 809: ATDISABLE(s_gen, atpgen_lock); ! 810: if (rcbp->rc_timestamp == 0) { ! 811: if ((rcbp->rc_timestamp = time.tv_sec) == 0) ! 812: rcbp->rc_timestamp = 1; ! 813: ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist); ! 814: } ! 815: ATENABLE(s_gen, atpgen_lock); ! 816: } ! 817: ! 818: DDP_OUTPUT(mlist); ! 819: return 0; ! 820: } /* atp_unpack_bdsp */ ! 821: ! 822: #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6) ! 823: #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC-64) ! 824: static unsigned int sNext = 0; ! 825: ! 826: int atp_bind(gref, sVal, flag) ! 827: gref_t *gref; ! 828: unsigned int sVal; ! 829: unsigned char *flag; ! 830: { ! 831: extern unsigned char asp_inpC[]; ! 832: extern asp_scb_t *asp_scbQ[]; ! 833: unsigned char inpC, sNextUsed = 0; ! 834: unsigned int sMin, sMax, sSav; ! 835: struct atp_state *atp; ! 836: int s; ! 837: ! 838: atp = (struct atp_state *)gref->info; ! 839: if (atp->dflag) ! 840: atp = (struct atp_state *)atp->atp_msgq; ! 841: ! 842: sMax = ATP_SOCKET_LAST; ! 843: sMin = ATP_SOCKET_FIRST; ! 844: ATDISABLE(s, atpgen_lock); ! 845: if (flag && (*flag == 3)) { ! 846: sMin += 40; ! 847: if (sMin < sNext) { ! 848: sMin = sNext; ! 849: sNextUsed = 1; ! 850: } ! 851: } ! 852: ! 853: if ( (sVal != 0) ! 854: && ((sVal > sMax) || (sVal < 2) || (sVal == 6) ! 855: || ((atp_inputQ[sVal] != NULL) && ! 856: (atp_inputQ[sVal] != (gref_t *)1)) ! 857: || (ot_atp_socketM[sVal] != 0)) ) ! 858: { ! 859: ATENABLE(s, atpgen_lock); ! 860: return 0; ! 861: } ! 862: ! 863: if (sVal == 0) { ! 864: inpC = 255; ! 865: again: ! 866: for (sVal=sMin; sVal <= sMax; sVal++) { ! 867: if (ot_atp_socketM[sVal] == 0) { ! 868: if (atp_inputQ[sVal] == NULL || ! 869: atp_inputQ[sVal] == (gref_t *)1) ! 870: break; ! 871: else if (flag && (*flag == 3)) { ! 872: if ((asp_scbQ[sVal]->dflag == *flag) ! 873: && (asp_inpC[sVal] < inpC) ) { ! 874: inpC = asp_inpC[sVal]; ! 875: sSav = sVal; ! 876: } ! 877: } ! 878: } ! 879: } ! 880: if (sVal > sMax) { ! 881: if (flag && (*flag == 3)) { ! 882: if (sNextUsed) { ! 883: sNextUsed = 0; ! 884: sMax = sNext - 1; ! 885: sMin = ATP_SOCKET_FIRST+40; ! 886: goto again; ! 887: } ! 888: sNext = 0; ! 889: *flag = (unsigned char)sSav; ! 890: } ! 891: ATENABLE(s, atpgen_lock); ! 892: return 0; ! 893: } ! 894: } ! 895: atp->atp_socket_no = (short)sVal; ! 896: atp_inputQ[sVal] = gref; ! 897: if (flag == 0) ! 898: atp_pidM[sVal] = atp->atp_pid; ! 899: else if (*flag == 3) { ! 900: sNext = sVal + 1; ! 901: if (sNext > ATP_SOCKET_LAST) ! 902: sNext = 0; ! 903: } ! 904: ! 905: ATENABLE(s, atpgen_lock); ! 906: return (int)sVal; ! 907: } ! 908: ! 909: void atp_req_ind(atp, mioc) ! 910: register struct atp_state *atp; ! 911: register gbuf_t *mioc; ! 912: { ! 913: register struct atp_rcb *rcbp; ! 914: int s; ! 915: ! 916: if ((rcbp = atp->atp_attached.head) != 0) { ! 917: gbuf_cont(mioc) = rcbp->rc_ioctl; ! 918: rcbp->rc_ioctl = NULL; ! 919: ATDISABLE(s, atp->atp_lock); ! 920: if (rcbp->rc_xo) { ! 921: ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list); ! 922: rcbp->rc_state = RCB_NOTIFIED; ! 923: ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list); ! 924: } else ! 925: atp_rcb_free(rcbp); ! 926: ATENABLE(s, atp->atp_lock); ! 927: if (gbuf_cont(mioc)) ! 928: ((ioc_t *)gbuf_rptr(mioc))->ioc_count = gbuf_msgsize(gbuf_cont(mioc)); ! 929: else ! 930: ((ioc_t *)gbuf_rptr(mioc))->ioc_count = 0; ! 931: asp_ack_reply(atp->atp_gref, mioc); ! 932: } else ! 933: gbuf_freeb(mioc); ! 934: } ! 935: ! 936: void atp_rsp_ind(trp, mioc) ! 937: register struct atp_trans *trp; ! 938: register gbuf_t *mioc; ! 939: { ! 940: register struct atp_state *atp = trp->tr_queue; ! 941: register int err; ! 942: gbuf_t *xm = 0; ! 943: ! 944: err = 0; ! 945: { ! 946: switch (trp->tr_state) { ! 947: case TRANS_DONE: ! 948: if (asp_pack_bdsp(trp, &xm) < 0) ! 949: err = EFAULT; ! 950: gbuf_cont(mioc) = trp->tr_xmt; ! 951: trp->tr_xmt = NULL; ! 952: break; ! 953: ! 954: case TRANS_FAILED: ! 955: err = ETIMEDOUT; ! 956: break; ! 957: ! 958: default: ! 959: err = ENOENT; ! 960: break; ! 961: } ! 962: atp_free(trp); ! 963: ! 964: if (err) { ! 965: dPrintf(D_M_ATP, D_L_ERROR, ! 966: ("atp_rsp_ind: TRANSACTION error\n")); ! 967: atp_iocnak(atp, mioc, err); ! 968: } else { ! 969: gbuf_cont(gbuf_cont(mioc)) = xm; ! 970: atp_iocack(atp, mioc); ! 971: } ! 972: } ! 973: } ! 974: ! 975: void atp_cancel_req(gref, tid) ! 976: gref_t *gref; ! 977: unsigned short tid; ! 978: { ! 979: int s; ! 980: struct atp_state *atp; ! 981: struct atp_trans *trp; ! 982: ! 983: atp = (struct atp_state *)gref->info; ! 984: if (atp->dflag) ! 985: atp = (struct atp_state *)atp->atp_msgq; ! 986: ! 987: ATDISABLE(s, atp->atp_lock); ! 988: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) { ! 989: if (trp->tr_tid == tid) ! 990: break; ! 991: } ! 992: ATENABLE(s, atp->atp_lock); ! 993: if (trp != NULL) ! 994: atp_free(trp); ! 995: } ! 996: ! 997: /* ! 998: * stop ATP now ! 999: */ ! 1000: void ! 1001: atp_stop(m, flag) ! 1002: gbuf_t *m; ! 1003: int flag; ! 1004: { ! 1005: struct atp_trans *trp; ! 1006: int k, s, *x_wptr; ! 1007: struct atp_state *atp; ! 1008: gref_t *gref; ! 1009: ! 1010: gbuf_rptr(m)[1]++; ! 1011: ! 1012: if (flag) ! 1013: atp_off_flag = 1; ! 1014: ! 1015: asp_stop(m, flag); ! 1016: ATDISABLE(s, atpall_lock); ! 1017: ! 1018: x_wptr = (int *)gbuf_wptr(m); ! 1019: for (atp = atp_used_list; atp; atp = atp->atp_trans_waiting) { ! 1020: if (flag == 2) { ! 1021: atp->atp_flags |= ATP_CLOSING; ! 1022: } else { ! 1023: *(int *)gbuf_wptr(m) = atp->atp_pid; ! 1024: gbuf_winc(m,sizeof(int)); ! 1025: } ! 1026: } ! 1027: ! 1028: for (k=0; k < 256; k++) { ! 1029: if (((gref = atp_inputQ[k]) == 0) || gref == (gref_t *)1) ! 1030: continue; ! 1031: atp = (struct atp_state *)gref->info; ! 1032: if (atp->dflag) ! 1033: continue; ! 1034: if (flag == 2) { ! 1035: atp->atp_flags |= ATP_CLOSING; ! 1036: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) { ! 1037: if (trp->tr_rsp_wait) { ! 1038: trp->tr_state = TRANS_FAILED; ! 1039: thread_wakeup(&trp->tr_event); ! 1040: } ! 1041: } ! 1042: } else { ! 1043: *(int *)gbuf_wptr(m) = atp->atp_pid; ! 1044: gbuf_winc(m,sizeof(int)); ! 1045: } ! 1046: } ! 1047: ATENABLE(s, atpall_lock); ! 1048: ! 1049: while (x_wptr != (int *)gbuf_wptr(m)) { ! 1050: dPrintf(D_M_ATP, D_L_TRACE, ("atp_stop: pid=%d\n", *x_wptr)); ! 1051: x_wptr++; ! 1052: } ! 1053: } ! 1054: ! 1055: /* ! 1056: * remove atp from the use list ! 1057: */ ! 1058: void ! 1059: atp_dequeue_atp(atp) ! 1060: struct atp_state *atp; ! 1061: { ! 1062: int s; ! 1063: ! 1064: ATDISABLE(s, atpall_lock); ! 1065: if (atp == atp_used_list) { ! 1066: if ((atp_used_list = atp->atp_trans_waiting) != 0) ! 1067: atp->atp_trans_waiting->atp_rcb_waiting = 0; ! 1068: } else if (atp->atp_rcb_waiting) { ! 1069: if ((atp->atp_rcb_waiting->atp_trans_waiting ! 1070: = atp->atp_trans_waiting) != 0) ! 1071: atp->atp_trans_waiting->atp_rcb_waiting = atp->atp_rcb_waiting; ! 1072: } ! 1073: ! 1074: atp->atp_trans_waiting = 0; ! 1075: atp->atp_rcb_waiting = 0; ! 1076: ATENABLE(s, atpall_lock); ! 1077: } ! 1078: ! 1079: void ! 1080: atp_timout(func, trp, ticks) ! 1081: void (*func)(); ! 1082: struct atp_trans *trp; ! 1083: int ticks; ! 1084: { ! 1085: int s; ! 1086: unsigned int sum; ! 1087: struct atp_trans *curr_trp, *prev_trp; ! 1088: ! 1089: ATDISABLE(s, atptmo_lock); ! 1090: if (trp->tr_tmo_func) { ! 1091: ATENABLE(s, atptmo_lock); ! 1092: return; ! 1093: } ! 1094: ! 1095: trp->tr_tmo_func = func; ! 1096: trp->tr_tmo_delta = 1+(ticks>>5); ! 1097: ! 1098: if (trp_tmo_list == 0) { ! 1099: trp->tr_tmo_next = trp->tr_tmo_prev = 0; ! 1100: trp_tmo_list = trp; ! 1101: ATENABLE(s, atptmo_lock); ! 1102: return; ! 1103: } ! 1104: ! 1105: prev_trp = 0; ! 1106: curr_trp = trp_tmo_list; ! 1107: sum = 0; ! 1108: ! 1109: while (1) { ! 1110: sum += curr_trp->tr_tmo_delta; ! 1111: if (sum > trp->tr_tmo_delta) { ! 1112: sum -= curr_trp->tr_tmo_delta; ! 1113: trp->tr_tmo_delta -= sum; ! 1114: curr_trp->tr_tmo_delta -= trp->tr_tmo_delta; ! 1115: break; ! 1116: } ! 1117: prev_trp = curr_trp; ! 1118: if ((curr_trp = curr_trp->tr_tmo_next) == 0) { ! 1119: trp->tr_tmo_delta -= sum; ! 1120: break; ! 1121: } ! 1122: } ! 1123: ! 1124: if (prev_trp) { ! 1125: trp->tr_tmo_prev = prev_trp; ! 1126: if ((trp->tr_tmo_next = prev_trp->tr_tmo_next) != 0) ! 1127: prev_trp->tr_tmo_next->tr_tmo_prev = trp; ! 1128: prev_trp->tr_tmo_next = trp; ! 1129: } else { ! 1130: trp->tr_tmo_prev = 0; ! 1131: trp->tr_tmo_next = trp_tmo_list; ! 1132: trp_tmo_list->tr_tmo_prev = trp; ! 1133: trp_tmo_list = trp; ! 1134: } ! 1135: ATENABLE(s, atptmo_lock); ! 1136: } ! 1137: ! 1138: void ! 1139: atp_untimout(func, trp) ! 1140: void (*func)(); ! 1141: struct atp_trans *trp; ! 1142: { ! 1143: int s; ! 1144: ! 1145: ATDISABLE(s, atptmo_lock); ! 1146: if (trp->tr_tmo_func == 0) { ! 1147: ATENABLE(s, atptmo_lock); ! 1148: return; ! 1149: } ! 1150: ! 1151: if (trp_tmo_list == trp) { ! 1152: if ((trp_tmo_list = trp->tr_tmo_next) != 0) { ! 1153: trp_tmo_list->tr_tmo_prev = 0; ! 1154: trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta; ! 1155: } ! 1156: } else { ! 1157: if ((trp->tr_tmo_prev->tr_tmo_next = trp->tr_tmo_next) != 0) { ! 1158: trp->tr_tmo_next->tr_tmo_prev = trp->tr_tmo_prev; ! 1159: trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta; ! 1160: } ! 1161: } ! 1162: trp->tr_tmo_func = 0; ! 1163: ATENABLE(s, atptmo_lock); ! 1164: } ! 1165: ! 1166: static void *trp_clock_tmo = 0; ! 1167: ! 1168: void ! 1169: atp_trp_clock(arg) ! 1170: void *arg; ! 1171: { ! 1172: if (!atp_off_flag) ! 1173: atp_trp_timer(arg, 0); ! 1174: } ! 1175: ! 1176: void ! 1177: atp_trp_timer(arg, flag) ! 1178: void *arg; ! 1179: int flag; ! 1180: { ! 1181: int s; ! 1182: struct atp_trans *trp; ! 1183: void (*tr_tmo_func)(); ! 1184: ! 1185: if (atp_off_flag) ! 1186: return; ! 1187: if (flag) { ! 1188: atp_off_flag = 1; ! 1189: atalk_untimeout(atp_trp_clock, (void *)arg, trp_clock_tmo); ! 1190: trp_clock_tmo = 0; ! 1191: return; ! 1192: } ! 1193: ! 1194: ATDISABLE(s, atptmo_lock); ! 1195: if (trp_tmo_list) ! 1196: trp_tmo_list->tr_tmo_delta--; ! 1197: while (((trp = trp_tmo_list) != 0) && (trp_tmo_list->tr_tmo_delta == 0)) { ! 1198: if ((trp_tmo_list = trp->tr_tmo_next) != 0) ! 1199: trp_tmo_list->tr_tmo_prev = 0; ! 1200: if ((tr_tmo_func = trp->tr_tmo_func) != 0) { ! 1201: trp->tr_tmo_func = 0; ! 1202: ATENABLE(s, atptmo_lock); ! 1203: (*tr_tmo_func)(trp); ! 1204: ATDISABLE(s, atptmo_lock); ! 1205: } ! 1206: } ! 1207: ATENABLE(s, atptmo_lock); ! 1208: ! 1209: trp_clock_tmo = (void *)atalk_timeout(atp_trp_clock, (void *)arg, (1<<5)); ! 1210: } ! 1211: ! 1212: void ! 1213: atp_send_req(gref, mioc) ! 1214: gref_t *gref; ! 1215: gbuf_t *mioc; ! 1216: { ! 1217: register struct atp_state *atp; ! 1218: register struct atp_trans *trp; ! 1219: register ioc_t *iocbp; ! 1220: register at_atp_t *athp; ! 1221: register at_ddp_t *ddp; ! 1222: gbuf_t *m, *m2, *bds; ! 1223: struct atp_set_default *sdb; ! 1224: int s, old; ! 1225: unsigned int timer; ! 1226: ! 1227: atp = (struct atp_state *)((struct atp_state *)gref->info)->atp_msgq; ! 1228: iocbp = (ioc_t *)gbuf_rptr(mioc); ! 1229: ! 1230: if ((trp = atp_trans_alloc(atp)) == NULL) { ! 1231: l_retry: ! 1232: ((asp_scb_t *)gref->info)->stat_msg = mioc; ! 1233: iocbp->ioc_private = (void *)gref; ! 1234: atalk_timeout(atp_retry_req, mioc, 10); ! 1235: return; ! 1236: } ! 1237: ! 1238: { ! 1239: m2 = gbuf_cont(mioc); ! 1240: ! 1241: if ((bds = gbuf_dupb(m2)) == NULL) { ! 1242: atp_trans_free(trp); ! 1243: goto l_retry; ! 1244: } ! 1245: gbuf_rinc(m2,atpBDSsize); ! 1246: gbuf_wset(bds,atpBDSsize); ! 1247: iocbp->ioc_count -= atpBDSsize; ! 1248: gbuf_cont(m2) = NULL; ! 1249: } ! 1250: ! 1251: old = iocbp->ioc_cmd; ! 1252: iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST; ! 1253: sdb = (struct atp_set_default *)gbuf_rptr(m2); ! 1254: ! 1255: /* ! 1256: * The at_snd_req library routine multiplies seconds by 100. ! 1257: * We need to divide by 100 in order to obtain the timer. ! 1258: */ ! 1259: if ((timer = (sdb->def_rate * HZ)/100) == 0) ! 1260: timer = HZ; ! 1261: iocbp->ioc_count -= sizeof(struct atp_set_default); ! 1262: gbuf_rinc(m2,sizeof(struct atp_set_default)); ! 1263: ! 1264: trp->tr_retry = sdb->def_retries; ! 1265: trp->tr_timeout = timer; ! 1266: trp->tr_bdsp = bds; ! 1267: trp->tr_tid = atp_tid(atp); ! 1268: trp->tr_xmt = mioc; ! 1269: ! 1270: /* ! 1271: * Now fill in the header (and remember the bits ! 1272: * we need to know) ! 1273: */ ! 1274: athp = AT_ATP_HDR(m2); ! 1275: athp->cmd = ATP_CMD_TREQ; ! 1276: UAS_ASSIGN(athp->tid, trp->tr_tid); ! 1277: athp->eom = 0; ! 1278: athp->sts = 0; ! 1279: trp->tr_xo = athp->xo; ! 1280: trp->tr_bitmap = athp->bitmap; ! 1281: ddp = AT_DDP_HDR(m2); ! 1282: ddp->type = DDP_ATP; ! 1283: ddp->src_socket = (at_socket)atp->atp_socket_no; ! 1284: trp->tr_socket.socket = ddp->dst_socket; ! 1285: trp->tr_socket.node = ddp->dst_node; ! 1286: trp->tr_socket.net = NET_VALUE(ddp->dst_net); ! 1287: trp->tr_local_socket = atp->atp_socket_no; ! 1288: trp->tr_local_node = ddp->src_node; ! 1289: NET_NET(trp->tr_local_net, ddp->src_net); ! 1290: /* ! 1291: * Put us in the transaction waiting queue ! 1292: */ ! 1293: ATDISABLE(s, atp->atp_lock); ! 1294: ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list); ! 1295: ATENABLE(s, atp->atp_lock); ! 1296: ! 1297: /* ! 1298: * Send the message and set the timer ! 1299: */ ! 1300: if ( !trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo) { ! 1301: m = (gbuf_t *)gbuf_copym(m2); ! 1302: atp_x_done(trp); /* no reason to tie up resources */ ! 1303: } else { ! 1304: m = (gbuf_t *)gbuf_dupm(m2); ! 1305: atp_timout(atp_req_timeout, trp, trp->tr_timeout); ! 1306: } ! 1307: if (m) ! 1308: DDP_OUTPUT(m); ! 1309: } ! 1310: ! 1311: void ! 1312: atp_retry_req(m) ! 1313: gbuf_t *m; ! 1314: { ! 1315: gref_t *gref; ! 1316: ! 1317: gref = (gref_t *)((ioc_t *)gbuf_rptr(m))->ioc_private; ! 1318: if (gref->info) { ! 1319: ((asp_scb_t *)gref->info)->stat_msg = 0; ! 1320: atp_send_req(gref, m); ! 1321: } ! 1322: } ! 1323: ! 1324: void ! 1325: atp_send_rsp(gref, m, wait) ! 1326: gref_t *gref; ! 1327: gbuf_t *m; ! 1328: int wait; ! 1329: { ! 1330: register struct atp_state *atp; ! 1331: register struct atp_rcb *rcbp; ! 1332: register at_atp_t *athp; ! 1333: register at_ddp_t *ddp; ! 1334: int s, xcnt; ! 1335: ! 1336: atp = (struct atp_state *)gref->info; ! 1337: if (atp->dflag) ! 1338: atp = (struct atp_state *)atp->atp_msgq; ! 1339: ddp = AT_DDP_HDR(m); ! 1340: athp = AT_ATP_HDR(m); ! 1341: ! 1342: /* ! 1343: * search for the corresponding rcb ! 1344: */ ! 1345: ATDISABLE(s, atp->atp_lock); ! 1346: for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) { ! 1347: if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) && ! 1348: (rcbp->rc_socket.node == ddp->dst_node) && ! 1349: (rcbp->rc_socket.net == NET_VALUE(ddp->dst_net)) && ! 1350: (rcbp->rc_socket.socket == ddp->dst_socket) ) ! 1351: break; ! 1352: } ! 1353: ! 1354: /* ! 1355: * If it has already been sent then drop the request ! 1356: */ ! 1357: if ((rcbp && (rcbp->rc_state != RCB_NOTIFIED)) || ! 1358: (rcbp == NULL && athp->xo) ) { ! 1359: ATENABLE(s, atp->atp_lock); ! 1360: gbuf_freem(m); ! 1361: return; ! 1362: } ! 1363: ATENABLE(s, atp->atp_lock); ! 1364: ! 1365: if (rcbp == NULL) { /* a response is being sent for an ALO transaction */ ! 1366: if ((rcbp = atp_rcb_alloc(atp)) == NULL) { ! 1367: gbuf_freem(m); ! 1368: return; ! 1369: } ! 1370: rcbp->rc_ioctl = 0; ! 1371: rcbp->rc_socket.socket = ddp->dst_socket; ! 1372: rcbp->rc_socket.node = ddp->dst_node; ! 1373: rcbp->rc_socket.net = NET_VALUE(ddp->dst_net); ! 1374: rcbp->rc_tid = UAS_VALUE(athp->tid); ! 1375: rcbp->rc_bitmap = 0xff; ! 1376: rcbp->rc_xo = 0; ! 1377: rcbp->rc_state = RCB_RESPONSE_FULL; ! 1378: ATDISABLE(s, atp->atp_lock); ! 1379: ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list); ! 1380: ATENABLE(s, atp->atp_lock); ! 1381: } ! 1382: else if (ddp->src_node == 0) { ! 1383: NET_NET(ddp->src_net, rcbp->rc_local_net); ! 1384: ddp->src_node = rcbp->rc_local_node; ! 1385: } ! 1386: ! 1387: /* first bds entry gives number of bds entries in total (hack) */ ! 1388: xcnt = (gbuf_len(m) > TOTAL_ATP_HDR_SIZE) ? ! 1389: UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz) : 0; ! 1390: s = atp_unpack_bdsp(atp, m, rcbp, xcnt, wait); ! 1391: if (s == 0) ! 1392: atp_send_replies(atp, rcbp); ! 1393: } /* atp_send_rsp */ ! 1394: ! 1395: int ! 1396: asp_pack_bdsp(trp, xm) ! 1397: register struct atp_trans *trp; ! 1398: gbuf_t **xm; ! 1399: { ! 1400: register struct atpBDS *bdsp; ! 1401: register gbuf_t *m, *m2; ! 1402: register int i; ! 1403: gbuf_t *m_prev, *m_head = 0; ! 1404: ! 1405: dPrintf(D_M_ATP, D_L_INFO, ("asp_pack_bdsp: socket=%d\n", ! 1406: trp->tr_queue->atp_socket_no)); ! 1407: ! 1408: if ((m2 = trp->tr_bdsp) == NULL) ! 1409: return 0; ! 1410: trp->tr_bdsp = NULL; ! 1411: bdsp = (struct atpBDS *)gbuf_rptr(m2); ! 1412: ! 1413: for (i = 0; (i < ATP_TRESP_MAX && ! 1414: bdsp < (struct atpBDS *)(gbuf_wptr(m2))); i++) { ! 1415: if ((m = trp->tr_rcv[i]) == NULL) ! 1416: break; ! 1417: if (i == 0) { ! 1418: /* discard ddp hdr on first packet */ ! 1419: gbuf_rinc(m,DDP_X_HDR_SIZE); ! 1420: } ! 1421: ! 1422: UAL_UAL(bdsp->bdsUserData, (((at_atp_t *)(gbuf_rptr(m)))->user_bytes)); ! 1423: gbuf_rinc(m, ATP_HDR_SIZE); ! 1424: ! 1425: if (UAL_VALUE(bdsp->bdsBuffAddr)) { ! 1426: /* user expects data back */ ! 1427: short tmp; ! 1428: gbuf_t *tmp_m; ! 1429: ! 1430: while (m && ((tmp = (short)(gbuf_len(m))) == 0)) { ! 1431: tmp_m = m; ! 1432: m = gbuf_cont(m); ! 1433: gbuf_freeb(tmp_m); ! 1434: } ! 1435: if (m_head == 0) ! 1436: m_head = m; ! 1437: else ! 1438: gbuf_cont(m_prev) = m; ! 1439: if (m) { ! 1440: while (gbuf_cont(m)) { ! 1441: m = gbuf_cont(m); ! 1442: tmp += (short)(gbuf_len(m)); ! 1443: } ! 1444: m_prev = m; ! 1445: } ! 1446: UAS_ASSIGN(bdsp->bdsDataSz, tmp); ! 1447: } ! 1448: trp->tr_rcv[i] = NULL; ! 1449: bdsp++; ! 1450: ! 1451: } ! 1452: /* ! 1453: * report the number of packets ! 1454: */ ! 1455: UAS_ASSIGN(((struct atpBDS *)gbuf_rptr(m2))->bdsBuffSz, i); ! 1456: ! 1457: if (trp->tr_xmt) /* an ioctl block is still held? */ ! 1458: gbuf_cont(trp->tr_xmt) = m2; ! 1459: else ! 1460: trp->tr_xmt = m2; ! 1461: ! 1462: if (m_head) ! 1463: *xm = m_head; ! 1464: else ! 1465: *xm = 0; ! 1466: ! 1467: dPrintf(D_M_ATP, D_L_INFO, (" : size=%d\n", ! 1468: gbuf_msgsize(*xm))); ! 1469: ! 1470: return 0; ! 1471: } ! 1472: ! 1473: /* ! 1474: * The following routines are direct entries from system ! 1475: * calls to allow fast sending and recving of ATP data. ! 1476: */ ! 1477: ! 1478: int ! 1479: _ATPsndreq(fd, buf, len, nowait, err, proc) ! 1480: int fd; ! 1481: unsigned char *buf; ! 1482: int len; ! 1483: int nowait; ! 1484: int *err; ! 1485: void *proc; ! 1486: { ! 1487: gref_t *gref; ! 1488: int s, rc; ! 1489: unsigned short tid; ! 1490: unsigned int timer; ! 1491: register struct atp_state *atp; ! 1492: register struct atp_trans *trp; ! 1493: register ioc_t *iocbp; ! 1494: register at_atp_t *athp; ! 1495: register at_ddp_t *ddp; ! 1496: struct atp_set_default *sdb; ! 1497: gbuf_t *m2, *m, *mioc; ! 1498: char bds[atpBDSsize]; ! 1499: ! 1500: if ((*err = atalk_getref(0, fd, &gref, proc)) != 0) ! 1501: return -1; ! 1502: ! 1503: if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0) ! 1504: || (atp->atp_flags & ATP_CLOSING)) { ! 1505: dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndreq: stale handle=0x%x, pid=%d\n", ! 1506: (u_int) gref, gref->pid)); ! 1507: ! 1508: *err = EINVAL; ! 1509: return -1; ! 1510: } ! 1511: ! 1512: while ((mioc = gbuf_alloc(sizeof(ioc_t), PRI_MED)) == 0) { ! 1513: ATDISABLE(s, atp->atp_delay_lock); ! 1514: rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atpmioc", 10); ! 1515: ATENABLE(s, atp->atp_delay_lock); ! 1516: if (rc != 0) { ! 1517: *err = rc; ! 1518: return -1; ! 1519: } ! 1520: ! 1521: } ! 1522: gbuf_wset(mioc,sizeof(ioc_t)); ! 1523: len -= atpBDSsize; ! 1524: while ((m2 = gbuf_alloc(len, PRI_MED)) == 0) { ! 1525: ATDISABLE(s, atp->atp_delay_lock); ! 1526: rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atpm2", 10); ! 1527: ATENABLE(s, atp->atp_delay_lock); ! 1528: if (rc != 0) { ! 1529: gbuf_freeb(mioc); ! 1530: *err = rc; ! 1531: return -1; ! 1532: } ! 1533: } ! 1534: gbuf_wset(m2,len); ! 1535: gbuf_cont(mioc) = m2; ! 1536: if (((*err = copyin((caddr_t)buf, (caddr_t)bds, atpBDSsize)) != 0) ! 1537: || ((*err = copyin((caddr_t)&buf[atpBDSsize], ! 1538: (caddr_t)gbuf_rptr(m2), len)) != 0)) { ! 1539: gbuf_freem(mioc); ! 1540: return -1; ! 1541: } ! 1542: gbuf_set_type(mioc, MSG_IOCTL); ! 1543: iocbp = (ioc_t *)gbuf_rptr(mioc); ! 1544: iocbp->ioc_count = len; ! 1545: iocbp->ioc_cmd = nowait ? AT_ATP_ISSUE_REQUEST_NOTE : AT_ATP_ISSUE_REQUEST; ! 1546: sdb = (struct atp_set_default *)gbuf_rptr(m2); ! 1547: ! 1548: /* ! 1549: * The at_snd_req library routine multiplies seconds by 100. ! 1550: * We need to divide by 100 in order to obtain the timer. ! 1551: */ ! 1552: if ((timer = (sdb->def_rate * HZ)/100) == 0) ! 1553: timer = HZ; ! 1554: iocbp->ioc_count -= sizeof(struct atp_set_default); ! 1555: gbuf_rinc(m2,sizeof(struct atp_set_default)); ! 1556: ! 1557: /* ! 1558: * allocate and set up the transaction record ! 1559: */ ! 1560: while ((trp = atp_trans_alloc(atp)) == 0) { ! 1561: ATDISABLE(s, atp->atp_delay_lock); ! 1562: rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atptrp", 10); ! 1563: ATENABLE(s, atp->atp_delay_lock); ! 1564: if (rc != 0) { ! 1565: gbuf_freem(mioc); ! 1566: *err = rc; ! 1567: return -1; ! 1568: } ! 1569: } ! 1570: trp->tr_retry = sdb->def_retries; ! 1571: trp->tr_timeout = timer; ! 1572: trp->tr_bdsp = NULL; ! 1573: trp->tr_tid = atp_tid(atp); ! 1574: tid = trp->tr_tid; ! 1575: ! 1576: /* ! 1577: * remember the IOCTL packet so we can ack it ! 1578: * later ! 1579: */ ! 1580: trp->tr_xmt = mioc; ! 1581: ! 1582: /* ! 1583: * Now fill in the header (and remember the bits ! 1584: * we need to know) ! 1585: */ ! 1586: athp = AT_ATP_HDR(m2); ! 1587: athp->cmd = ATP_CMD_TREQ; ! 1588: UAS_ASSIGN(athp->tid, trp->tr_tid); ! 1589: athp->eom = 0; ! 1590: athp->sts = 0; ! 1591: trp->tr_xo = athp->xo; ! 1592: trp->tr_bitmap = athp->bitmap; ! 1593: ddp = AT_DDP_HDR(m2); ! 1594: ddp->type = DDP_ATP; ! 1595: ddp->src_socket = (at_socket)atp->atp_socket_no; ! 1596: ddp->src_node = 0; ! 1597: trp->tr_socket.socket = ddp->dst_socket; ! 1598: trp->tr_socket.node = ddp->dst_node; ! 1599: trp->tr_socket.net = NET_VALUE(ddp->dst_net); ! 1600: trp->tr_local_socket = atp->atp_socket_no; ! 1601: ! 1602: /* ! 1603: * Put us in the transaction waiting queue ! 1604: */ ! 1605: ATDISABLE(s, atp->atp_lock); ! 1606: ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list); ! 1607: ATENABLE(s, atp->atp_lock); ! 1608: ! 1609: /* ! 1610: * Send the message and set the timer ! 1611: */ ! 1612: if ( !trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo) { ! 1613: m = (gbuf_t *)gbuf_copym(m2); ! 1614: atp_x_done(trp); /* no reason to tie up resources */ ! 1615: } else { ! 1616: m = (gbuf_t *)gbuf_dupm(m2); ! 1617: atp_timout(atp_req_timeout, trp, trp->tr_timeout); ! 1618: } ! 1619: if (m) ! 1620: DDP_OUTPUT(m); ! 1621: ! 1622: if (nowait) ! 1623: return (int)tid; ! 1624: ! 1625: /* ! 1626: * wait for the transaction to complete ! 1627: */ ! 1628: ATDISABLE(s, trp->tr_lock); ! 1629: while ((trp->tr_state != TRANS_DONE) && (trp->tr_state != TRANS_FAILED)) { ! 1630: trp->tr_rsp_wait = 1; ! 1631: rc = tsleep(&trp->tr_event, PSOCK | PCATCH, "atpsndreq", 0); ! 1632: if (rc != 0) { ! 1633: trp->tr_rsp_wait = 0; ! 1634: ATENABLE(s, trp->tr_lock); ! 1635: *err = rc; ! 1636: return -1; ! 1637: } ! 1638: } ! 1639: trp->tr_rsp_wait = 0; ! 1640: ATENABLE(s, trp->tr_lock); ! 1641: ! 1642: if (trp->tr_state == TRANS_FAILED) { ! 1643: /* ! 1644: * transaction timed out, return error ! 1645: */ ! 1646: atp_free(trp); ! 1647: *err = ETIMEDOUT; ! 1648: return -1; ! 1649: } ! 1650: ! 1651: /* ! 1652: * copy out the recv data ! 1653: */ ! 1654: atp_pack_bdsp(trp, bds); ! 1655: ! 1656: /* ! 1657: * copyout the result info ! 1658: */ ! 1659: copyout((caddr_t)bds, (caddr_t)buf, atpBDSsize); ! 1660: ! 1661: atp_free(trp); ! 1662: ! 1663: return (int)tid; ! 1664: } /* _ATPsndreq */ ! 1665: ! 1666: int ! 1667: _ATPsndrsp(fd, respbuff, resplen, datalen, err, proc) ! 1668: int fd; ! 1669: unsigned char *respbuff; ! 1670: int resplen; ! 1671: int datalen; ! 1672: int *err; ! 1673: void *proc; ! 1674: { ! 1675: gref_t *gref; ! 1676: int s, rc; ! 1677: long bufaddr; ! 1678: gbuf_t *m, *mdata; ! 1679: register short len; ! 1680: register int size; ! 1681: register struct atp_state *atp; ! 1682: register struct atpBDS *bdsp; ! 1683: register char *buf; ! 1684: ! 1685: if ((*err = atalk_getref(0, fd, &gref, proc)) != 0) ! 1686: return -1; ! 1687: ! 1688: if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0) ! 1689: || (atp->atp_flags & ATP_CLOSING)) { ! 1690: dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndrsp: stale handle=0x%x, pid=%d\n", ! 1691: (u_int) gref, gref->pid)); ! 1692: ! 1693: *err = EINVAL; ! 1694: return -1; ! 1695: } ! 1696: ! 1697: /* ! 1698: * allocate buffer and copy in the response info ! 1699: */ ! 1700: while ((m = gbuf_alloc(resplen, PRI_MED)) == 0) { ! 1701: ATDISABLE(s, atp->atp_delay_lock); ! 1702: rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atprspinfo", 10); ! 1703: ATENABLE(s, atp->atp_delay_lock); ! 1704: if (rc != 0) { ! 1705: *err = rc; ! 1706: return -1; ! 1707: } ! 1708: } ! 1709: if ((*err = copyin((caddr_t)respbuff, (caddr_t)gbuf_rptr(m), resplen)) != 0) { ! 1710: gbuf_freeb(m); ! 1711: return -1; ! 1712: } ! 1713: gbuf_wset(m,resplen); ! 1714: ((at_ddp_t *)gbuf_rptr(m))->src_node = 0; ! 1715: bdsp = (struct atpBDS *)(gbuf_rptr(m) + TOTAL_ATP_HDR_SIZE); ! 1716: if ((resplen == TOTAL_ATP_HDR_SIZE) || ((len = UAS_VALUE(bdsp->bdsDataSz)) == 1)) ! 1717: len = 0; ! 1718: else ! 1719: len = 16 * sizeof(gbuf_t); ! 1720: ! 1721: /* ! 1722: * allocate buffer and copy in the response data ! 1723: */ ! 1724: while ((mdata = gbuf_alloc(datalen+len, PRI_MED)) == 0) { ! 1725: ATDISABLE(s, atp->atp_delay_lock); ! 1726: rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atprspdata", 10); ! 1727: ATENABLE(s, atp->atp_delay_lock); ! 1728: if (rc != 0) { ! 1729: gbuf_freem(m); ! 1730: *err = rc; ! 1731: return -1; ! 1732: } ! 1733: } ! 1734: gbuf_cont(m) = mdata; ! 1735: for (size=0; bdsp < (struct atpBDS *)gbuf_wptr(m); bdsp++) { ! 1736: if ((bufaddr = UAL_VALUE(bdsp->bdsBuffAddr)) != 0) { ! 1737: len = UAS_VALUE(bdsp->bdsBuffSz); ! 1738: buf = (char *)bufaddr; ! 1739: if ((*err = copyin((caddr_t)buf, ! 1740: (caddr_t)&gbuf_rptr(mdata)[size], len)) != 0) { ! 1741: gbuf_freem(m); ! 1742: return -1; ! 1743: } ! 1744: size += len; ! 1745: } ! 1746: } ! 1747: gbuf_wset(mdata,size); ! 1748: ! 1749: atp_send_rsp(gref, m, TRUE); ! 1750: return 0; ! 1751: } ! 1752: ! 1753: int ! 1754: _ATPgetreq(fd, buf, buflen, err, proc) ! 1755: int fd; ! 1756: unsigned char *buf; ! 1757: int buflen; ! 1758: int *err; ! 1759: void *proc; ! 1760: { ! 1761: gref_t *gref; ! 1762: register struct atp_state *atp; ! 1763: register struct atp_rcb *rcbp; ! 1764: register gbuf_t *m, *m_head; ! 1765: int s, size, len; ! 1766: ! 1767: if ((*err = atalk_getref(0, fd, &gref, proc)) != 0) ! 1768: return -1; ! 1769: ! 1770: if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0) ! 1771: || (atp->atp_flags & ATP_CLOSING)) { ! 1772: dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetreq: stale handle=0x%x, pid=%d\n", ! 1773: (u_int) gref, gref->pid)); ! 1774: *err = EINVAL; ! 1775: return -1; ! 1776: } ! 1777: ! 1778: ATDISABLE(s, atp->atp_lock); ! 1779: if ((rcbp = atp->atp_attached.head) != NULL) { ! 1780: /* ! 1781: * Got one, move it to the active response Q ! 1782: */ ! 1783: m_head = rcbp->rc_ioctl; ! 1784: rcbp->rc_ioctl = NULL; ! 1785: ! 1786: if (rcbp->rc_xo) { ! 1787: ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list); ! 1788: rcbp->rc_state = RCB_NOTIFIED; ! 1789: ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list); ! 1790: } else { ! 1791: /* detach rcbp from attached queue, ! 1792: * and free any outstanding resources ! 1793: */ ! 1794: atp_rcb_free(rcbp); ! 1795: } ! 1796: ATENABLE(s, atp->atp_lock); ! 1797: ! 1798: /* ! 1799: * copyout the request data, including the protocol header ! 1800: */ ! 1801: for (size=0, m=m_head; m; m = gbuf_cont(m)) { ! 1802: if ((len = gbuf_len(m)) > buflen) ! 1803: len = buflen; ! 1804: copyout((caddr_t)gbuf_rptr(m), (caddr_t)&buf[size], len); ! 1805: size += len; ! 1806: if ((buflen -= len) == 0) ! 1807: break; ! 1808: } ! 1809: gbuf_freem(m_head); ! 1810: ! 1811: return size; ! 1812: } ! 1813: ATENABLE(s, atp->atp_lock); ! 1814: ! 1815: return -1; ! 1816: } ! 1817: ! 1818: int ! 1819: _ATPgetrsp(fd, bdsp, err, proc) ! 1820: int fd; ! 1821: struct atpBDS *bdsp; ! 1822: int *err; ! 1823: void *proc; ! 1824: { ! 1825: gref_t *gref; ! 1826: register struct atp_state *atp; ! 1827: register struct atp_trans *trp; ! 1828: int s, tid; ! 1829: char bds[atpBDSsize]; ! 1830: ! 1831: if ((*err = atalk_getref(0, fd, &gref, proc)) != 0) ! 1832: return -1; ! 1833: ! 1834: if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0) ! 1835: || (atp->atp_flags & ATP_CLOSING)) { ! 1836: dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetrsp: stale handle=0x%x, pid=%d\n", ! 1837: (u_int) gref, gref->pid)); ! 1838: *err = EINVAL; ! 1839: return -1; ! 1840: } ! 1841: ! 1842: ATDISABLE(s, atp->atp_lock); ! 1843: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) { ! 1844: dPrintf(D_M_ATP, D_L_INFO, ! 1845: ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n", ! 1846: (u_int) atp, (u_int) trp, trp->tr_state)); ! 1847: ! 1848: switch (trp->tr_state) { ! 1849: case TRANS_DONE: ! 1850: ATENABLE(s, atp->atp_lock); ! 1851: if ((*err = copyin((caddr_t)bdsp, ! 1852: (caddr_t)bds, sizeof(bds))) != 0) ! 1853: return -1; ! 1854: atp_pack_bdsp(trp, bds); ! 1855: tid = (int)trp->tr_tid; ! 1856: atp_free(trp); ! 1857: copyout((caddr_t)bds, (caddr_t)bdsp, sizeof(bds)); ! 1858: return tid; ! 1859: ! 1860: case TRANS_FAILED: ! 1861: /* ! 1862: * transaction timed out, return error ! 1863: */ ! 1864: ATENABLE(s, atp->atp_lock); ! 1865: atp_free(trp); ! 1866: *err = ETIMEDOUT; ! 1867: return -1; ! 1868: ! 1869: default: ! 1870: continue; ! 1871: } ! 1872: } ! 1873: ATENABLE(s, atp->atp_lock); ! 1874: ! 1875: *err = EINVAL; ! 1876: return -1; ! 1877: } ! 1878: ! 1879: void ! 1880: atp_drop_req(gref, m) ! 1881: gref_t *gref; ! 1882: gbuf_t *m; ! 1883: { ! 1884: int s; ! 1885: struct atp_state *atp; ! 1886: struct atp_rcb *rcbp; ! 1887: at_atp_t *athp; ! 1888: at_ddp_t *ddp; ! 1889: ! 1890: atp = (struct atp_state *)gref->info; ! 1891: if (atp->dflag) ! 1892: atp = (struct atp_state *)atp->atp_msgq; ! 1893: ddp = AT_DDP_HDR(m); ! 1894: athp = AT_ATP_HDR(m); ! 1895: ! 1896: /* ! 1897: * search for the corresponding rcb ! 1898: */ ! 1899: ATDISABLE(s, atp->atp_lock); ! 1900: for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) { ! 1901: if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) && ! 1902: (rcbp->rc_socket.node == ddp->src_node) && ! 1903: (rcbp->rc_socket.net == NET_VALUE(ddp->src_net)) && ! 1904: (rcbp->rc_socket.socket == ddp->src_socket) ) ! 1905: break; ! 1906: } ! 1907: ! 1908: /* ! 1909: * drop the request ! 1910: */ ! 1911: if (rcbp) ! 1912: atp_rcb_free(rcbp); ! 1913: ATENABLE(s, atp->atp_lock); ! 1914: ! 1915: gbuf_freem(m); ! 1916: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.