1/* 2 * Copyright (c) 2000-2006 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/* Modified for MP, 1996 by Tuyen Nguyen */ 29/* 30 * tcb (transaction) allocation routine. If no transaction data structure 31 * is available then put the module on a queue of modules waiting 32 * for transaction structures. When a tcb is available it will be 33 * removed from this list and its write queue will be scheduled. 34 * Version 1.4 of atp_alloc.c on 89/02/09 17:53:01 35 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX. 36 */ 37#include <sys/errno.h> 38#include <sys/types.h> 39#include <sys/param.h> 40#include <machine/spl.h> 41#include <sys/systm.h> 42#include <sys/kernel.h> 43#include <sys/proc.h> 44#include <sys/filedesc.h> 45#include <sys/fcntl.h> 46#include <sys/mbuf.h> 47#include <sys/socket.h> 48 49#include <netat/sysglue.h> 50#include <netat/appletalk.h> 51#include <netat/ddp.h> 52#include <netat/debug.h> 53#include <netat/at_pcb.h> 54#include <netat/atp.h> 55 56/*### MacOSX MCLBYTE is 2048, not 4096 like AIX */ 57#define TRPS_PER_BLK 16 58 59gbuf_t *atp_resource_m = 0; 60extern caddr_t atp_free_cluster_list; 61extern struct atp_rcb_qhead atp_need_rel; 62 63 64struct atp_trans *atp_trans_alloc(atp) 65struct atp_state *atp; 66{ 67 int i; 68 gbuf_t *m; 69 register struct atp_trans *trp, *trp_array; 70 71 if (atp_trans_free_list == 0) { 72 if ((m = gbuf_alloc_wait(TRPS_PER_BLK*sizeof(struct atp_trans), 73 atp == NULL)) == 0) 74 return (struct atp_trans *)0; 75 bzero(gbuf_rptr(m), TRPS_PER_BLK*sizeof(struct atp_trans)); 76 trp_array = (struct atp_trans *)gbuf_rptr(m); 77 for (i=0; i < TRPS_PER_BLK-1; i++) 78 trp_array[i].tr_list.next = (struct atp_trans *)&trp_array[i+1]; 79 gbuf_cont(m) = atp_resource_m; 80 atp_resource_m = m; 81 trp_array[i].tr_list.next = atp_trans_free_list; 82 atp_trans_free_list = (struct atp_trans *)&trp_array[0]; 83 } 84 85 trp = atp_trans_free_list; 86 atp_trans_free_list = trp->tr_list.next; 87 trp->tr_queue = atp; 88 trp->tr_state = TRANS_TIMEOUT; 89 trp->tr_local_node = 0; 90 ATEVENTINIT(trp->tr_event); 91 92 dPrintf(D_M_ATP_LOW, D_L_TRACE, 93 ("atp_trans_alloc(0x%x): alloc'd trp 0x%x\n", 94 (u_int) atp, (u_int) trp)); 95 return trp; 96} /* atp_trans_alloc */ 97 98/* 99 * tcb free routine - if modules are waiting schedule them 100 * always called at 'lock' 101 */ 102 103void atp_trans_free(trp) 104register struct atp_trans *trp; 105{ 106 107 trp->tr_queue = 0; 108 trp->tr_list.next = atp_trans_free_list; 109 atp_trans_free_list = trp; 110} 111 112/* 113 * This routine allocates a rcb, if none are available it makes sure the 114 * the write service routine will be called when one is 115 * always called at 'lock' 116 */ 117 118struct atp_rcb *atp_rcb_alloc(atp) 119struct atp_state *atp; 120{ 121 register struct atp_rcb *rcbp; 122 123 if ((rcbp = atp_rcb_free_list) != NULL) { 124 atp_rcb_free_list = rcbp->rc_list.next; 125 rcbp->rc_queue = atp; 126 rcbp->rc_pktcnt = 0; 127 rcbp->rc_local_node = 0; 128 } 129 dPrintf(D_M_ATP_LOW, D_L_TRACE, 130 ("atp_rcb_alloc: allocated rcbp 0x%x\n", (u_int) rcbp)); 131 return(rcbp); 132} 133 134/* 135 * Here we free rcbs, if required reschedule other people waiting for them 136 * always called at 'lock' 137 */ 138 139void atp_rcb_free(rcbp) 140register struct atp_rcb *rcbp; 141{ 142 register struct atp_state *atp; 143 register int i; 144 register int rc_state; 145 146 dPrintf(D_M_ATP_LOW, D_L_TRACE, 147 ("atp_rcb_free: freeing rcbp 0x%x\n", (u_int) rcbp)); 148 atp = rcbp->rc_queue; 149 if ((rc_state = rcbp->rc_state) == -1) { 150 dPrintf(D_M_ATP, D_L_WARNING, 151 ("atp_rcb_free(%d): tid=%d,loc=%d,rem=%d\n", 152 0, rcbp->rc_tid, 153 rcbp->rc_socket.socket, atp->atp_socket_no)); 154 return; 155 } 156 rcbp->rc_state = -1; 157 rcbp->rc_xo = 0; 158 rcbp->rc_queue = 0; 159 160 if (rcbp->rc_timestamp) { 161 rcbp->rc_timestamp = 0; 162 ATP_Q_REMOVE(atp_need_rel, rcbp, rc_tlist); 163 rcbp->rc_tlist.prev = NULL; 164 rcbp->rc_tlist.next = NULL; 165 } 166 167 if (rcbp->rc_xmt) { 168 gbuf_freem(rcbp->rc_xmt); /* *** bad free is the second mbuf in this chain *** */ 169 rcbp->rc_xmt = NULL; 170 for (i=0; i < rcbp->rc_pktcnt; i++) 171 rcbp->rc_snd[i] = 0; 172 } 173 if (atp_free_cluster_list) 174 atp_delete_free_clusters(NULL); 175 if (rc_state != RCB_UNQUEUED) { 176 if (rc_state == RCB_PENDING) { 177 ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list); 178 } else { 179 ATP_Q_REMOVE(atp->atp_rcb, rcbp, rc_list); 180 } 181 } 182 if (rcbp->rc_ioctl) { 183 gbuf_freem(rcbp->rc_ioctl); 184 rcbp->rc_ioctl = NULL; 185 } 186 rcbp->rc_list.next = atp_rcb_free_list; 187 atp_rcb_free_list = rcbp; 188} 189