1/* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1996-1998 Apple Computer, Inc. 30 * All Rights Reserved. 31 */ 32 33/* Modified for MP, 1996 by Tuyen Nguyen 34 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX. 35 */ 36#include <sys/errno.h> 37#include <sys/types.h> 38#include <sys/param.h> 39#include <machine/spl.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/proc.h> 43#include <sys/filedesc.h> 44#include <sys/fcntl.h> 45#include <sys/mbuf.h> 46#include <sys/ioctl.h> 47#include <sys/malloc.h> 48#include <sys/socket.h> 49 50#include <netat/sysglue.h> 51#include <netat/appletalk.h> 52#include <netat/ddp.h> 53#include <netat/at_pcb.h> 54#include <netat/atp.h> 55#include <netat/asp.h> 56#include <netat/debug.h> 57 58extern struct atp_rcb_qhead atp_need_rel; 59extern struct atp_trans *trp_tmo_rcb; 60 61/* 62 * The request timer retries a request, if all retries are used up 63 * it returns a NAK 64 */ 65 66void 67atp_req_timeout(trp) 68register struct atp_trans *trp; 69{ 70 register gbuf_t *m; 71 gref_t *gref; 72 struct atp_state *atp; 73 struct atp_trans *ctrp; 74 75 if ((atp = trp->tr_queue) == 0) 76 return; 77 if (atp->atp_flags & ATP_CLOSING) 78 return; 79 80 for (ctrp = atp->atp_trans_wait.head; ctrp; ctrp = ctrp->tr_list.next) { 81 if (ctrp == trp) 82 break; 83 } 84 if (ctrp != trp) 85 return; 86 87 if ((m = gbuf_cont(trp->tr_xmt)) == NULL) 88 m = trp->tr_xmt; /* issued via the new interface */ 89 90 if (trp->tr_retry == 0) { 91 trp->tr_state = TRANS_FAILED; 92 if (m == trp->tr_xmt) { 93 trp->tr_xmt = NULL; 94l_notify: 95 gbuf_wset(m,1); 96 *gbuf_rptr(m) = 99; 97 gbuf_set_type(m, MSG_DATA); 98 gref = trp->tr_queue->atp_gref; 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 gbuf_freem(m); 113 if (trp->tr_rsp_wait) 114 wakeup(&trp->tr_event); 115 break; 116 } 117 atp_iocnak(trp->tr_queue, m, ETIMEDOUT); 118 atp_free(trp); 119 return; 120 121 case AT_ATP_ISSUE_REQUEST_NOTE: 122 case AT_ATP_ISSUE_REQUEST_TICKLE: 123 trp->tr_xmt = gbuf_cont(m); 124 gbuf_cont(m) = NULL; 125 goto l_notify; 126 } 127 } else { 128 (AT_ATP_HDR(m))->bitmap = trp->tr_bitmap; 129 130 if (trp->tr_retry != (unsigned int) ATP_INFINITE_RETRIES) 131 trp->tr_retry--; 132 atp_send(trp); 133 } 134} 135 136 137/* 138 * atp_free frees up a request, cleaning up the queues and freeing 139 * the request packet 140 * always called at 'lock' 141 */ 142 143void atp_free(trp) 144register struct atp_trans *trp; 145{ 146 register struct atp_state *atp; 147 register int i; 148 149 dPrintf(D_M_ATP_LOW, D_L_TRACE, 150 ("atp_free: freeing trp 0x%x\n", (u_int) trp)); 151 152 153 if (trp->tr_state == TRANS_ABORTING) { 154 ATP_Q_REMOVE(atp_trans_abort, trp, tr_list); 155 trp->tr_state = TRANS_DONE; 156 } 157 else { 158 if (trp->tr_tmo_func) 159 atp_untimout(atp_req_timeout, trp); 160 161 atp = trp->tr_queue; 162 ATP_Q_REMOVE(atp->atp_trans_wait, trp, tr_list); 163 164 if (trp->tr_xmt) { 165 gbuf_freem(trp->tr_xmt); 166 trp->tr_xmt = NULL; 167 } 168 for (i = 0; i < 8; i++) { 169 if (trp->tr_rcv[i]) { 170 gbuf_freem(trp->tr_rcv[i]); 171 trp->tr_rcv[i] = NULL; 172 } 173 } 174 if (trp->tr_bdsp) { 175 gbuf_freem(trp->tr_bdsp); 176 trp->tr_bdsp = NULL; 177 } 178 179 if (trp->tr_rsp_wait) { 180 trp->tr_state = TRANS_ABORTING; 181 ATP_Q_APPEND(atp_trans_abort, trp, tr_list); 182 wakeup(&trp->tr_event); 183 return; 184 } 185 } 186 187 atp_trans_free(trp); 188} /* atp_free */ 189 190 191/* 192 * atp_send transmits a request packet by queuing it (if it isn't already) and 193 * scheduling the queue 194 */ 195 196void atp_send(trp) 197register struct atp_trans *trp; 198{ 199 gbuf_t *m; 200 struct atp_state *atp; 201 202 dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ("atp_send: trp=0x%x, loc=%d\n", 203 (u_int) trp->tr_queue, trp->tr_local_socket)); 204 205 if ((atp = trp->tr_queue) != 0) { 206 if (trp->tr_state == TRANS_TIMEOUT) { 207 if ((m = gbuf_cont(trp->tr_xmt)) == NULL) 208 m = trp->tr_xmt; 209 210 /* 211 * Now either release the transaction or start the timer 212 */ 213 if (!trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo) { 214 m = (gbuf_t *)gbuf_copym(m); 215 atp_x_done(trp); 216 } else { 217 m = (gbuf_t *)gbuf_dupm(m); 218 219 atp_timout(atp_req_timeout, trp, trp->tr_timeout); 220 } 221 222 if (m) { 223 trace_mbufs(D_M_ATP_LOW, " m", m); 224 DDP_OUTPUT(m); 225 } 226 } 227 } 228} 229 230 231/* 232 * atp_reply sends all the available messages in the bitmap again 233 * by queueing us to the write service routine 234 */ 235 236void atp_reply(rcbp) 237register struct atp_rcb *rcbp; 238{ 239 register struct atp_state *atp; 240 register int i; 241 242 if ((atp = rcbp->rc_queue) != 0) { 243 for (i = 0; i < rcbp->rc_pktcnt; i++) { 244 if (rcbp->rc_bitmap&atp_mask[i]) 245 rcbp->rc_snd[i] = 1; 246 else 247 rcbp->rc_snd[i] = 0; 248 } 249 if (rcbp->rc_rep_waiting == 0) { 250 rcbp->rc_state = RCB_SENDING; 251 rcbp->rc_rep_waiting = 1; 252 atp_send_replies(atp, rcbp); 253 } 254 } 255} 256 257 258/* 259 * The rcb timer just frees the rcb, this happens when we missed a release for XO 260 */ 261 262void atp_rcb_timer(__unused struct atp_trans *junk) 263{ 264 register struct atp_rcb *rcbp; 265 register struct atp_rcb *next_rcbp; 266 struct timeval timenow; 267 268l_again: 269 getmicrouptime(&timenow); 270 for (rcbp = atp_need_rel.head; rcbp; rcbp = next_rcbp) { 271 next_rcbp = rcbp->rc_tlist.next; 272 273 if ((timenow.tv_sec - rcbp->rc_timestamp) > 30) { 274 atp_rcb_free(rcbp); 275 goto l_again; 276 } 277 } 278 atp_timout(atp_rcb_timer, trp_tmo_rcb, 10 * HZ); 279} 280 281void atp_iocack(atp, m) 282struct atp_state *atp; 283register 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 298void atp_iocnak(atp, m, err) 299struct atp_state *atp; 300register gbuf_t *m; 301register 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 */ 322static int lasttid; 323int atp_tid(atp) 324register struct atp_state *atp; 325{ 326 register int i; 327 register struct atp_trans *trp; 328 329 for (i = lasttid;;) { 330 i = (i+1)&0xffff; 331 332 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) { 333 if (trp->tr_tid == i) 334 break; 335 } 336 if (trp == NULL) { 337 lasttid = i; 338 return(i); 339 } 340 } 341} 342