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 * RxAttn.c 30 * 31 * From v01.12 06/12/90 mbs 32 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX. 33 */ 34 35#include <sys/errno.h> 36#include <sys/types.h> 37#include <sys/param.h> 38#include <machine/spl.h> 39#include <sys/systm.h> 40#include <sys/kernel.h> 41#include <sys/proc.h> 42#include <sys/filedesc.h> 43#include <sys/fcntl.h> 44#include <sys/mbuf.h> 45#include <sys/socket.h> 46#include <sys/time.h> 47 48#include <netat/sysglue.h> 49#include <netat/appletalk.h> 50#include <netat/at_pcb.h> 51#include <netat/debug.h> 52#include <netat/adsp.h> 53#include <netat/adsp_internal.h> 54 55/* 56 * Used to search down queue of sessions for a session that matches 57 * sender and source connection ID 58*/ 59typedef struct 60{ 61 AddrUnion addr; 62 word srcCID; 63} MATCH_SENDER, *MATCH_SENDERPtr; 64 65/* 66 * MatchSender 67 * 68 */ 69static boolean MatchSender(CCBPtr, MATCH_SENDERPtr); 70 71static boolean MatchSender(sp, m) /* (CCBPtr sp, MATCH_SENDERPtr m) */ 72 CCBPtr sp; 73 MATCH_SENDERPtr m; 74{ 75 76 if (sp->state != sOpen && sp->state != sClosing) 77 return 0; 78 79 if (sp->remCID != m->srcCID) 80 return 0; 81 82 if (sp->remoteAddress.a.node != m->addr.a.node) 83 return 0; 84 if (sp->remoteAddress.a.socket != m->addr.a.socket) 85 return 0; 86 if (sp->remoteAddress.a.net && m->addr.a.net && 87 (sp->remoteAddress.a.net != m->addr.a.net)) 88 return 0; 89 90 return 1; 91} 92 93 94/* 95 * FindSender 96 * 97 * Given an ADSP Packet, find the stream it is associated with. 98 * 99 * This should only be used for ADSP Packets that could be received 100 * by an OPEN connection. 101 * 102 * INPUTS: 103 * Pointer to ADSP header & address of sender 104 * OUTPUTS: 105 * Pointer to stream if found, else 0 106 */ 107CCBPtr FindSender(f, a) /* (ADSP_FRAMEPtr f, AddrUnion a) */ 108 ADSP_FRAMEPtr f; 109 AddrUnion a; 110{ 111 MATCH_SENDER m; 112 113 m.addr = a; 114 m.srcCID = UAS_VALUE_NTOH(f->CID); 115 return (CCBPtr)qfind_m((CCB *)AT_ADSP_STREAMS, &m, (ProcPtr)MatchSender); 116} 117 118/* 119 * RXAttention 120 * 121 * We just got an Attention Packet. 122 * See if it came from anybody we know. 123 * Then check to see if it is an attention data packet or acknowledgement 124 * 125 * Interrupts are masked OFF at this point. 126 * 127 * INPUTS: 128 * stream pointer 129 * Pointer to ADSP header, 130 * Length of header plus data 131 * OUTPUTS: 132 * Returns 1 if packet was ignored 133 */ 134int RXAttention(sp, mp, f, len) /* (CCBPtr sp, ADSP_FRAMEPtr f, word len) */ 135 CCBPtr sp; 136 gbuf_t *mp; 137 ADSP_FRAMEPtr f; 138 int len; 139{ 140 int offset; 141 struct adspcmd *pb; 142 long diff; 143 144 if (UAS_VALUE(f->pktRecvWdw)) /* This field must be 0 in attn pkts */ 145 return 1; 146 147 if ((f->descriptor == 148 (char)(ADSP_ATTENTION_BIT | ADSP_ACK_REQ_BIT)) && /* Attention Data */ 149 ((sp->userFlags & eAttention) == 0)) /* & they read the previous */ 150 { 151 diff = UAL_VALUE_NTOH(f->pktFirstByteSeq) - sp->attnRecvSeq; 152 if (diff > 0) /* Hey, he missed one */ 153 return 1; 154 155 if (diff == 0) /* This is the one we expected */ 156 { 157 len -= ADSP_FRAME_LEN; /* remove adsp header */ 158 if (len < 2) /* Poorly formed attn packet */ 159 return 1; 160 sp->attnCode = (f->data[0] << 8) + f->data[1]; /* Save attn code */ 161 sp->attn_mb = mp; 162 offset = ((unsigned char *)&f->data[2]) - (unsigned char *)gbuf_rptr(mp); 163 gbuf_rinc(mp,offset); 164 sp->attnPtr = (unsigned char *)gbuf_rptr(mp); 165 mp = 0; /* mp has been queued don't free it */ 166 167 /* Interrupts are off here, or otherwise we have to do 168 * these three operations automically. 169 */ 170 sp->attnSize = len - 2; /* Tell user how many bytes */ 171 ++sp->attnRecvSeq; 172 /* Set flag saying we got attn message */ 173 sp->userFlags |= eAttention; 174 UrgentUser(sp); /* Notify user */ 175 /* BEFORE sending acknowledge */ 176 } /* in sequence */ 177 178 sp->sendAttnAck = 1; /* send attention ack for dupl. & 179 * expected data */ 180 sp->callSend = 1; 181 } /* Attn Data */ 182 183 /* 184 * Interrupts are OFF here, otherwise we have to do this atomically 185 */ 186 /* Check to see if this acknowledges anything */ 187 if ((sp->attnSendSeq + 1) == UAL_VALUE_NTOH(f->pktNextRecvSeq)) { 188 sp->attnSendSeq++; 189 if ((pb = sp->sapb) == 0) { /* We never sent data ? !!! */ 190 if (mp) 191 gbuf_freem(mp); 192 return 0; 193 } 194 195 sp->sapb = (struct adspcmd *)pb->qLink; /* Unlink from queue */ 196 197 /* Remove timer */ 198 RemoveTimerElem(&adspGlobal.fastTimers, &sp->AttnTimer); 199 200 pb->ioResult = 0; 201 if (gbuf_cont(pb->mp)) { 202 gbuf_freem(gbuf_cont(pb->mp)); /* free the data */ 203 gbuf_cont(pb->mp) = 0; 204 } 205 completepb(sp, pb); /* Done with the send attention */ 206 207 if (sp->sapb) { /* Another send attention pending? */ 208 sp->sendAttnData = 1; 209 sp->callSend = 1; 210 } else { 211 if (sp->state == sClosing) /* this ack may allow us to close... */ 212 CheckOkToClose(sp); 213 } 214 } 215 if (mp) 216 gbuf_freem(mp); 217 return 0; 218} 219