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#define ATP_DECLARE 37 38#include <sys/errno.h> 39#include <sys/types.h> 40#include <sys/param.h> 41#include <machine/spl.h> 42#include <sys/systm.h> 43#include <sys/kernel.h> 44#include <sys/proc.h> 45#include <sys/filedesc.h> 46#include <sys/fcntl.h> 47#include <sys/mbuf.h> 48#include <sys/ioctl.h> 49#include <sys/malloc.h> 50#include <sys/socket.h> 51#include <vm/vm_kern.h> /* for kernel_map */ 52 53#include <netat/sysglue.h> 54#include <netat/appletalk.h> 55#include <netat/ddp.h> 56#include <netat/at_pcb.h> 57#include <netat/atp.h> 58#include <netat/asp.h> 59#include <netat/debug.h> 60 61/* 62 * The init routine creates all the free lists 63 * Version 1.4 of atp_open.c on 89/02/09 17:53:11 64 */ 65 66int atp_inited = 0; 67struct atp_rcb_qhead atp_need_rel; 68 69/**********/ 70int atp_pidM[256]; 71gref_t *atp_inputQ[256]; 72struct atp_state *atp_used_list; 73 74int atp_input(mp) 75 gbuf_t *mp; 76{ 77 register gref_t *gref; 78 79 switch (gbuf_type(mp)) { 80 case MSG_DATA: 81 gref = atp_inputQ[((at_ddp_t *)gbuf_rptr(mp))->dst_socket]; 82 if ((gref == 0) || (gref == (gref_t *)1)) { 83 dPrintf(D_M_ATP, D_L_WARNING, ("atp_input: no socket, skt=%d\n", 84 ((at_ddp_t *)gbuf_rptr(mp))->dst_socket)); 85 gbuf_freem(mp); 86 return 0; 87 } 88 break; 89 90 case MSG_IOCACK: 91 case MSG_IOCNAK: 92 gref = (gref_t *)((ioc_t *)gbuf_rptr(mp))->ioc_private; 93 break; 94 95 case MSG_IOCTL: 96 default: 97 dPrintf(D_M_ATP, D_L_WARNING, ("atp_input: unknown msg, type=%d\n", 98 gbuf_type(mp))); 99 gbuf_freem(mp); 100 return 0; 101 } 102 103 atp_rput(gref, mp); 104 return 0; 105} 106 107/**********/ 108void atp_init(void) 109{ 110 if (!atp_inited) { 111 atp_inited = 1; 112 atp_used_list = 0; 113 atp_trans_abort.head = NULL; 114 atp_trans_abort.tail = NULL; 115 116 atp_need_rel.head = NULL; 117 atp_need_rel.tail = NULL; 118 119 bzero(atp_inputQ, sizeof(atp_inputQ)); 120 bzero(atp_pidM, sizeof(atp_pidM)); 121 asp_init(); 122 } 123} 124 125/* 126 * The open routine allocates a state structure 127 */ 128 129/*ARGSUSED*/ 130int atp_open(gref, flag) 131 gref_t *gref; 132 int flag; 133{ 134 register struct atp_state *atp; 135 register int i; 136 vm_offset_t temp; 137 138 /* 139 * Allocate and init state and reply control block lists 140 * if this is the first open 141 */ 142 if (atp_rcb_data == NULL) { 143 if (kmem_alloc(kernel_map, &temp, sizeof(struct atp_rcb) * NATP_RCB) != KERN_SUCCESS) 144 return(ENOMEM); 145 if (atp_rcb_data == NULL) { 146 bzero((caddr_t)temp, sizeof(struct atp_rcb) * NATP_RCB); 147 atp_rcb_data = (struct atp_rcb*)temp; 148 for (i = 0; i < NATP_RCB; i++) { 149 atp_rcb_data[i].rc_list.next = atp_rcb_free_list; 150 atp_rcb_free_list = &atp_rcb_data[i]; 151 } 152 } else 153 kmem_free(kernel_map, temp, sizeof(struct atp_rcb) * NATP_RCB); /* already allocated by another process */ 154 } 155 156 if (atp_state_data == NULL) { 157 if (kmem_alloc(kernel_map, &temp, sizeof(struct atp_state) * NATP_STATE) != KERN_SUCCESS) 158 return(ENOMEM); 159 if (atp_state_data == NULL) { 160 bzero((caddr_t)temp, sizeof(struct atp_state) * NATP_STATE); 161 atp_state_data = (struct atp_state*) temp; 162 for (i = 0; i < NATP_STATE; i++) { 163 atp_state_data[i].atp_trans_waiting = atp_free_list; 164 atp_free_list = &atp_state_data[i]; 165 } 166 } else 167 kmem_free(kernel_map, temp, sizeof(struct atp_state) * NATP_STATE); 168 } 169 170 171 /* 172 * If no atp structure available return failure 173 */ 174 175 if ((atp = atp_free_list) == NULL) 176 return(EAGAIN); 177 178 /* 179 * Update free list 180 */ 181 182 atp_free_list = atp->atp_trans_waiting; 183 184 /* 185 * Initialize the data structure 186 */ 187 188 atp->dflag = 0; 189 atp->atp_trans_wait.head = NULL; 190 atp->atp_trans_waiting = NULL; 191 atp->atp_gref = gref; 192 atp->atp_retry = 10; 193 atp->atp_timeout = HZ/8; 194 atp->atp_rcb_waiting = NULL; 195 atp->atp_rcb.head = NULL; 196 atp->atp_attached.head = NULL; 197 atp->atp_flags = T_MPSAFE; 198 atp->atp_socket_no = -1; 199 atp->atp_pid = gref->pid; 200 atp->atp_msgq = 0; 201 ATEVENTINIT(atp->atp_event); 202 ATEVENTINIT(atp->atp_delay_event); 203 gref->info = (void *)atp; 204 205 /* 206 * Return success 207 */ 208 209 if (flag) { 210 if ((atp->atp_trans_waiting = atp_used_list) != 0) 211 atp->atp_trans_waiting->atp_rcb_waiting = atp; 212 atp_used_list = atp; 213 } 214 return(0); 215} 216 217/* 218 * The close routine frees all the data structures 219 */ 220 221/*ARGSUSED*/ 222int atp_close(gref, flag) 223 gref_t *gref; 224 int flag; 225{ 226 register struct atp_state *atp; 227 register struct atp_trans *trp; 228 register struct atp_rcb *rcbp; 229 int socket; 230 pid_t pid; 231 232 atp = (struct atp_state *)gref->info; 233 if (atp->dflag) 234 atp = (struct atp_state *)atp->atp_msgq; 235 if (atp->atp_msgq) { 236 gbuf_freem(atp->atp_msgq); 237 atp->atp_msgq = 0; 238 } 239 240 atp->atp_flags |= ATP_CLOSING; 241 socket = atp->atp_socket_no; 242 if (socket != -1) 243 atp_inputQ[socket] = (gref_t *)1; 244 245 /* 246 * blow away all pending timers 247 */ 248 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) 249 atp_untimout(atp_req_timeout, trp); 250 251 /* 252 * Release pending transactions + rcbs 253 */ 254 while ((trp = atp->atp_trans_wait.head)) 255 atp_free(trp); 256 while ((rcbp = atp->atp_rcb.head)) 257 atp_rcb_free(rcbp); 258 while ((rcbp = atp->atp_attached.head)) 259 atp_rcb_free(rcbp); 260 261 if (flag && (socket == -1)) 262 atp_dequeue_atp(atp); 263 264 /* 265 * free the state variable 266 */ 267 atp->atp_socket_no = -1; 268 atp->atp_trans_waiting = atp_free_list; 269 atp_free_list = atp; 270 271 if (socket != -1) { 272 pid = (pid_t)atp_pidM[socket]; 273 atp_pidM[socket] = 0; 274 atp_inputQ[socket] = NULL; 275 if (pid) 276 ddp_notify_nbp(socket, pid, DDP_ATP); 277 } 278 279 return 0; 280} 281