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