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