|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1996-1998 Apple Computer, Inc.
27: * All Rights Reserved.
28: *
29: * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF APPLE COMPUTER, INC.
30: * The copyright notice above does not evidence any actual or
31: * intended publication of such source code.
32: */
33:
34: #include <appletalk.h>
35: #include <atp.h>
36: #include <ddp.h>
37: #include <at_atp.h>
38: #include <atp_inc.h>
39:
40: extern atlock_t atpgen_lock;
41: void atp_free();
42: void atp_send(struct atp_trans *);
43:
44: /*
45: * The request timer retries a request, if all retries are used up
46: * it returns a NAK
47: */
48:
49: void
50: atp_req_timeout(trp)
51: register struct atp_trans *trp;
52: {
53: int s;
54: register gbuf_t *m;
55: gref_t *gref;
56: struct atp_state *atp;
57: struct atp_trans *ctrp;
58:
59: if ((atp = trp->tr_queue) == 0)
60: return;
61: ATDISABLE(s, atp->atp_lock);
62: if (atp->atp_flags & ATP_CLOSING) {
63: ATENABLE(s, atp->atp_lock);
64: return;
65: }
66: for (ctrp = atp->atp_trans_wait.head; ctrp; ctrp = ctrp->tr_list.next) {
67: if (ctrp == trp)
68: break;
69: }
70: if (ctrp != trp) {
71: ATENABLE(s, atp->atp_lock);
72: return;
73: }
74:
75: if ((m = gbuf_cont(trp->tr_xmt)) == NULL)
76: m = trp->tr_xmt; /* issued via the new interface */
77:
78: if (trp->tr_retry == 0) {
79: trp->tr_state = TRANS_FAILED;
80: if (m == trp->tr_xmt) {
81: trp->tr_xmt = NULL;
82: l_notify:
83: gbuf_wset(m,1);
84: *gbuf_rptr(m) = 99;
85: gbuf_set_type(m, MSG_DATA);
86: gref = trp->tr_queue->atp_gref;
87: ATENABLE(s, atp->atp_lock);
88: atalk_putnext(gref, m);
89:
90: return;
91: }
92: dPrintf(D_M_ATP_LOW,D_L_INFO, ("atp_req_timeout: skt=%d\n",
93: trp->tr_local_socket));
94: m = trp->tr_xmt;
95: switch(((ioc_t *)(gbuf_rptr(trp->tr_xmt)))->ioc_cmd) {
96: case AT_ATP_ISSUE_REQUEST:
97: trp->tr_xmt = NULL;
98: if (trp->tr_queue->dflag)
99: ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_REQUEST_COMPLETE;
100: else if (trp->tr_bdsp == NULL) {
101: ATENABLE(s, atp->atp_lock);
102: gbuf_freem(m);
103: if (trp->tr_rsp_wait)
104: #ifdef _AIX
105: e_wakeup(&trp->tr_event);
106: #else
107: thread_wakeup(&trp->tr_event);
108: #endif
109: break;
110: }
111: ATENABLE(s, atp->atp_lock);
112: atp_iocnak(trp->tr_queue, m, ETIMEDOUT);
113: atp_free(trp);
114: return;
115:
116: case AT_ATP_ISSUE_REQUEST_NOTE:
117: case AT_ATP_ISSUE_REQUEST_DEF_NOTE:
118: /* AT_ATP_ISSUE_REQUEST_DEF_NOTE is used just for tickle */
119: trp->tr_xmt = gbuf_cont(m);
120: gbuf_cont(m) = NULL;
121: goto l_notify;
122: }
123: } else {
124: (AT_ATP_HDR(m))->bitmap = trp->tr_bitmap;
125:
126: if (trp->tr_retry != (unsigned int) ATP_INFINITE_RETRIES)
127: trp->tr_retry--;
128: ATENABLE(s, atp->atp_lock);
129: atp_send(trp);
130: }
131: }
132:
133:
134: /*
135: * atp_free frees up a request, cleaning up the queues and freeing
136: * the request packet
137: * always called at 'lock'
138: */
139:
140: void atp_free(trp)
141: register struct atp_trans *trp;
142: {
143: register struct atp_state *atp;
144: register int i;
145: int s;
146:
147: dPrintf(D_M_ATP_LOW, D_L_TRACE,
148: ("atp_free: freeing trp 0x%x\n", (u_int) trp));
149: ATDISABLE(s, atpgen_lock);
150: if (trp->tr_tmo_func)
151: atp_untimout(atp_req_timeout, trp);
152: atp = trp->tr_queue;
153:
154: ATP_Q_REMOVE(atp->atp_trans_wait, trp, tr_list);
155:
156: if (trp->tr_xmt) {
157: gbuf_freem(trp->tr_xmt);
158: trp->tr_xmt = NULL;
159: }
160: for (i = 0; i < 8; i++) {
161: if (trp->tr_rcv[i]) {
162: gbuf_freem(trp->tr_rcv[i]);
163: trp->tr_rcv[i] = NULL;
164: }
165: }
166: if (trp->tr_bdsp) {
167: gbuf_freem(trp->tr_bdsp);
168: trp->tr_bdsp = NULL;
169: }
170:
171: ATENABLE(s, atpgen_lock);
172: atp_trans_free(trp);
173:
174: } /* atp_free */
175:
176:
177: /*
178: * atp_send transmits a request packet by queuing it (if it isn't already) and
179: * scheduling the queue
180: */
181:
182: void atp_send(trp)
183: register struct atp_trans *trp;
184: {
185: gbuf_t *m;
186: struct atp_state *atp;
187:
188: dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ("atp_send: trp=0x%x, skt=%d\n",
189: (u_int) trp->tr_queue, trp->tr_local_socket));
190:
191: if ((atp = trp->tr_queue) != 0) {
192: if (trp->tr_state == TRANS_TIMEOUT) {
193: if ((m = gbuf_cont(trp->tr_xmt)) == NULL)
194: m = trp->tr_xmt;
195:
196: /*
197: * Now either release the transaction or start the timer
198: */
199: if (!trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo) {
200: m = (gbuf_t *)gbuf_copym(m);
201: atp_x_done(trp);
202: } else {
203: m = (gbuf_t *)gbuf_dupm(m);
204:
205: atp_timout(atp_req_timeout, trp, trp->tr_timeout);
206: }
207:
208: if (m)
209: DDP_OUTPUT(m);
210: }
211: }
212: }
213:
214:
215: /*
216: * atp_reply sends all the available messages in the bitmap again
217: * by queueing us to the write service routine
218: */
219:
220: void atp_reply(rcbp)
221: register struct atp_rcb *rcbp;
222: {
223: register struct atp_state *atp;
224: register int i;
225: int s;
226:
227: if ((atp = rcbp->rc_queue) != 0) {
228: ATDISABLE(s, atp->atp_lock);
229: for (i = 0; i < rcbp->rc_pktcnt; i++) {
230: if (rcbp->rc_bitmap&atp_mask[i])
231: rcbp->rc_snd[i] = 1;
232: else
233: rcbp->rc_snd[i] = 0;
234: }
235: if (rcbp->rc_rep_waiting == 0) {
236: rcbp->rc_state = RCB_SENDING;
237: rcbp->rc_rep_waiting = 1;
238: ATENABLE(s, atp->atp_lock);
239: atp_send_replies(atp, rcbp);
240: } else
241: ATENABLE(s, atp->atp_lock);
242: }
243: }
244:
245:
246: /*
247: * The rcb timer just frees the rcb, this happens when we missed a release for XO
248: */
249:
250: void atp_rcb_timer()
251: {
252: int s;
253: register struct atp_rcb *rcbp;
254: register struct atp_rcb *next_rcbp;
255: extern struct atp_rcb_qhead atp_need_rel;
256: extern struct atp_trans *trp_tmo_rcb;
257:
258: l_again:
259: ATDISABLE(s, atpgen_lock);
260: for (rcbp = atp_need_rel.head; rcbp; rcbp = next_rcbp) {
261: next_rcbp = rcbp->rc_tlist.next;
262:
263: if (abs(time.tv_sec - rcbp->rc_timestamp) > 30) {
264: ATENABLE(s, atpgen_lock);
265: atp_rcb_free(rcbp);
266: goto l_again;
267: }
268: }
269: ATENABLE(s, atpgen_lock);
270: atp_timout(atp_rcb_timer, trp_tmo_rcb, 10 * HZ);
271: }
272:
273: atp_iocack(atp, m)
274: struct atp_state *atp;
275: register gbuf_t *m;
276: {
277: if (gbuf_type(m) == MSG_IOCTL)
278: gbuf_set_type(m, MSG_IOCACK);
279: if (gbuf_cont(m))
280: ((ioc_t *)gbuf_rptr(m))->ioc_count = gbuf_msgsize(gbuf_cont(m));
281: else
282: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
283:
284: if (atp->dflag)
285: asp_ack_reply(atp->atp_gref, m);
286: else
287: atalk_putnext(atp->atp_gref, m);
288: }
289:
290: atp_iocnak(atp, m, err)
291: struct atp_state *atp;
292: register gbuf_t *m;
293: register int err;
294: {
295: if (gbuf_type(m) == MSG_IOCTL)
296: gbuf_set_type(m, MSG_IOCNAK);
297: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
298: ((ioc_t *)gbuf_rptr(m))->ioc_error = err ? err : ENXIO;
299: ((ioc_t *)gbuf_rptr(m))->ioc_rval = -1;
300: if (gbuf_cont(m)) {
301: gbuf_freem(gbuf_cont(m));
302: gbuf_cont(m) = NULL;
303: }
304:
305: if (atp->dflag)
306: asp_nak_reply(atp->atp_gref, m);
307: else
308: atalk_putnext(atp->atp_gref, m);
309: }
310:
311: /*
312: * Generate a transaction id for a socket
313: */
314: static int lasttid;
315: atp_tid(atp)
316: register struct atp_state *atp;
317: {
318: register int i;
319: register struct atp_trans *trp;
320: int s;
321:
322: ATDISABLE(s, atpgen_lock);
323: for (i = lasttid;;) {
324: i = (i+1)&0xffff;
325:
326: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
327: if (trp->tr_tid == i)
328: break;
329: }
330: if (trp == NULL) {
331: lasttid = i;
332: ATENABLE(s, atpgen_lock);
333: return(i);
334: }
335: }
336: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.