|
|
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: #include <appletalk.h> ! 35: #include <atp.h> ! 36: #include <ddp.h> ! 37: #include <at_atp.h> ! 38: #include <atp_inc.h> ! 39: ! 40: static void atp_trans_complete(); ! 41: ! 42: /* ! 43: * Decide what to do about received messages ! 44: * Version 1.7 of atp_read.c on 89/02/09 17:53:16 ! 45: */ ! 46: ! 47: int atp_treq_event(gref) ! 48: register gref_t *gref; ! 49: { ! 50: register gbuf_t *m; ! 51: register struct atp_state *atp; ! 52: ! 53: atp = (struct atp_state *)gref->info; ! 54: if (atp->dflag) ! 55: atp = (struct atp_state *)atp->atp_msgq; ! 56: ! 57: if (atp->dflag) { ! 58: if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) != NULL) { ! 59: gbuf_set_type(m, MSG_IOCTL); ! 60: gbuf_wset(m,sizeof(ioc_t)); ! 61: ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_GET_POLL; ! 62: atp_wput(gref, m); ! 63: } ! 64: } ! 65: else if ((m = gbuf_alloc(1, PRI_HI)) != NULL) { ! 66: *gbuf_rptr(m) = 0; ! 67: gbuf_wset(m,1); ! 68: atalk_putnext(gref, m); ! 69: } ! 70: ! 71: if (m == 0) ! 72: atalk_timeout(atp_treq_event, gref, 10); ! 73: } ! 74: ! 75: void atp_rput(gref, m) ! 76: gref_t *gref; ! 77: gbuf_t *m; ! 78: { ! 79: register at_atp_t *athp; ! 80: register struct atp_state *atp; ! 81: register int s, s_gen; ! 82: gbuf_t *m_asp = NULL; ! 83: ! 84: atp = (struct atp_state *)gref->info; ! 85: if (atp->dflag) ! 86: atp = (struct atp_state *)atp->atp_msgq; ! 87: ! 88: switch(gbuf_type(m)) { ! 89: case MSG_DATA: ! 90: /* ! 91: * Decode the message, make sure it is an atp ! 92: * message ! 93: */ ! 94: if (((AT_DDP_HDR(m))->type != ATP_DDP_TYPE) || ! 95: (atp->atp_flags & ATP_CLOSING)) { ! 96: gbuf_freem(m); ! 97: dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), ! 98: ("atp_rput: dropping MSG, not atp\n")); ! 99: break; ! 100: } ! 101: ! 102: athp = AT_ATP_HDR(m); ! 103: dPrintf(D_M_ATP_LOW, D_L_INPUT, ! 104: ("atp_rput MSG_DATA: %s (%d)\n", ! 105: (athp->cmd == ATP_CMD_TRESP)? "TRESP": ! 106: (athp->cmd == ATP_CMD_TREL)? "TREL": ! 107: (athp->cmd == ATP_CMD_TREQ)? "TREQ": "unknown", ! 108: athp->cmd)); ! 109: ! 110: switch (athp->cmd) { ! 111: ! 112: case ATP_CMD_TRESP: ! 113: { ! 114: register struct atp_trans *trp; ! 115: register int seqno; ! 116: register at_ddp_t *ddp; ! 117: ! 118: /* ! 119: * we just got a response, find the trans record ! 120: */ ! 121: ! 122: ATDISABLE(s, atp->atp_lock); ! 123: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) { ! 124: if (trp->tr_tid == UAS_VALUE(athp->tid)) ! 125: break; ! 126: } ! 127: ! 128: /* ! 129: * If we can't find one then ignore the message ! 130: */ ! 131: seqno = athp->bitmap; ! 132: if (trp == NULL) { ! 133: ATENABLE(s, atp->atp_lock); ! 134: ddp = AT_DDP_HDR(m); ! 135: dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), ! 136: ("atp_rput: dropping TRESP, no trp,tid=%d,loc=%d,rem=%d.%d,seqno=%d\n", ! 137: UAS_VALUE(athp->tid), ! 138: ddp->dst_socket,ddp->src_node,ddp->src_socket,seqno)); ! 139: gbuf_freem(m); ! 140: return; ! 141: } ! 142: ! 143: /* ! 144: * If no longer valid, drop it ! 145: */ ! 146: if (trp->tr_state == TRANS_FAILED) { ! 147: ATENABLE(s, atp->atp_lock); ! 148: ddp = AT_DDP_HDR(m); ! 149: dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), ! 150: ("atp_rput: dropping TRESP, failed trp,tid=%d,loc=%d,rem=%d.%d\n", ! 151: UAS_VALUE(athp->tid), ! 152: ddp->dst_socket, ddp->src_node, ddp->src_socket)); ! 153: gbuf_freem(m); ! 154: return; ! 155: } ! 156: ! 157: /* ! 158: * If we have already received it, ignore it ! 159: */ ! 160: if (!(trp->tr_bitmap&atp_mask[seqno]) || trp->tr_rcv[seqno]) { ! 161: ATENABLE(s, atp->atp_lock); ! 162: ddp = AT_DDP_HDR(m); ! 163: dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), ! 164: ("atp_rput: dropping TRESP, duplicate,tid=%d,loc=%d,rem=%d.%d,seqno=%d\n", ! 165: UAS_VALUE(athp->tid), ! 166: ddp->dst_socket, ddp->src_node, ddp->src_socket, seqno)); ! 167: gbuf_freem(m); ! 168: return; ! 169: } ! 170: ! 171: /* ! 172: * Update the received packet bitmap ! 173: */ ! 174: if (athp->eom) ! 175: trp->tr_bitmap &= atp_lomask[seqno]; ! 176: else ! 177: trp->tr_bitmap &= ~atp_mask[seqno]; ! 178: ! 179: /* ! 180: * Save the message in the trans record ! 181: */ ! 182: trp->tr_rcv[seqno] = m; ! 183: ! 184: /* ! 185: * If it isn't the first message then ! 186: * can the header ! 187: */ ! 188: if (seqno) ! 189: gbuf_rinc(m,DDP_X_HDR_SIZE); ! 190: ! 191: /* ! 192: * If we now have all the responses then return ! 193: * the message to the user ! 194: */ ! 195: if (trp->tr_bitmap == 0) { ! 196: ATENABLE(s, atp->atp_lock); ! 197: ! 198: /* ! 199: * Cancel the request timer and any ! 200: * pending transmits ! 201: */ ! 202: atp_untimout(atp_req_timeout, trp); ! 203: ! 204: /* ! 205: * Send the results back to the user ! 206: */ ! 207: atp_x_done(trp); ! 208: return; ! 209: } ! 210: if (athp->sts) { ! 211: /* ! 212: * If they want treq again, send them ! 213: */ ! 214: ATENABLE(s, atp->atp_lock); ! 215: atp_untimout(atp_req_timeout, trp); ! 216: atp_send(trp); ! 217: return; ! 218: } ! 219: ATENABLE(s, atp->atp_lock); ! 220: return; ! 221: } ! 222: ! 223: case ATP_CMD_TREL: ! 224: { register struct atp_rcb *rcbp; ! 225: register at_ddp_t *ddp; ! 226: ! 227: /* ! 228: * Search for a matching transaction ! 229: */ ! 230: ddp = AT_DDP_HDR(m); ! 231: ! 232: ATDISABLE(s, atp->atp_lock); ! 233: for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) { ! 234: if (rcbp->rc_tid == UAS_VALUE(athp->tid) && ! 235: rcbp->rc_socket.node == ddp->src_node && ! 236: rcbp->rc_socket.net == NET_VALUE(ddp->src_net) && ! 237: rcbp->rc_socket.socket == ddp->src_socket) { ! 238: /* ! 239: * Mark the rcb released ! 240: */ ! 241: rcbp->rc_not_sent_bitmap = 0; ! 242: if (rcbp->rc_state == RCB_SENDING) ! 243: rcbp->rc_state = RCB_RELEASED; ! 244: else ! 245: { ! 246: ddp = 0; ! 247: atp_rcb_free(rcbp); ! 248: ATENABLE(s, atp->atp_lock); ! 249: } ! 250: break; ! 251: } ! 252: } ! 253: ! 254: if (ddp) ! 255: ATENABLE(s, atp->atp_lock); ! 256: gbuf_freem(m); ! 257: return; ! 258: } ! 259: ! 260: ! 261: case ATP_CMD_TREQ: ! 262: { register struct atp_rcb *rcbp; ! 263: register at_ddp_t *ddp; ! 264: gbuf_t *m2; ! 265: ! 266: /* ! 267: * If it is a request message, first ! 268: * check to see ! 269: * if matches something in our active ! 270: * request queue ! 271: */ ! 272: ddp = AT_DDP_HDR(m); ! 273: ! 274: ATDISABLE(s, atp->atp_lock); ! 275: for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) { ! 276: if (rcbp->rc_tid == UAS_VALUE(athp->tid) && ! 277: rcbp->rc_socket.node == ddp->src_node && ! 278: rcbp->rc_socket.net == NET_VALUE(ddp->src_net) && ! 279: rcbp->rc_socket.socket == ddp->src_socket) ! 280: break; ! 281: } ! 282: /* ! 283: * If this is a new req then do ! 284: * something with it ! 285: */ ! 286: if (rcbp == NULL) { ! 287: /* ! 288: * see if it matches something in the ! 289: * attached request queue ! 290: * if it does, just release the message ! 291: * and go on about our buisness ! 292: */ ! 293: /* we just did this, why do again? -jjs 4-10-95 */ ! 294: for (rcbp = atp->atp_attached.head; rcbp; rcbp = rcbp->rc_list.next) { ! 295: if (rcbp->rc_tid == UAS_VALUE(athp->tid) && ! 296: rcbp->rc_socket.node == ddp->src_node && ! 297: rcbp->rc_socket.net == NET_VALUE(ddp->src_net) && ! 298: rcbp->rc_socket.socket == ddp->src_socket) { ! 299: ATENABLE(s, atp->atp_lock); ! 300: gbuf_freem(m); ! 301: dPrintf(D_M_ATP_LOW, D_L_INPUT, ! 302: ("atp_rput: dropping TREQ, matches req queue\n")); ! 303: return; ! 304: } ! 305: } ! 306: ! 307: /* ! 308: * assume someone is interested in ! 309: * in an asynchronous incoming request ! 310: */ ! 311: ATENABLE(s, atp->atp_lock); ! 312: if ((rcbp = atp_rcb_alloc(atp)) == NULL) { ! 313: gbuf_freem(m); ! 314: return; ! 315: } ! 316: rcbp->rc_state = RCB_UNQUEUED; ! 317: ATDISABLE(s, atp->atp_lock); ! 318: ! 319: rcbp->rc_local_node = ddp->dst_node; ! 320: NET_NET(rcbp->rc_local_net, ddp->dst_net); ! 321: rcbp->rc_socket.socket = ddp->src_socket; ! 322: rcbp->rc_socket.node = ddp->src_node; ! 323: rcbp->rc_socket.net = NET_VALUE(ddp->src_net); ! 324: rcbp->rc_tid = UAS_VALUE(athp->tid); ! 325: rcbp->rc_bitmap = athp->bitmap; ! 326: rcbp->rc_not_sent_bitmap = athp->bitmap; ! 327: rcbp->rc_xo = athp->xo; ! 328: /* ! 329: * if async then send it as ! 330: * data ! 331: * otherwise, it is a synchronous ioctl so ! 332: * complete it ! 333: */ ! 334: if (atp->dflag) { /* for ASP? */ ! 335: if (m2 = gbuf_alloc(sizeof(ioc_t), PRI_HI)) { ! 336: gbuf_set_type(m2, MSG_DATA); ! 337: gbuf_wset(m2,sizeof(ioc_t)); ! 338: ((ioc_t *)gbuf_rptr(m2))->ioc_cmd = AT_ATP_GET_POLL; ! 339: m_asp = m2; ! 340: } ! 341: } else if (m2 = gbuf_alloc(1, PRI_HI)) { ! 342: *gbuf_rptr(m2) = 0; ! 343: gbuf_wset(m2,1); ! 344: atalk_putnext(gref, m2); ! 345: } ! 346: if (m2 == 0) { ! 347: dPrintf(D_M_ATP,D_L_WARNING, ! 348: ("atp_rput: out of buffer for TREQ\n")); ! 349: atalk_timeout(atp_treq_event, gref, 10); ! 350: } ! 351: rcbp->rc_ioctl = m; ! 352: ! 353: /* ! 354: * move it to the attached list ! 355: */ ! 356: dPrintf(D_M_ATP_LOW, D_L_INPUT, ! 357: ("atp_rput: moving to attached list\n")); ! 358: rcbp->rc_state = RCB_PENDING; ! 359: ATP_Q_APPEND(atp->atp_attached, rcbp, rc_list); ! 360: if (m_asp != NULL) { ! 361: ATENABLE(s, atp->atp_lock); ! 362: atp_req_ind(atp, m_asp); ! 363: return; ! 364: } ! 365: } else { ! 366: dPrintf(D_M_ATP_LOW, D_L_INPUT, ! 367: ("atp_rput: found match, state:%d\n", ! 368: rcbp->rc_state)); ! 369: ! 370: /* ! 371: * Otherwise we have found a matching request ! 372: * look for what to do ! 373: */ ! 374: switch (rcbp->rc_state) { ! 375: case RCB_RESPONDING: ! 376: case RCB_RESPONSE_FULL: ! 377: /* ! 378: * If it is one we have in progress ! 379: * (either have all the responses ! 380: * or are waiting for them) ! 381: * update the bitmap and resend ! 382: * the replies ! 383: */ ! 384: ATDISABLE(s_gen, atpgen_lock); ! 385: if (rcbp->rc_timestamp) { ! 386: rcbp->rc_timestamp = time.tv_sec; ! 387: if (rcbp->rc_timestamp == 0) ! 388: rcbp->rc_timestamp = 1; ! 389: } ! 390: ATENABLE(s_gen, atpgen_lock); ! 391: rcbp->rc_bitmap = athp->bitmap; ! 392: rcbp->rc_not_sent_bitmap = athp->bitmap; ! 393: ATENABLE(s, atp->atp_lock); ! 394: gbuf_freem(m); ! 395: atp_reply(rcbp); ! 396: return; ! 397: ! 398: case RCB_RELEASED: ! 399: default: ! 400: /* ! 401: * If we have a release or ! 402: * we haven't sent any data yet ! 403: * ignore the request ! 404: */ ! 405: ATENABLE(s, atp->atp_lock); ! 406: gbuf_freem(m); ! 407: return; ! 408: } ! 409: } ! 410: ATENABLE(s, atp->atp_lock); ! 411: return; ! 412: } ! 413: ! 414: default: ! 415: gbuf_freem(m); ! 416: break; ! 417: } ! 418: break; ! 419: ! 420: case MSG_IOCACK: ! 421: if (atp->dflag) ! 422: asp_ack_reply(gref, m); ! 423: else ! 424: atalk_putnext(gref, m); ! 425: break; ! 426: ! 427: case MSG_IOCNAK: ! 428: if (atp->dflag) ! 429: asp_nak_reply(gref, m); ! 430: else ! 431: atalk_putnext(gref, m); ! 432: break; ! 433: ! 434: default: ! 435: gbuf_freem(m); ! 436: } ! 437: } /* atp_rput */ ! 438: ! 439: void ! 440: atp_x_done(trp) ! 441: register struct atp_trans *trp; ! 442: { ! 443: struct atp_state *atp; ! 444: gbuf_t *m; ! 445: ! 446: if ( !trp->tr_xo) ! 447: atp_trans_complete(trp); ! 448: else { ! 449: /* ! 450: * If execute once send a release ! 451: */ ! 452: if ((m = (gbuf_t *)atp_build_release(trp)) != NULL) { ! 453: AT_DDP_HDR(m)->src_socket = ((struct atp_state *) ! 454: trp->tr_queue)->atp_socket_no; ! 455: DDP_OUTPUT(m); ! 456: /* ! 457: * Now send back the transaction reply to the process ! 458: * or notify the process if required ! 459: */ ! 460: atp_trans_complete(trp); ! 461: } else { ! 462: ! 463: atp = trp->tr_queue; ! 464: trp->tr_state = TRANS_RELEASE; ! 465: atalk_timeout(atp_x_done, trp, 10); ! 466: } ! 467: } ! 468: } ! 469: ! 470: static void ! 471: atp_trans_complete(trp) ! 472: register struct atp_trans *trp; ! 473: { register gbuf_t *m; ! 474: register int type; ! 475: struct atp_state *atp; ! 476: ! 477: /* we could gbuf_freem(trp->tr_xmt) here if were not planning to ! 478: re-use the mbuf later */ ! 479: m = trp->tr_xmt; ! 480: trp->tr_xmt = NULL; ! 481: trp->tr_state = TRANS_DONE; ! 482: ! 483: if (gbuf_cont(m) == NULL) /* issued via the new interface */ ! 484: type = AT_ATP_ISSUE_REQUEST_NOTE; ! 485: else { ! 486: type = ((ioc_t *)(gbuf_rptr(m)))->ioc_cmd; ! 487: /* ! 488: * free any data following the ioctl blk ! 489: */ ! 490: gbuf_freem(gbuf_cont(m)); ! 491: gbuf_cont(m) = NULL; ! 492: } ! 493: dPrintf(D_M_ATP_LOW, D_L_INPUT, ("atp_trans_comp: trp=0x%x type = %s\n", ! 494: (u_int) trp, ! 495: (type==AT_ATP_ISSUE_REQUEST)? "AT_ATP_ISSUE_REQUEST": ! 496: (type==AT_ATP_ISSUE_REQUEST_NOTE)? "AT_ATP_ISSUE_REQUEST_NOTE" : ! 497: "unknown")); ! 498: ! 499: switch(type) { ! 500: case AT_ATP_ISSUE_REQUEST: ! 501: atp = trp->tr_queue; ! 502: if (atp->dflag) { ! 503: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0; ! 504: ((ioc_t *)gbuf_rptr(m))->ioc_error = 0; ! 505: ((ioc_t *)gbuf_rptr(m))->ioc_rval = trp->tr_tid; ! 506: ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_REQUEST_COMPLETE; ! 507: gbuf_set_type(m, MSG_IOCTL); ! 508: atp_rsp_ind(trp, m); ! 509: } else { ! 510: if (trp->tr_bdsp == NULL) { ! 511: gbuf_freem(m); ! 512: if (trp->tr_rsp_wait) ! 513: #ifdef _AIX ! 514: e_wakeup(&trp->tr_event); ! 515: #else ! 516: thread_wakeup(&trp->tr_event); ! 517: #endif ! 518: } else { ! 519: gbuf_set_type(m, MSG_IOCACK); ! 520: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0; ! 521: ((ioc_t *)gbuf_rptr(m))->ioc_error = 0; ! 522: ((ioc_t *)gbuf_rptr(m))->ioc_rval = 0; ! 523: atalk_putnext(trp->tr_queue->atp_gref, m); ! 524: } ! 525: } ! 526: break; ! 527: ! 528: case AT_ATP_ISSUE_REQUEST_NOTE: ! 529: gbuf_wset(m,1); ! 530: *gbuf_rptr(m) = 1; ! 531: gbuf_set_type(m, MSG_DATA); ! 532: atalk_putnext(trp->tr_queue->atp_gref, m); ! 533: break; ! 534: } ! 535: } /* atp_trans_complete */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.