|
|
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: extern atlock_t atpgen_lock; ! 41: void atp_free(); ! 42: void atp_send(struct atp_trans *); ! 43: ! 44: /* ! 45: * The request timer retries a request, if all retries are used up ! 46: * it returns a NAK ! 47: */ ! 48: ! 49: void ! 50: atp_req_timeout(trp) ! 51: register struct atp_trans *trp; ! 52: { ! 53: int s; ! 54: register gbuf_t *m; ! 55: gref_t *gref; ! 56: struct atp_state *atp; ! 57: struct atp_trans *ctrp; ! 58: ! 59: if ((atp = trp->tr_queue) == 0) ! 60: return; ! 61: ATDISABLE(s, atp->atp_lock); ! 62: if (atp->atp_flags & ATP_CLOSING) { ! 63: ATENABLE(s, atp->atp_lock); ! 64: return; ! 65: } ! 66: for (ctrp = atp->atp_trans_wait.head; ctrp; ctrp = ctrp->tr_list.next) { ! 67: if (ctrp == trp) ! 68: break; ! 69: } ! 70: if (ctrp != trp) { ! 71: ATENABLE(s, atp->atp_lock); ! 72: return; ! 73: } ! 74: ! 75: if ((m = gbuf_cont(trp->tr_xmt)) == NULL) ! 76: m = trp->tr_xmt; /* issued via the new interface */ ! 77: ! 78: if (trp->tr_retry == 0) { ! 79: trp->tr_state = TRANS_FAILED; ! 80: if (m == trp->tr_xmt) { ! 81: trp->tr_xmt = NULL; ! 82: l_notify: ! 83: gbuf_wset(m,1); ! 84: *gbuf_rptr(m) = 99; ! 85: gbuf_set_type(m, MSG_DATA); ! 86: gref = trp->tr_queue->atp_gref; ! 87: ATENABLE(s, atp->atp_lock); ! 88: atalk_putnext(gref, m); ! 89: ! 90: return; ! 91: } ! 92: dPrintf(D_M_ATP_LOW,D_L_INFO, ("atp_req_timeout: skt=%d\n", ! 93: trp->tr_local_socket)); ! 94: m = trp->tr_xmt; ! 95: switch(((ioc_t *)(gbuf_rptr(trp->tr_xmt)))->ioc_cmd) { ! 96: case AT_ATP_ISSUE_REQUEST: ! 97: trp->tr_xmt = NULL; ! 98: if (trp->tr_queue->dflag) ! 99: ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_REQUEST_COMPLETE; ! 100: else if (trp->tr_bdsp == NULL) { ! 101: ATENABLE(s, atp->atp_lock); ! 102: gbuf_freem(m); ! 103: if (trp->tr_rsp_wait) ! 104: #ifdef _AIX ! 105: e_wakeup(&trp->tr_event); ! 106: #else ! 107: thread_wakeup(&trp->tr_event); ! 108: #endif ! 109: break; ! 110: } ! 111: ATENABLE(s, atp->atp_lock); ! 112: atp_iocnak(trp->tr_queue, m, ETIMEDOUT); ! 113: atp_free(trp); ! 114: return; ! 115: ! 116: case AT_ATP_ISSUE_REQUEST_NOTE: ! 117: case AT_ATP_ISSUE_REQUEST_DEF_NOTE: ! 118: /* AT_ATP_ISSUE_REQUEST_DEF_NOTE is used just for tickle */ ! 119: trp->tr_xmt = gbuf_cont(m); ! 120: gbuf_cont(m) = NULL; ! 121: goto l_notify; ! 122: } ! 123: } else { ! 124: (AT_ATP_HDR(m))->bitmap = trp->tr_bitmap; ! 125: ! 126: if (trp->tr_retry != (unsigned int) ATP_INFINITE_RETRIES) ! 127: trp->tr_retry--; ! 128: ATENABLE(s, atp->atp_lock); ! 129: atp_send(trp); ! 130: } ! 131: } ! 132: ! 133: ! 134: /* ! 135: * atp_free frees up a request, cleaning up the queues and freeing ! 136: * the request packet ! 137: * always called at 'lock' ! 138: */ ! 139: ! 140: void atp_free(trp) ! 141: register struct atp_trans *trp; ! 142: { ! 143: register struct atp_state *atp; ! 144: register int i; ! 145: int s; ! 146: ! 147: dPrintf(D_M_ATP_LOW, D_L_TRACE, ! 148: ("atp_free: freeing trp 0x%x\n", (u_int) trp)); ! 149: ATDISABLE(s, atpgen_lock); ! 150: if (trp->tr_tmo_func) ! 151: atp_untimout(atp_req_timeout, trp); ! 152: atp = trp->tr_queue; ! 153: ! 154: ATP_Q_REMOVE(atp->atp_trans_wait, trp, tr_list); ! 155: ! 156: if (trp->tr_xmt) { ! 157: gbuf_freem(trp->tr_xmt); ! 158: trp->tr_xmt = NULL; ! 159: } ! 160: for (i = 0; i < 8; i++) { ! 161: if (trp->tr_rcv[i]) { ! 162: gbuf_freem(trp->tr_rcv[i]); ! 163: trp->tr_rcv[i] = NULL; ! 164: } ! 165: } ! 166: if (trp->tr_bdsp) { ! 167: gbuf_freem(trp->tr_bdsp); ! 168: trp->tr_bdsp = NULL; ! 169: } ! 170: ! 171: ATENABLE(s, atpgen_lock); ! 172: atp_trans_free(trp); ! 173: ! 174: } /* atp_free */ ! 175: ! 176: ! 177: /* ! 178: * atp_send transmits a request packet by queuing it (if it isn't already) and ! 179: * scheduling the queue ! 180: */ ! 181: ! 182: void atp_send(trp) ! 183: register struct atp_trans *trp; ! 184: { ! 185: gbuf_t *m; ! 186: struct atp_state *atp; ! 187: ! 188: dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ("atp_send: trp=0x%x, skt=%d\n", ! 189: (u_int) trp->tr_queue, trp->tr_local_socket)); ! 190: ! 191: if ((atp = trp->tr_queue) != 0) { ! 192: if (trp->tr_state == TRANS_TIMEOUT) { ! 193: if ((m = gbuf_cont(trp->tr_xmt)) == NULL) ! 194: m = trp->tr_xmt; ! 195: ! 196: /* ! 197: * Now either release the transaction or start the timer ! 198: */ ! 199: if (!trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo) { ! 200: m = (gbuf_t *)gbuf_copym(m); ! 201: atp_x_done(trp); ! 202: } else { ! 203: m = (gbuf_t *)gbuf_dupm(m); ! 204: ! 205: atp_timout(atp_req_timeout, trp, trp->tr_timeout); ! 206: } ! 207: ! 208: if (m) ! 209: DDP_OUTPUT(m); ! 210: } ! 211: } ! 212: } ! 213: ! 214: ! 215: /* ! 216: * atp_reply sends all the available messages in the bitmap again ! 217: * by queueing us to the write service routine ! 218: */ ! 219: ! 220: void atp_reply(rcbp) ! 221: register struct atp_rcb *rcbp; ! 222: { ! 223: register struct atp_state *atp; ! 224: register int i; ! 225: int s; ! 226: ! 227: if ((atp = rcbp->rc_queue) != 0) { ! 228: ATDISABLE(s, atp->atp_lock); ! 229: for (i = 0; i < rcbp->rc_pktcnt; i++) { ! 230: if (rcbp->rc_bitmap&atp_mask[i]) ! 231: rcbp->rc_snd[i] = 1; ! 232: else ! 233: rcbp->rc_snd[i] = 0; ! 234: } ! 235: if (rcbp->rc_rep_waiting == 0) { ! 236: rcbp->rc_state = RCB_SENDING; ! 237: rcbp->rc_rep_waiting = 1; ! 238: ATENABLE(s, atp->atp_lock); ! 239: atp_send_replies(atp, rcbp); ! 240: } else ! 241: ATENABLE(s, atp->atp_lock); ! 242: } ! 243: } ! 244: ! 245: ! 246: /* ! 247: * The rcb timer just frees the rcb, this happens when we missed a release for XO ! 248: */ ! 249: ! 250: void atp_rcb_timer() ! 251: { ! 252: int s; ! 253: register struct atp_rcb *rcbp; ! 254: register struct atp_rcb *next_rcbp; ! 255: extern struct atp_rcb_qhead atp_need_rel; ! 256: extern struct atp_trans *trp_tmo_rcb; ! 257: ! 258: l_again: ! 259: ATDISABLE(s, atpgen_lock); ! 260: for (rcbp = atp_need_rel.head; rcbp; rcbp = next_rcbp) { ! 261: next_rcbp = rcbp->rc_tlist.next; ! 262: ! 263: if (abs(time.tv_sec - rcbp->rc_timestamp) > 30) { ! 264: ATENABLE(s, atpgen_lock); ! 265: atp_rcb_free(rcbp); ! 266: goto l_again; ! 267: } ! 268: } ! 269: ATENABLE(s, atpgen_lock); ! 270: atp_timout(atp_rcb_timer, trp_tmo_rcb, 10 * HZ); ! 271: } ! 272: ! 273: atp_iocack(atp, m) ! 274: struct atp_state *atp; ! 275: register gbuf_t *m; ! 276: { ! 277: if (gbuf_type(m) == MSG_IOCTL) ! 278: gbuf_set_type(m, MSG_IOCACK); ! 279: if (gbuf_cont(m)) ! 280: ((ioc_t *)gbuf_rptr(m))->ioc_count = gbuf_msgsize(gbuf_cont(m)); ! 281: else ! 282: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0; ! 283: ! 284: if (atp->dflag) ! 285: asp_ack_reply(atp->atp_gref, m); ! 286: else ! 287: atalk_putnext(atp->atp_gref, m); ! 288: } ! 289: ! 290: atp_iocnak(atp, m, err) ! 291: struct atp_state *atp; ! 292: register gbuf_t *m; ! 293: register int err; ! 294: { ! 295: if (gbuf_type(m) == MSG_IOCTL) ! 296: gbuf_set_type(m, MSG_IOCNAK); ! 297: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0; ! 298: ((ioc_t *)gbuf_rptr(m))->ioc_error = err ? err : ENXIO; ! 299: ((ioc_t *)gbuf_rptr(m))->ioc_rval = -1; ! 300: if (gbuf_cont(m)) { ! 301: gbuf_freem(gbuf_cont(m)); ! 302: gbuf_cont(m) = NULL; ! 303: } ! 304: ! 305: if (atp->dflag) ! 306: asp_nak_reply(atp->atp_gref, m); ! 307: else ! 308: atalk_putnext(atp->atp_gref, m); ! 309: } ! 310: ! 311: /* ! 312: * Generate a transaction id for a socket ! 313: */ ! 314: static int lasttid; ! 315: atp_tid(atp) ! 316: register struct atp_state *atp; ! 317: { ! 318: register int i; ! 319: register struct atp_trans *trp; ! 320: int s; ! 321: ! 322: ATDISABLE(s, atpgen_lock); ! 323: for (i = lasttid;;) { ! 324: i = (i+1)&0xffff; ! 325: ! 326: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) { ! 327: if (trp->tr_tid == i) ! 328: break; ! 329: } ! 330: if (trp == NULL) { ! 331: lasttid = i; ! 332: ATENABLE(s, atpgen_lock); ! 333: return(i); ! 334: } ! 335: } ! 336: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.