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