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