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 * Reset.c
30 *
31 * From  v01.15 07/11/90 mbs
32 */
33/*
34 * Change log:
35 *   06/29/95 - Modified to handle flow control for writing (Tuyen Nguyen)
36 *    Modified for MP, 1996 by Tuyen Nguyen
37 *   Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
38 */
39
40#include <sys/errno.h>
41#include <sys/types.h>
42#include <sys/param.h>
43#include <machine/spl.h>
44#include <sys/systm.h>
45#include <sys/kernel.h>
46#include <sys/proc.h>
47#include <sys/filedesc.h>
48#include <sys/fcntl.h>
49#include <sys/mbuf.h>
50#include <sys/socket.h>
51#include <sys/time.h>
52
53#include <netat/sysglue.h>
54#include <netat/appletalk.h>
55#include <netat/at_pcb.h>
56#include <netat/debug.h>
57#include <netat/adsp.h>
58#include <netat/adsp_internal.h>
59
60/*
61 * RXFReset
62 *
63 * We just got a Forward Reset Packet.
64 *
65 * Called with interrupts OFF
66 *
67 * INPUTS:
68 *	stream pointer
69 *    	Pointer to ADSP header,
70 * OUTPUTS:
71 *	Returns 1 if packet was ignored
72 */
73int RXFReset(sp, f)		/* (CCBPtr sp, ADSP_FRAMEPtr f) */
74    CCBPtr sp;
75    ADSP_FRAMEPtr f;
76{
77    unsigned int pktFirstByteSeq;
78    unsigned int hi;
79    register gbuf_t *mp;
80    register struct adspcmd *pb;
81
82    pktFirstByteSeq = UAL_VALUE_NTOH(f->pktFirstByteSeq);
83
84    hi = sp->recvSeq + CalcRecvWdw(sp);
85
86    /*
87     * Must do this with interrupts OFF
88     */
89    if (BETWEEN(sp->recvSeq, pktFirstByteSeq, hi)) /* Is this acceptable? */
90    {
91	sp->recvSeq = pktFirstByteSeq;
92	while ((mp = sp->rbuf_mb)) { /* clear the receive queue */
93	    sp->rbuf_mb = gbuf_next(mp);
94	    gbuf_freem(mp);
95	}
96	if (sp->crbuf_mb) {
97	    gbuf_freem(sp->crbuf_mb);
98	    sp->crbuf_mb = 0;
99	}
100	sp->rData = 0;
101	sp->rbufFull = 0;
102	sp->userFlags |= eFwdReset; /* Set forward reset received Flag */
103
104	mp = gbuf_alloc(sizeof(struct adspcmd), PRI_HI);
105	pb = (struct adspcmd *)gbuf_rptr(mp);
106	gbuf_winc(mp,sizeof(struct adspcmd));
107	pb->ioc = 0;
108	pb->mp = mp;
109
110	pb->csCode = dspReset;
111	pb->ioResult = 0;
112	completepb(sp, pb);
113	sp->userFlags &= ~eFwdReset;
114    }
115
116    if (LTE(pktFirstByteSeq, hi)) {
117	sp->sendCtl |= B_CTL_FRESETACK;	/* Ack it if it's OK, or a duplicate */
118	sp->callSend = 1;
119    }
120
121    return 0;
122}
123
124
125/*
126 * RXFResetAck
127 *
128 * We just got a Forward Reset Acknowledgement packet
129 *
130 * Called with interrupts OFF
131 *
132 * INPUTS:
133 *	  stream pointer
134 *    Pointer to ADSP header,
135 * OUTPUTS:
136 *    Returns 1 if packet was ignored
137 */
138int RXFResetAck(sp, f)		/* (CCBPtr sp, ADSP_FRAMEPtr f) */
139    CCBPtr sp;
140    ADSP_FRAMEPtr f;
141{
142    unsigned int  PktNextRecvSeq;
143
144    if (sp->frpb == 0)		/* Not expecting frwd reset Ack packet */
145	return 1;
146
147    PktNextRecvSeq = UAL_VALUE_NTOH(f->pktNextRecvSeq);
148
149    if (BETWEEN(sp->sendSeq, PktNextRecvSeq, sp->sendWdwSeq+1)) {
150	struct adspcmd *pb;
151
152	RemoveTimerElem(&adspGlobal.fastTimers, &sp->ResetTimer);
153				/* Remove timer */
154
155	/*
156	 * Interrupts are OFF here while we muck with the linked list
157	 */
158	pb = sp->frpb;		/* Unlink copy of user's parameter block */
159	sp->frpb = (struct adspcmd *)pb->qLink;
160
161	pb->ioResult = 0;
162	completepb(sp, pb);	/* complete(pb, 0); */
163
164	if (sp->state == sClosing) /* this ack may allow us to close... */
165	    CheckOkToClose(sp);
166
167	if (sp->frpb)		/* Another to send? */
168	{
169	    sp->callSend = 1;
170	    sp->sendCtl |= B_CTL_FRESET;
171	}
172    }
173
174    return 0;
175}
176
177
178/*
179 * dspReset
180 *
181 * INPUTS:
182 * 	--> ccbRefNum		refnum of connection end
183 *
184 * OUTPUTS:
185 *	none
186 *
187 * ERRORS:
188 *	errRefNum		bad connection refnum
189 *	errState		connection is not open
190 *	errAborted		request aborted by Remove or Close call
191 */
192int adspReset(sp, pb)		/* (DSPPBPtr pb) */
193    CCBPtr sp;
194    struct adspcmd *pb;
195{
196    register gbuf_t *mp;
197    register struct adspcmd *rpb;
198
199    if (sp == 0) {
200	pb->ioResult = errRefNum;
201	return EINVAL;
202    }
203
204    if (sp->state != sOpen) {
205	pb->ioResult = errState;
206	return EINVAL;
207    }
208
209
210    while ((mp = sp->sbuf_mb)) { /* clear the send queue */
211	sp->sbuf_mb = gbuf_next(mp);
212	gbuf_freem(mp);
213    }
214    if (sp->csbuf_mb) {
215	gbuf_freem(sp->csbuf_mb);
216	sp->csbuf_mb = 0;
217    }
218    sp->sData = 0;
219    sp->writeFlush = 0;
220    sp->sendCtl |= B_CTL_FRESET;
221
222    sp->firstRtmtSeq = sp->sendSeq; /* Reset sequence #'s */
223    if ((mp = gbuf_copym(pb->mp))) {	/* copy the parameter block */
224	    adspioc_ack(0, (gbuf_t *)pb->ioc, pb->gref); /* release user */
225	    rpb = (struct adspcmd *)gbuf_rptr(mp);
226	    rpb->ioc = 0;		/* unlink copy */
227	    rpb->mp = mp;
228
229	    qAddToEnd((struct qlink **)&sp->frpb, (struct qlink *)rpb);
230				/* Hold on to pb (will be completed when */
231				/* forward reset ack is received). */
232    } else {			/* assume it will work... but keep no
233				 * bookkeeping for it.  yetch! */
234	    adspioc_ack(0, (gbuf_t *)pb->ioc, pb->gref);
235    }
236
237    CheckSend(sp);
238    return STR_IGNORE;
239
240}
241