|
|
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: #define RESOLVE_DBG
35:
36: #include <appletalk.h>
37: #include <atp.h>
38: #include <at_atp.h>
39: #include <atp_inc.h>
40: #include <lap.h>
41: #include <at_lap.h>
42: #include <ddp.h>
43: #include <at_ddp.h>
44: #include <at_asp.h>
45: #include <adsp_frames.h>
46: #include <atlog.h>
47:
48: static void atp_pack_bdsp(struct atp_trans *, struct atpBDS *);
49: static int atp_unpack_bdsp(struct atp_state *, gbuf_t *, struct atp_rcb *,
50: int, int);
51:
52: extern struct atp_rcb_qhead atp_need_rel;
53: extern int atp_inited;
54: extern char atp_off_flag;
55: extern struct atp_state *atp_used_list;
56: extern atlock_t atpgen_lock;
57: extern atlock_t atpall_lock;
58: extern atlock_t atptmo_lock;
59:
60: extern gref_t *atp_inputQ[];
61: extern int atp_pidM[];
62: extern char ot_atp_socketM[];
63: extern char ddp_off_flag;
64: extern int ot_protoCnt;
65: extern char ot_protoT[];
66:
67: static struct atp_trans *trp_tmo_list;
68: struct atp_trans *trp_tmo_rcb;
69:
70: /*
71: * write queue put routine .... filter out other than IOCTLs
72: * Version 1.8 of atp_write.c on 89/02/09 17:53:26
73: */
74:
75: void
76: atp_wput(gref, m)
77: register gref_t *gref;
78: register gbuf_t *m;
79: {
80: register ioc_t *iocbp;
81: int i, xcnt, s;
82: struct atp_state *atp;
83: struct atp_trans *trp;
84: struct atp_rcb *rcbp;
85: at_socket skt;
86:
87: atp = (struct atp_state *)gref->info;
88: if (atp->dflag)
89: atp = (struct atp_state *)atp->atp_msgq;
90:
91: switch(gbuf_type(m)) {
92: case MSG_DATA:
93: if (atp->atp_msgq) {
94: gbuf_freem(m);
95: dPrintf(D_M_ATP, D_L_WARNING,
96: ("atp_wput: atp_msgq discarded\n"));
97: } else
98: atp->atp_msgq = m;
99: break;
100:
101: case MSG_IOCTL:
102: /* Need to ensure that all copyin/copyout calls are made at
103: * put routine time which should be in the user context. (true when
104: * we are the stream head). The service routine can be called on an
105: * unpredictable context and copyin/copyout calls will get wrong results
106: * or even panic the kernel.
107: */
108: iocbp = (ioc_t *)gbuf_rptr(m);
109:
110: switch (iocbp->ioc_cmd) {
111: case AT_ATP_LINK:
112: atp_dequeue_atp(atp);
113: ot_protoT[DDP_ATP] = 1;
114: ot_protoCnt++;
115:
116: iocbp->ioc_rval = 0;
117: atp_iocack(atp, m);
118: trp_tmo_list = 0;
119: trp_tmo_rcb = atp_trans_alloc(0);
120: atp_timout(atp_rcb_timer, trp_tmo_rcb, 10 * HZ);
121: atp_trp_timer(&atp_inited, 0);
122: asp_timer(&atp_inited, 0);
123: return;
124:
125: case AT_ATP_UNLINK:
126: ot_protoT[DDP_ATP] = 0;
127: ot_protoCnt--;
128: ddp_off_flag = 0; /* why clear this in an unlink? */
129:
130: trp_tmo_list = 0;
131: atp_trp_timer(&atp_inited, 1);
132: asp_timer(&atp_inited, 1);
133: atp_inited = 0;
134: iocbp->ioc_rval = 0;
135: atp_iocack(atp, m);
136: return;
137:
138: case AT_ATP_BIND_REQ:
139: if (gbuf_cont(m) == NULL) {
140: iocbp->ioc_rval = -1;
141: atp_iocnak(atp, m, EINVAL);
142: return;
143: }
144: skt = *(at_socket *)gbuf_rptr(gbuf_cont(m));
145: if ((skt = (at_socket)atp_bind(gref, (unsigned int)skt, 0)) == 0)
146: atp_iocnak(atp, m, EINVAL);
147: else {
148: *(at_socket *)gbuf_rptr(gbuf_cont(m)) = skt;
149: iocbp->ioc_rval = 0;
150: atp_iocack(atp, m);
151: atp_dequeue_atp(atp);
152: }
153: return;
154:
155: case AT_ATP_GET_CHANID:
156: if (gbuf_cont(m) == NULL) {
157: iocbp->ioc_rval = -1;
158: atp_iocnak(atp, m, EINVAL);
159: return;
160: }
161: *(gref_t **)gbuf_rptr(gbuf_cont(m)) = gref;
162: atp_iocack(atp, m);
163: return;
164:
165: case AT_ATP_ISSUE_REQUEST_DEF:
166: /* case AT_ATP_ISSUE_REQUEST_DEF_NOTE: not actually XO */
167: /* AT_ATP_ISSUE_REQUEST_DEF_NOTE is used just for tickle
168: so it's not appropriate to check for it here
169: */
170: {
171: #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
172: gbuf_t *bds, *tmp;
173:
174: if ((tmp = gbuf_cont(m)) != 0) {
175: if ((bds = gbuf_dupb(tmp)) == NULL) {
176: atp_iocnak(atp, m, ENOBUFS);
177: return;
178: }
179: gbuf_rinc(tmp,atpBDSsize);
180: gbuf_wset(bds,atpBDSsize);
181: iocbp->ioc_count -= atpBDSsize;
182: gbuf_cont(tmp) = bds;
183: }
184: /* FALL THRU */
185: }
186:
187: case AT_ATP_SEND_FULL_RESPONSE: {
188: gbuf_t *m2;
189: struct atp_rcb *rcbp;
190: at_ddp_t *ddp;
191: at_atp_t *athp;
192:
193: /*
194: * send a response to a transaction
195: * first check it out
196: */
197: if (iocbp->ioc_count < TOTAL_ATP_HDR_SIZE) {
198: atp_iocnak(atp, m, EINVAL);
199: break;
200: }
201:
202: /*
203: * remove the response from the message
204: */
205: m2 = gbuf_cont(m);
206: gbuf_cont(m) = NULL;
207: iocbp->ioc_count = 0;
208: ddp = AT_DDP_HDR(m2);
209: athp = AT_ATP_HDR(m2);
210: if (atp->atp_msgq) {
211: gbuf_cont(m2) = atp->atp_msgq;
212: atp->atp_msgq = 0;
213: }
214:
215: ATDISABLE(s, atp->atp_lock);
216: /*
217: * search for the corresponding rcb
218: */
219: for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
220: if (rcbp->rc_tid == UAS_VALUE(athp->tid) &&
221: rcbp->rc_socket.node == ddp->dst_node &&
222: rcbp->rc_socket.net == NET_VALUE(ddp->dst_net) &&
223: rcbp->rc_socket.socket == ddp->dst_socket)
224: break;
225: }
226: ATENABLE(s, atp->atp_lock);
227:
228: /*
229: * If it has already been sent then return an error
230: */
231: if ((rcbp && rcbp->rc_state != RCB_NOTIFIED) ||
232: (rcbp == NULL && athp->xo)) {
233: atp_iocnak(atp, m, ENOENT);
234: gbuf_freem(m2);
235: return;
236: }
237: if (rcbp == NULL) { /* a response for an ALO transaction */
238: if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
239: atp_iocnak(atp, m, ENOBUFS);
240: gbuf_freem(m2);
241: return;
242: }
243: rcbp->rc_ioctl = 0;
244: rcbp->rc_socket.socket = ddp->dst_socket;
245: rcbp->rc_socket.node = ddp->dst_node;
246: rcbp->rc_socket.net = NET_VALUE(ddp->dst_net);
247: rcbp->rc_tid = UAS_VALUE(athp->tid);
248: rcbp->rc_bitmap = 0xff;
249: rcbp->rc_xo = 0;
250: ATDISABLE(s, atp->atp_lock);
251: rcbp->rc_state = RCB_SENDING;
252: ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
253: ATENABLE(s, atp->atp_lock);
254: }
255: /* first bds entry gives number of bds
256: * entries in total (hack)
257: */
258: if (gbuf_len(m2) > TOTAL_ATP_HDR_SIZE)
259: xcnt = UAS_VALUE(((struct atpBDS *)
260: (AT_ATP_HDR(m2)->data))->bdsDataSz);
261: else
262: xcnt = 0;
263: if ((i = atp_unpack_bdsp(atp, m2, rcbp, xcnt, FALSE))) {
264: if ( !rcbp->rc_xo)
265: atp_rcb_free(rcbp);
266: atp_iocnak(atp, m, i);
267: return;
268: }
269: atp_send_replies(atp, rcbp);
270:
271: /*
272: * send the ack back to the responder
273: */
274: atp_iocack(atp, m);
275: return;
276: }
277:
278: case AT_ATP_GET_POLL: {
279: if (gbuf_cont(m)) {
280: gbuf_freem(gbuf_cont(m));
281: gbuf_cont(m) = NULL;
282: iocbp->ioc_count = 0;
283: }
284:
285: /*
286: * search for a waiting request
287: */
288: ATDISABLE(s, atp->atp_lock);
289: if ((rcbp = atp->atp_attached.head)) {
290: /*
291: * Got one, move it to the active response Q
292: */
293: gbuf_cont(m) = rcbp->rc_ioctl;
294: rcbp->rc_ioctl = NULL;
295: if (rcbp->rc_xo) {
296: ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
297: rcbp->rc_state = RCB_NOTIFIED;
298: ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
299: } else {
300: /* detach rcbp from attached queue,
301: * and free any outstanding resources
302: */
303: atp_rcb_free(rcbp);
304: }
305: ATENABLE(s, atp->atp_lock);
306: atp_iocack(atp, m);
307: } else {
308: /*
309: * None available - can out
310: */
311: ATENABLE(s, atp->atp_lock);
312: atp_iocnak(atp, m, EAGAIN);
313: }
314: break;
315: }
316:
317: case AT_ATP_CANCEL_REQUEST: {
318: /*
319: * Cancel a pending request
320: */
321: if (iocbp->ioc_count != sizeof(int)) {
322: atp_iocnak(atp, m, EINVAL);
323: break;
324: }
325: i = *(int *)gbuf_rptr(gbuf_cont(m));
326: gbuf_freem(gbuf_cont(m));
327: gbuf_cont(m) = NULL;
328: ATDISABLE(s, atp->atp_lock);
329: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
330: if (trp->tr_tid == i)
331: break;
332: }
333: if (trp == NULL) {
334: ATENABLE(s, atp->atp_lock);
335: atp_iocnak(atp, m, ENOENT);
336: } else {
337: ATENABLE(s, atp->atp_lock);
338: atp_free(trp);
339: atp_iocack(atp, m);
340: }
341: break;
342: }
343:
344: case AT_ATP_PEEK: {
345: unsigned char event;
346: if (atalk_peek(gref, &event) == -1)
347: atp_iocnak(atp, m, ENOMSG);
348: else {
349: *gbuf_rptr(gbuf_cont(m)) = event;
350: atp_iocack(atp, m);
351: }
352: break;
353: }
354:
355: default:
356: /*
357: * Otherwise pass it on, if possible
358: */
359: iocbp->ioc_private = (void *)gref;
360: if (iocbp->ioc_cmd == DDP_IOC_GET_CFG) {
361: iocbp->ioc_count = atp->atp_socket_no;
362: iocbp->ioc_error = 3;
363: }
364: DDP_OUTPUT(m);
365: break;
366: }
367: break;
368:
369: default:
370: gbuf_freem(m);
371: break;
372: }
373: } /* atp_wput */
374:
375: gbuf_t *atp_build_release(trp)
376: register struct atp_trans *trp;
377: {
378: register gbuf_t *m;
379: register at_ddp_t *ddp;
380: register at_atp_t *athp;
381:
382: /*
383: * Now try and allocate enough space to send the message
384: * if none is available the caller will schedule
385: * a timeout so we can retry for more space soon
386: */
387: if ((m = (gbuf_t *)gbuf_alloc(AT_WR_OFFSET+ATP_HDR_SIZE, PRI_HI)) != NULL) {
388: gbuf_rinc(m,AT_WR_OFFSET);
389: gbuf_wset(m,TOTAL_ATP_HDR_SIZE);
390: ddp = AT_DDP_HDR(m);
391: ddp->type = DDP_ATP;
392: UAS_ASSIGN(ddp->checksum, 0);
393: ddp->dst_socket = trp->tr_socket.socket;
394: ddp->dst_node = trp->tr_socket.node;
395: NET_ASSIGN(ddp->dst_net, trp->tr_socket.net);
396: ddp->src_node = trp->tr_local_node;
397: NET_NET(ddp->src_net, trp->tr_local_net);
398:
399: /*
400: * clear the cmd/xo/eom/sts/unused fields
401: */
402: athp = AT_ATP_HDR(m);
403: ATP_CLEAR_CONTROL(athp);
404: athp->cmd = ATP_CMD_TREL;
405: UAS_ASSIGN(athp->tid, trp->tr_tid);
406: }
407:
408: return (m);
409: }
410:
411: void atp_send_replies(atp, rcbp)
412: register struct atp_state *atp;
413: register struct atp_rcb *rcbp;
414: { register gbuf_t *m;
415: register int i, len;
416: int s_gen, s, cnt;
417: unsigned char *m0_rptr = NULL, *m0_wptr = NULL;
418: register at_atp_t *athp;
419: register struct atpBDS *bdsp;
420: register gbuf_t *m2, *m1, *m0;
421: gbuf_t *mprev, *mlist = 0;
422: at_socket src_socket = (at_socket)atp->atp_socket_no;
423: gbuf_t *rc_xmt[ATP_TRESP_MAX];
424: struct ddp_atp {
425: char ddp_atp_hdr[TOTAL_ATP_HDR_SIZE];
426: };
427:
428: ATDISABLE(s, atp->atp_lock);
429: if (rcbp->rc_queue != atp) {
430: ATENABLE(s, atp->atp_lock);
431: return;
432: }
433: if (rcbp->rc_not_sent_bitmap == 0)
434: goto nothing_to_send;
435:
436: dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ("atp_send_replies\n"));
437: /*
438: * Do this for each message that hasn't been sent
439: */
440: cnt = rcbp->rc_pktcnt;
441: for (i = 0; i < cnt; i++) {
442: rc_xmt[i] = 0;
443: if (rcbp->rc_snd[i]) {
444: if ((rc_xmt[i] = gbuf_alloc(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,PRI_MED)) == NULL) {
445: for (cnt = 0; cnt < i; cnt++)
446: if (rc_xmt[cnt])
447: gbuf_freeb(rc_xmt[cnt]);
448: goto nothing_to_send;
449: }
450: }
451: }
452:
453: m = rcbp->rc_xmt;
454: m0 = gbuf_cont(m);
455: if (m0) {
456: m0_rptr = gbuf_rptr(m0);
457: m0_wptr = gbuf_wptr(m0);
458: }
459: if (gbuf_len(m) > TOTAL_ATP_HDR_SIZE)
460: bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
461: else
462: bdsp = 0;
463:
464: for (i = 0; i < cnt; i++) {
465: if (rcbp->rc_snd[i] == 0) {
466: if ((len = UAS_VALUE(bdsp->bdsBuffSz)))
467: gbuf_rinc(m0,len);
468:
469: } else {
470: m2 = rc_xmt[i];
471: gbuf_rinc(m2,AT_WR_OFFSET);
472: gbuf_wset(m2,TOTAL_ATP_HDR_SIZE);
473: *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m));
474: athp = AT_ATP_HDR(m2);
475: ATP_CLEAR_CONTROL(athp);
476: athp->cmd = ATP_CMD_TRESP;
477: athp->bitmap = i;
478: if (i == (cnt - 1))
479: athp->eom = 1; /* for the last fragment */
480: if (bdsp)
481: UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
482:
483: if (bdsp)
484: if (len = UAS_VALUE(bdsp->bdsBuffSz)) { /* copy in data */
485: if (m0 && gbuf_len(m0)) {
486: if ((m1 = gbuf_dupb(m0)) == NULL) {
487: for (i = 0; i < cnt; i++)
488: if (rc_xmt[i])
489: gbuf_freem(rc_xmt[i]);
490: gbuf_rptr(m0) = m0_rptr;
491: gbuf_wset(m0,(m0_wptr-m0_rptr));
492: goto nothing_to_send;
493: }
494: gbuf_wset(m1,len);
495: gbuf_rinc(m0,len);
496: if ((len = gbuf_len(m0)) < 0) {
497: gbuf_rdec(m0,len);
498: gbuf_wdec(m1,len);
499: if (NULL == (gbuf_cont(m1) = gbuf_dupb(gbuf_cont(m0)))) {
500: for (i = 0; i < cnt; i++)
501: if (rc_xmt[i])
502: gbuf_freem(rc_xmt[i]);
503: gbuf_rptr(m0) = m0_rptr;
504: gbuf_wset(m0,(m0_wptr-m0_rptr));
505: goto nothing_to_send;
506: }
507: } else
508: gbuf_cont(m1) = 0;
509: gbuf_cont(m2) = m1;
510: }
511: }
512:
513: AT_DDP_HDR(m2)->src_socket = src_socket;
514: dPrintf(D_M_ATP_LOW, D_L_OUTPUT,
515: ("atp_send_replies: %d, socket=%d, size=%d\n",
516: i, atp->atp_socket_no, gbuf_msgsize(gbuf_cont(m2))));
517:
518: if (mlist)
519: gbuf_next(mprev) = m2;
520: else
521: mlist = m2;
522: mprev = m2;
523:
524: rcbp->rc_snd[i] = 0;
525: rcbp->rc_not_sent_bitmap &= ~atp_mask[i];
526: if (rcbp->rc_not_sent_bitmap == 0)
527: break;
528: }
529: /*
530: * on to the next frag
531: */
532: bdsp++;
533: }
534: if (m0) {
535: gbuf_rptr(m0) = m0_rptr;
536: gbuf_wset(m0,(m0_wptr-m0_rptr));
537: }
538:
539: if (mlist) {
540: ATENABLE(s, atp->atp_lock);
541: DDP_OUTPUT(mlist);
542: ATDISABLE(s, atp->atp_lock);
543: }
544:
545: nothing_to_send:
546: /*
547: * If all replies from this reply block have been sent then
548: * remove it from the queue and mark it so
549: */
550: if (rcbp->rc_queue != atp) {
551: ATENABLE(s, atp->atp_lock);
552: return;
553: }
554: rcbp->rc_rep_waiting = 0;
555:
556: /*
557: * If we are doing execute once re-set the rcb timeout
558: * each time we send back any part of the response. Note
559: * that this timer is started when an initial request is
560: * received. Each response reprimes the timer. Duplicate
561: * requests do not reprime the timer.
562: *
563: * We have sent all of a response so free the
564: * resources.
565: */
566: if (rcbp->rc_xo && rcbp->rc_state != RCB_RELEASED) {
567: ATDISABLE(s_gen, atpgen_lock);
568: if (rcbp->rc_timestamp == 0) {
569: rcbp->rc_timestamp = time.tv_sec;
570: if (rcbp->rc_timestamp == 0)
571: rcbp->rc_timestamp = 1;
572: ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist);
573: }
574: rcbp->rc_state = RCB_RESPONSE_FULL;
575: ATENABLE(s_gen, atpgen_lock);
576: } else
577: atp_rcb_free(rcbp);
578: ATENABLE(s, atp->atp_lock);
579: } /* atp_send_replies */
580:
581:
582: static void
583: atp_pack_bdsp(trp, bdsp)
584: register struct atp_trans *trp;
585: register struct atpBDS *bdsp;
586: {
587: register gbuf_t *m = NULL;
588: register int i, datsize = 0;
589: struct atpBDS *bdsbase = bdsp;
590:
591: dPrintf(D_M_ATP, D_L_INFO, ("atp_pack_bdsp: socket=%d\n",
592: trp->tr_queue->atp_socket_no));
593:
594: for (i = 0; i < ATP_TRESP_MAX; i++, bdsp++) {
595: short bufsize = UAS_VALUE(bdsp->bdsBuffSz);
596: long bufaddr = UAL_VALUE(bdsp->bdsBuffAddr);
597:
598: if ((m = trp->tr_rcv[i]) == NULL)
599: break;
600:
601: /* discard ddp hdr on first packet */
602: if (i == 0)
603: gbuf_rinc(m,DDP_X_HDR_SIZE);
604:
605: /* this field may contain control information even when
606: no data is present */
607: UAL_UAL(bdsp->bdsUserData,
608: (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
609: gbuf_rinc(m, ATP_HDR_SIZE);
610:
611: if ((bufsize != 0) && (bufaddr != 0)) {
612: /* user expects data back */
613: short tmp = 0;
614: register char *buf = (char *)bufaddr;
615:
616: while (m) {
617: short len = (short)(gbuf_len(m));
618: if (len) {
619: if (len > bufsize)
620: len = bufsize;
621: copyout((caddr_t)gbuf_rptr(m),
622: (caddr_t)&buf[tmp],
623: len);
624: bufsize -= len;
625: tmp =+ len;
626: }
627: m = gbuf_cont(m);
628: }
629:
630: UAS_ASSIGN(bdsp->bdsDataSz, tmp);
631: datsize += (int)tmp;
632: }
633: gbuf_freem(trp->tr_rcv[i]);
634: trp->tr_rcv[i] = NULL;
635: }
636:
637: /* report the number of packets */
638: UAS_ASSIGN(((struct atpBDS *)bdsbase)->bdsBuffSz, i);
639:
640: dPrintf(D_M_ATP, D_L_INFO, (" : size=%d\n",
641: datsize));
642: } /* atp_pack_bdsp */
643:
644:
645: static int
646: atp_unpack_bdsp(atp, m, rcbp, cnt, wait)
647: struct atp_state *atp;
648: gbuf_t *m; /* ddp, atp and bdsp gbuf_t */
649: register struct atp_rcb *rcbp;
650: register int cnt, wait;
651: {
652: register struct atpBDS *bdsp;
653: register gbuf_t *m2, *m1, *m0;
654: register at_atp_t *athp;
655: register int i, len, s_gen;
656: at_socket src_socket;
657: struct ddp_atp {
658: char ddp_atp_hdr[TOTAL_ATP_HDR_SIZE];
659: };
660: gbuf_t *mprev, *mlist = 0;
661: gbuf_t *rc_xmt[ATP_TRESP_MAX];
662: unsigned char *m0_rptr, *m0_wptr;
663:
664: /*
665: * get the user data structure pointer
666: */
667: bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
668:
669: /*
670: * Guard against bogus count argument.
671: */
672: if ((unsigned) cnt > ATP_TRESP_MAX) {
673: dPrintf(D_M_ATP, D_L_ERROR,
674: ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt));
675: gbuf_freem(m);
676: return(EINVAL);
677: }
678: if ((src_socket = (at_socket)atp->atp_socket_no) == 0xFF) {
679: /* comparison was to -1, however src_socket is a u_char */
680: gbuf_freem(m);
681: return EPIPE;
682: }
683:
684: m0 = gbuf_cont(m);
685: rcbp->rc_xmt = m;
686: rcbp->rc_pktcnt = cnt;
687: rcbp->rc_state = RCB_SENDING;
688: rcbp->rc_not_sent_bitmap = 0;
689:
690: if (cnt <= 1) {
691: /*
692: * special case this to
693: * improve AFP write transactions to the server
694: */
695: rcbp->rc_pktcnt = 1;
696: if ((m2 = gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,
697: wait)) == NULL)
698: return 0;
699: gbuf_rinc(m2,AT_WR_OFFSET);
700: gbuf_wset(m2,TOTAL_ATP_HDR_SIZE);
701: *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m));
702: athp = AT_ATP_HDR(m2);
703: ATP_CLEAR_CONTROL(athp);
704: athp->cmd = ATP_CMD_TRESP;
705: athp->bitmap = 0;
706: athp->eom = 1; /* there's only 1 fragment */
707:
708: /* *** why only if cnt > 0? *** */
709: if (cnt > 0)
710: UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
711: if (m0)
712: if ((gbuf_cont(m2) = gbuf_dupb_wait(m0, wait)) == NULL) {
713: gbuf_freeb(m2);
714: return 0;
715: }
716: /*
717: * send the message and mark it as sent
718: */
719: AT_DDP_HDR(m2)->src_socket = src_socket;
720: dPrintf(D_M_ATP_LOW, D_L_INFO,
721: ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
722: 0,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(m2)),cnt));
723: mlist = m2;
724: goto l_send;
725: }
726:
727: for (i = 0; i < cnt; i++) {
728: /* all hdrs, packet data and dst addr storage */
729: if ((rc_xmt[i] =
730: gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,
731: wait)) == NULL) {
732: for (cnt = 0; cnt < i; cnt++)
733: if (rc_xmt[cnt])
734: gbuf_freeb(rc_xmt[cnt]);
735: return 0;
736: }
737: }
738:
739: if (m0) {
740: m0_rptr = gbuf_rptr(m0);
741: m0_wptr = gbuf_wptr(m0);
742: }
743:
744: for (i = 0; i < cnt; i++) {
745: m2 = rc_xmt[i];
746: gbuf_rinc(m2,AT_WR_OFFSET);
747: gbuf_wset(m2,TOTAL_ATP_HDR_SIZE);
748: *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m));
749: athp = AT_ATP_HDR(m2);
750: ATP_CLEAR_CONTROL(athp);
751: athp->cmd = ATP_CMD_TRESP;
752: athp->bitmap = i;
753: if (i == (cnt - 1))
754: athp->eom = 1; /* for the last fragment */
755: UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
756:
757: if ((len = UAS_VALUE(bdsp->bdsBuffSz))) { /* copy in data */
758: if (m0 && gbuf_len(m0)) {
759: if ((m1 = gbuf_dupb_wait(m0, wait)) == NULL) {
760: for (i = 0; i < cnt; i++)
761: if (rc_xmt[i])
762: gbuf_freem(rc_xmt[i]);
763: gbuf_rptr(m0) = m0_rptr;
764: gbuf_wset(m0,(m0_wptr-m0_rptr));
765: return 0;
766: }
767: gbuf_wset(m1,len);
768: gbuf_rinc(m0,len);
769: if ((len = gbuf_len(m0)) < 0) {
770: gbuf_rdec(m0,len);
771: gbuf_wdec(m1,len);
772: if ((gbuf_cont(m1) = gbuf_dupb_wait(gbuf_cont(m0), wait)) == NULL) {
773: for (i = 0; i < cnt; i++)
774: if (rc_xmt[i])
775: gbuf_freem(rc_xmt[i]);
776: gbuf_rptr(m0) = m0_rptr;
777: gbuf_wset(m0,(m0_wptr-m0_rptr));
778: return 0;
779: }
780: } else
781: gbuf_cont(m1) = 0;
782: gbuf_cont(m2) = m1;
783: }
784: }
785:
786: AT_DDP_HDR(m2)->src_socket = src_socket;
787: dPrintf(D_M_ATP_LOW,D_L_INFO,
788: ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
789: i,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(m2)),cnt));
790: if (mlist)
791: gbuf_next(mprev) = m2;
792: else
793: mlist = m2;
794: mprev = m2;
795: /*
796: * on to the next frag
797: */
798: bdsp++;
799: }
800: if (m0) {
801: gbuf_rptr(m0) = m0_rptr;
802: gbuf_wset(m0,(m0_wptr-m0_rptr));
803: }
804: /*
805: * send the message
806: */
807: l_send:
808: if (rcbp->rc_xo) {
809: ATDISABLE(s_gen, atpgen_lock);
810: if (rcbp->rc_timestamp == 0) {
811: if ((rcbp->rc_timestamp = time.tv_sec) == 0)
812: rcbp->rc_timestamp = 1;
813: ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist);
814: }
815: ATENABLE(s_gen, atpgen_lock);
816: }
817:
818: DDP_OUTPUT(mlist);
819: return 0;
820: } /* atp_unpack_bdsp */
821:
822: #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6)
823: #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC-64)
824: static unsigned int sNext = 0;
825:
826: int atp_bind(gref, sVal, flag)
827: gref_t *gref;
828: unsigned int sVal;
829: unsigned char *flag;
830: {
831: extern unsigned char asp_inpC[];
832: extern asp_scb_t *asp_scbQ[];
833: unsigned char inpC, sNextUsed = 0;
834: unsigned int sMin, sMax, sSav;
835: struct atp_state *atp;
836: int s;
837:
838: atp = (struct atp_state *)gref->info;
839: if (atp->dflag)
840: atp = (struct atp_state *)atp->atp_msgq;
841:
842: sMax = ATP_SOCKET_LAST;
843: sMin = ATP_SOCKET_FIRST;
844: ATDISABLE(s, atpgen_lock);
845: if (flag && (*flag == 3)) {
846: sMin += 40;
847: if (sMin < sNext) {
848: sMin = sNext;
849: sNextUsed = 1;
850: }
851: }
852:
853: if ( (sVal != 0)
854: && ((sVal > sMax) || (sVal < 2) || (sVal == 6)
855: || ((atp_inputQ[sVal] != NULL) &&
856: (atp_inputQ[sVal] != (gref_t *)1))
857: || (ot_atp_socketM[sVal] != 0)) )
858: {
859: ATENABLE(s, atpgen_lock);
860: return 0;
861: }
862:
863: if (sVal == 0) {
864: inpC = 255;
865: again:
866: for (sVal=sMin; sVal <= sMax; sVal++) {
867: if (ot_atp_socketM[sVal] == 0) {
868: if (atp_inputQ[sVal] == NULL ||
869: atp_inputQ[sVal] == (gref_t *)1)
870: break;
871: else if (flag && (*flag == 3)) {
872: if ((asp_scbQ[sVal]->dflag == *flag)
873: && (asp_inpC[sVal] < inpC) ) {
874: inpC = asp_inpC[sVal];
875: sSav = sVal;
876: }
877: }
878: }
879: }
880: if (sVal > sMax) {
881: if (flag && (*flag == 3)) {
882: if (sNextUsed) {
883: sNextUsed = 0;
884: sMax = sNext - 1;
885: sMin = ATP_SOCKET_FIRST+40;
886: goto again;
887: }
888: sNext = 0;
889: *flag = (unsigned char)sSav;
890: }
891: ATENABLE(s, atpgen_lock);
892: return 0;
893: }
894: }
895: atp->atp_socket_no = (short)sVal;
896: atp_inputQ[sVal] = gref;
897: if (flag == 0)
898: atp_pidM[sVal] = atp->atp_pid;
899: else if (*flag == 3) {
900: sNext = sVal + 1;
901: if (sNext > ATP_SOCKET_LAST)
902: sNext = 0;
903: }
904:
905: ATENABLE(s, atpgen_lock);
906: return (int)sVal;
907: }
908:
909: void atp_req_ind(atp, mioc)
910: register struct atp_state *atp;
911: register gbuf_t *mioc;
912: {
913: register struct atp_rcb *rcbp;
914: int s;
915:
916: if ((rcbp = atp->atp_attached.head) != 0) {
917: gbuf_cont(mioc) = rcbp->rc_ioctl;
918: rcbp->rc_ioctl = NULL;
919: ATDISABLE(s, atp->atp_lock);
920: if (rcbp->rc_xo) {
921: ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
922: rcbp->rc_state = RCB_NOTIFIED;
923: ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
924: } else
925: atp_rcb_free(rcbp);
926: ATENABLE(s, atp->atp_lock);
927: if (gbuf_cont(mioc))
928: ((ioc_t *)gbuf_rptr(mioc))->ioc_count = gbuf_msgsize(gbuf_cont(mioc));
929: else
930: ((ioc_t *)gbuf_rptr(mioc))->ioc_count = 0;
931: asp_ack_reply(atp->atp_gref, mioc);
932: } else
933: gbuf_freeb(mioc);
934: }
935:
936: void atp_rsp_ind(trp, mioc)
937: register struct atp_trans *trp;
938: register gbuf_t *mioc;
939: {
940: register struct atp_state *atp = trp->tr_queue;
941: register int err;
942: gbuf_t *xm = 0;
943:
944: err = 0;
945: {
946: switch (trp->tr_state) {
947: case TRANS_DONE:
948: if (asp_pack_bdsp(trp, &xm) < 0)
949: err = EFAULT;
950: gbuf_cont(mioc) = trp->tr_xmt;
951: trp->tr_xmt = NULL;
952: break;
953:
954: case TRANS_FAILED:
955: err = ETIMEDOUT;
956: break;
957:
958: default:
959: err = ENOENT;
960: break;
961: }
962: atp_free(trp);
963:
964: if (err) {
965: dPrintf(D_M_ATP, D_L_ERROR,
966: ("atp_rsp_ind: TRANSACTION error\n"));
967: atp_iocnak(atp, mioc, err);
968: } else {
969: gbuf_cont(gbuf_cont(mioc)) = xm;
970: atp_iocack(atp, mioc);
971: }
972: }
973: }
974:
975: void atp_cancel_req(gref, tid)
976: gref_t *gref;
977: unsigned short tid;
978: {
979: int s;
980: struct atp_state *atp;
981: struct atp_trans *trp;
982:
983: atp = (struct atp_state *)gref->info;
984: if (atp->dflag)
985: atp = (struct atp_state *)atp->atp_msgq;
986:
987: ATDISABLE(s, atp->atp_lock);
988: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
989: if (trp->tr_tid == tid)
990: break;
991: }
992: ATENABLE(s, atp->atp_lock);
993: if (trp != NULL)
994: atp_free(trp);
995: }
996:
997: /*
998: * stop ATP now
999: */
1000: void
1001: atp_stop(m, flag)
1002: gbuf_t *m;
1003: int flag;
1004: {
1005: struct atp_trans *trp;
1006: int k, s, *x_wptr;
1007: struct atp_state *atp;
1008: gref_t *gref;
1009:
1010: gbuf_rptr(m)[1]++;
1011:
1012: if (flag)
1013: atp_off_flag = 1;
1014:
1015: asp_stop(m, flag);
1016: ATDISABLE(s, atpall_lock);
1017:
1018: x_wptr = (int *)gbuf_wptr(m);
1019: for (atp = atp_used_list; atp; atp = atp->atp_trans_waiting) {
1020: if (flag == 2) {
1021: atp->atp_flags |= ATP_CLOSING;
1022: } else {
1023: *(int *)gbuf_wptr(m) = atp->atp_pid;
1024: gbuf_winc(m,sizeof(int));
1025: }
1026: }
1027:
1028: for (k=0; k < 256; k++) {
1029: if (((gref = atp_inputQ[k]) == 0) || gref == (gref_t *)1)
1030: continue;
1031: atp = (struct atp_state *)gref->info;
1032: if (atp->dflag)
1033: continue;
1034: if (flag == 2) {
1035: atp->atp_flags |= ATP_CLOSING;
1036: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
1037: if (trp->tr_rsp_wait) {
1038: trp->tr_state = TRANS_FAILED;
1039: thread_wakeup(&trp->tr_event);
1040: }
1041: }
1042: } else {
1043: *(int *)gbuf_wptr(m) = atp->atp_pid;
1044: gbuf_winc(m,sizeof(int));
1045: }
1046: }
1047: ATENABLE(s, atpall_lock);
1048:
1049: while (x_wptr != (int *)gbuf_wptr(m)) {
1050: dPrintf(D_M_ATP, D_L_TRACE, ("atp_stop: pid=%d\n", *x_wptr));
1051: x_wptr++;
1052: }
1053: }
1054:
1055: /*
1056: * remove atp from the use list
1057: */
1058: void
1059: atp_dequeue_atp(atp)
1060: struct atp_state *atp;
1061: {
1062: int s;
1063:
1064: ATDISABLE(s, atpall_lock);
1065: if (atp == atp_used_list) {
1066: if ((atp_used_list = atp->atp_trans_waiting) != 0)
1067: atp->atp_trans_waiting->atp_rcb_waiting = 0;
1068: } else if (atp->atp_rcb_waiting) {
1069: if ((atp->atp_rcb_waiting->atp_trans_waiting
1070: = atp->atp_trans_waiting) != 0)
1071: atp->atp_trans_waiting->atp_rcb_waiting = atp->atp_rcb_waiting;
1072: }
1073:
1074: atp->atp_trans_waiting = 0;
1075: atp->atp_rcb_waiting = 0;
1076: ATENABLE(s, atpall_lock);
1077: }
1078:
1079: void
1080: atp_timout(func, trp, ticks)
1081: void (*func)();
1082: struct atp_trans *trp;
1083: int ticks;
1084: {
1085: int s;
1086: unsigned int sum;
1087: struct atp_trans *curr_trp, *prev_trp;
1088:
1089: ATDISABLE(s, atptmo_lock);
1090: if (trp->tr_tmo_func) {
1091: ATENABLE(s, atptmo_lock);
1092: return;
1093: }
1094:
1095: trp->tr_tmo_func = func;
1096: trp->tr_tmo_delta = 1+(ticks>>5);
1097:
1098: if (trp_tmo_list == 0) {
1099: trp->tr_tmo_next = trp->tr_tmo_prev = 0;
1100: trp_tmo_list = trp;
1101: ATENABLE(s, atptmo_lock);
1102: return;
1103: }
1104:
1105: prev_trp = 0;
1106: curr_trp = trp_tmo_list;
1107: sum = 0;
1108:
1109: while (1) {
1110: sum += curr_trp->tr_tmo_delta;
1111: if (sum > trp->tr_tmo_delta) {
1112: sum -= curr_trp->tr_tmo_delta;
1113: trp->tr_tmo_delta -= sum;
1114: curr_trp->tr_tmo_delta -= trp->tr_tmo_delta;
1115: break;
1116: }
1117: prev_trp = curr_trp;
1118: if ((curr_trp = curr_trp->tr_tmo_next) == 0) {
1119: trp->tr_tmo_delta -= sum;
1120: break;
1121: }
1122: }
1123:
1124: if (prev_trp) {
1125: trp->tr_tmo_prev = prev_trp;
1126: if ((trp->tr_tmo_next = prev_trp->tr_tmo_next) != 0)
1127: prev_trp->tr_tmo_next->tr_tmo_prev = trp;
1128: prev_trp->tr_tmo_next = trp;
1129: } else {
1130: trp->tr_tmo_prev = 0;
1131: trp->tr_tmo_next = trp_tmo_list;
1132: trp_tmo_list->tr_tmo_prev = trp;
1133: trp_tmo_list = trp;
1134: }
1135: ATENABLE(s, atptmo_lock);
1136: }
1137:
1138: void
1139: atp_untimout(func, trp)
1140: void (*func)();
1141: struct atp_trans *trp;
1142: {
1143: int s;
1144:
1145: ATDISABLE(s, atptmo_lock);
1146: if (trp->tr_tmo_func == 0) {
1147: ATENABLE(s, atptmo_lock);
1148: return;
1149: }
1150:
1151: if (trp_tmo_list == trp) {
1152: if ((trp_tmo_list = trp->tr_tmo_next) != 0) {
1153: trp_tmo_list->tr_tmo_prev = 0;
1154: trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
1155: }
1156: } else {
1157: if ((trp->tr_tmo_prev->tr_tmo_next = trp->tr_tmo_next) != 0) {
1158: trp->tr_tmo_next->tr_tmo_prev = trp->tr_tmo_prev;
1159: trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
1160: }
1161: }
1162: trp->tr_tmo_func = 0;
1163: ATENABLE(s, atptmo_lock);
1164: }
1165:
1166: static void *trp_clock_tmo = 0;
1167:
1168: void
1169: atp_trp_clock(arg)
1170: void *arg;
1171: {
1172: if (!atp_off_flag)
1173: atp_trp_timer(arg, 0);
1174: }
1175:
1176: void
1177: atp_trp_timer(arg, flag)
1178: void *arg;
1179: int flag;
1180: {
1181: int s;
1182: struct atp_trans *trp;
1183: void (*tr_tmo_func)();
1184:
1185: if (atp_off_flag)
1186: return;
1187: if (flag) {
1188: atp_off_flag = 1;
1189: atalk_untimeout(atp_trp_clock, (void *)arg, trp_clock_tmo);
1190: trp_clock_tmo = 0;
1191: return;
1192: }
1193:
1194: ATDISABLE(s, atptmo_lock);
1195: if (trp_tmo_list)
1196: trp_tmo_list->tr_tmo_delta--;
1197: while (((trp = trp_tmo_list) != 0) && (trp_tmo_list->tr_tmo_delta == 0)) {
1198: if ((trp_tmo_list = trp->tr_tmo_next) != 0)
1199: trp_tmo_list->tr_tmo_prev = 0;
1200: if ((tr_tmo_func = trp->tr_tmo_func) != 0) {
1201: trp->tr_tmo_func = 0;
1202: ATENABLE(s, atptmo_lock);
1203: (*tr_tmo_func)(trp);
1204: ATDISABLE(s, atptmo_lock);
1205: }
1206: }
1207: ATENABLE(s, atptmo_lock);
1208:
1209: trp_clock_tmo = (void *)atalk_timeout(atp_trp_clock, (void *)arg, (1<<5));
1210: }
1211:
1212: void
1213: atp_send_req(gref, mioc)
1214: gref_t *gref;
1215: gbuf_t *mioc;
1216: {
1217: register struct atp_state *atp;
1218: register struct atp_trans *trp;
1219: register ioc_t *iocbp;
1220: register at_atp_t *athp;
1221: register at_ddp_t *ddp;
1222: gbuf_t *m, *m2, *bds;
1223: struct atp_set_default *sdb;
1224: int s, old;
1225: unsigned int timer;
1226:
1227: atp = (struct atp_state *)((struct atp_state *)gref->info)->atp_msgq;
1228: iocbp = (ioc_t *)gbuf_rptr(mioc);
1229:
1230: if ((trp = atp_trans_alloc(atp)) == NULL) {
1231: l_retry:
1232: ((asp_scb_t *)gref->info)->stat_msg = mioc;
1233: iocbp->ioc_private = (void *)gref;
1234: atalk_timeout(atp_retry_req, mioc, 10);
1235: return;
1236: }
1237:
1238: {
1239: m2 = gbuf_cont(mioc);
1240:
1241: if ((bds = gbuf_dupb(m2)) == NULL) {
1242: atp_trans_free(trp);
1243: goto l_retry;
1244: }
1245: gbuf_rinc(m2,atpBDSsize);
1246: gbuf_wset(bds,atpBDSsize);
1247: iocbp->ioc_count -= atpBDSsize;
1248: gbuf_cont(m2) = NULL;
1249: }
1250:
1251: old = iocbp->ioc_cmd;
1252: iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST;
1253: sdb = (struct atp_set_default *)gbuf_rptr(m2);
1254:
1255: /*
1256: * The at_snd_req library routine multiplies seconds by 100.
1257: * We need to divide by 100 in order to obtain the timer.
1258: */
1259: if ((timer = (sdb->def_rate * HZ)/100) == 0)
1260: timer = HZ;
1261: iocbp->ioc_count -= sizeof(struct atp_set_default);
1262: gbuf_rinc(m2,sizeof(struct atp_set_default));
1263:
1264: trp->tr_retry = sdb->def_retries;
1265: trp->tr_timeout = timer;
1266: trp->tr_bdsp = bds;
1267: trp->tr_tid = atp_tid(atp);
1268: trp->tr_xmt = mioc;
1269:
1270: /*
1271: * Now fill in the header (and remember the bits
1272: * we need to know)
1273: */
1274: athp = AT_ATP_HDR(m2);
1275: athp->cmd = ATP_CMD_TREQ;
1276: UAS_ASSIGN(athp->tid, trp->tr_tid);
1277: athp->eom = 0;
1278: athp->sts = 0;
1279: trp->tr_xo = athp->xo;
1280: trp->tr_bitmap = athp->bitmap;
1281: ddp = AT_DDP_HDR(m2);
1282: ddp->type = DDP_ATP;
1283: ddp->src_socket = (at_socket)atp->atp_socket_no;
1284: trp->tr_socket.socket = ddp->dst_socket;
1285: trp->tr_socket.node = ddp->dst_node;
1286: trp->tr_socket.net = NET_VALUE(ddp->dst_net);
1287: trp->tr_local_socket = atp->atp_socket_no;
1288: trp->tr_local_node = ddp->src_node;
1289: NET_NET(trp->tr_local_net, ddp->src_net);
1290: /*
1291: * Put us in the transaction waiting queue
1292: */
1293: ATDISABLE(s, atp->atp_lock);
1294: ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
1295: ATENABLE(s, atp->atp_lock);
1296:
1297: /*
1298: * Send the message and set the timer
1299: */
1300: if ( !trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo) {
1301: m = (gbuf_t *)gbuf_copym(m2);
1302: atp_x_done(trp); /* no reason to tie up resources */
1303: } else {
1304: m = (gbuf_t *)gbuf_dupm(m2);
1305: atp_timout(atp_req_timeout, trp, trp->tr_timeout);
1306: }
1307: if (m)
1308: DDP_OUTPUT(m);
1309: }
1310:
1311: void
1312: atp_retry_req(m)
1313: gbuf_t *m;
1314: {
1315: gref_t *gref;
1316:
1317: gref = (gref_t *)((ioc_t *)gbuf_rptr(m))->ioc_private;
1318: if (gref->info) {
1319: ((asp_scb_t *)gref->info)->stat_msg = 0;
1320: atp_send_req(gref, m);
1321: }
1322: }
1323:
1324: void
1325: atp_send_rsp(gref, m, wait)
1326: gref_t *gref;
1327: gbuf_t *m;
1328: int wait;
1329: {
1330: register struct atp_state *atp;
1331: register struct atp_rcb *rcbp;
1332: register at_atp_t *athp;
1333: register at_ddp_t *ddp;
1334: int s, xcnt;
1335:
1336: atp = (struct atp_state *)gref->info;
1337: if (atp->dflag)
1338: atp = (struct atp_state *)atp->atp_msgq;
1339: ddp = AT_DDP_HDR(m);
1340: athp = AT_ATP_HDR(m);
1341:
1342: /*
1343: * search for the corresponding rcb
1344: */
1345: ATDISABLE(s, atp->atp_lock);
1346: for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
1347: if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) &&
1348: (rcbp->rc_socket.node == ddp->dst_node) &&
1349: (rcbp->rc_socket.net == NET_VALUE(ddp->dst_net)) &&
1350: (rcbp->rc_socket.socket == ddp->dst_socket) )
1351: break;
1352: }
1353:
1354: /*
1355: * If it has already been sent then drop the request
1356: */
1357: if ((rcbp && (rcbp->rc_state != RCB_NOTIFIED)) ||
1358: (rcbp == NULL && athp->xo) ) {
1359: ATENABLE(s, atp->atp_lock);
1360: gbuf_freem(m);
1361: return;
1362: }
1363: ATENABLE(s, atp->atp_lock);
1364:
1365: if (rcbp == NULL) { /* a response is being sent for an ALO transaction */
1366: if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
1367: gbuf_freem(m);
1368: return;
1369: }
1370: rcbp->rc_ioctl = 0;
1371: rcbp->rc_socket.socket = ddp->dst_socket;
1372: rcbp->rc_socket.node = ddp->dst_node;
1373: rcbp->rc_socket.net = NET_VALUE(ddp->dst_net);
1374: rcbp->rc_tid = UAS_VALUE(athp->tid);
1375: rcbp->rc_bitmap = 0xff;
1376: rcbp->rc_xo = 0;
1377: rcbp->rc_state = RCB_RESPONSE_FULL;
1378: ATDISABLE(s, atp->atp_lock);
1379: ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
1380: ATENABLE(s, atp->atp_lock);
1381: }
1382: else if (ddp->src_node == 0) {
1383: NET_NET(ddp->src_net, rcbp->rc_local_net);
1384: ddp->src_node = rcbp->rc_local_node;
1385: }
1386:
1387: /* first bds entry gives number of bds entries in total (hack) */
1388: xcnt = (gbuf_len(m) > TOTAL_ATP_HDR_SIZE) ?
1389: UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz) : 0;
1390: s = atp_unpack_bdsp(atp, m, rcbp, xcnt, wait);
1391: if (s == 0)
1392: atp_send_replies(atp, rcbp);
1393: } /* atp_send_rsp */
1394:
1395: int
1396: asp_pack_bdsp(trp, xm)
1397: register struct atp_trans *trp;
1398: gbuf_t **xm;
1399: {
1400: register struct atpBDS *bdsp;
1401: register gbuf_t *m, *m2;
1402: register int i;
1403: gbuf_t *m_prev, *m_head = 0;
1404:
1405: dPrintf(D_M_ATP, D_L_INFO, ("asp_pack_bdsp: socket=%d\n",
1406: trp->tr_queue->atp_socket_no));
1407:
1408: if ((m2 = trp->tr_bdsp) == NULL)
1409: return 0;
1410: trp->tr_bdsp = NULL;
1411: bdsp = (struct atpBDS *)gbuf_rptr(m2);
1412:
1413: for (i = 0; (i < ATP_TRESP_MAX &&
1414: bdsp < (struct atpBDS *)(gbuf_wptr(m2))); i++) {
1415: if ((m = trp->tr_rcv[i]) == NULL)
1416: break;
1417: if (i == 0) {
1418: /* discard ddp hdr on first packet */
1419: gbuf_rinc(m,DDP_X_HDR_SIZE);
1420: }
1421:
1422: UAL_UAL(bdsp->bdsUserData, (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
1423: gbuf_rinc(m, ATP_HDR_SIZE);
1424:
1425: if (UAL_VALUE(bdsp->bdsBuffAddr)) {
1426: /* user expects data back */
1427: short tmp;
1428: gbuf_t *tmp_m;
1429:
1430: while (m && ((tmp = (short)(gbuf_len(m))) == 0)) {
1431: tmp_m = m;
1432: m = gbuf_cont(m);
1433: gbuf_freeb(tmp_m);
1434: }
1435: if (m_head == 0)
1436: m_head = m;
1437: else
1438: gbuf_cont(m_prev) = m;
1439: if (m) {
1440: while (gbuf_cont(m)) {
1441: m = gbuf_cont(m);
1442: tmp += (short)(gbuf_len(m));
1443: }
1444: m_prev = m;
1445: }
1446: UAS_ASSIGN(bdsp->bdsDataSz, tmp);
1447: }
1448: trp->tr_rcv[i] = NULL;
1449: bdsp++;
1450:
1451: }
1452: /*
1453: * report the number of packets
1454: */
1455: UAS_ASSIGN(((struct atpBDS *)gbuf_rptr(m2))->bdsBuffSz, i);
1456:
1457: if (trp->tr_xmt) /* an ioctl block is still held? */
1458: gbuf_cont(trp->tr_xmt) = m2;
1459: else
1460: trp->tr_xmt = m2;
1461:
1462: if (m_head)
1463: *xm = m_head;
1464: else
1465: *xm = 0;
1466:
1467: dPrintf(D_M_ATP, D_L_INFO, (" : size=%d\n",
1468: gbuf_msgsize(*xm)));
1469:
1470: return 0;
1471: }
1472:
1473: /*
1474: * The following routines are direct entries from system
1475: * calls to allow fast sending and recving of ATP data.
1476: */
1477:
1478: int
1479: _ATPsndreq(fd, buf, len, nowait, err, proc)
1480: int fd;
1481: unsigned char *buf;
1482: int len;
1483: int nowait;
1484: int *err;
1485: void *proc;
1486: {
1487: gref_t *gref;
1488: int s, rc;
1489: unsigned short tid;
1490: unsigned int timer;
1491: register struct atp_state *atp;
1492: register struct atp_trans *trp;
1493: register ioc_t *iocbp;
1494: register at_atp_t *athp;
1495: register at_ddp_t *ddp;
1496: struct atp_set_default *sdb;
1497: gbuf_t *m2, *m, *mioc;
1498: char bds[atpBDSsize];
1499:
1500: if ((*err = atalk_getref(0, fd, &gref, proc)) != 0)
1501: return -1;
1502:
1503: if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1504: || (atp->atp_flags & ATP_CLOSING)) {
1505: dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
1506: (u_int) gref, gref->pid));
1507:
1508: *err = EINVAL;
1509: return -1;
1510: }
1511:
1512: while ((mioc = gbuf_alloc(sizeof(ioc_t), PRI_MED)) == 0) {
1513: ATDISABLE(s, atp->atp_delay_lock);
1514: rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atpmioc", 10);
1515: ATENABLE(s, atp->atp_delay_lock);
1516: if (rc != 0) {
1517: *err = rc;
1518: return -1;
1519: }
1520:
1521: }
1522: gbuf_wset(mioc,sizeof(ioc_t));
1523: len -= atpBDSsize;
1524: while ((m2 = gbuf_alloc(len, PRI_MED)) == 0) {
1525: ATDISABLE(s, atp->atp_delay_lock);
1526: rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atpm2", 10);
1527: ATENABLE(s, atp->atp_delay_lock);
1528: if (rc != 0) {
1529: gbuf_freeb(mioc);
1530: *err = rc;
1531: return -1;
1532: }
1533: }
1534: gbuf_wset(m2,len);
1535: gbuf_cont(mioc) = m2;
1536: if (((*err = copyin((caddr_t)buf, (caddr_t)bds, atpBDSsize)) != 0)
1537: || ((*err = copyin((caddr_t)&buf[atpBDSsize],
1538: (caddr_t)gbuf_rptr(m2), len)) != 0)) {
1539: gbuf_freem(mioc);
1540: return -1;
1541: }
1542: gbuf_set_type(mioc, MSG_IOCTL);
1543: iocbp = (ioc_t *)gbuf_rptr(mioc);
1544: iocbp->ioc_count = len;
1545: iocbp->ioc_cmd = nowait ? AT_ATP_ISSUE_REQUEST_NOTE : AT_ATP_ISSUE_REQUEST;
1546: sdb = (struct atp_set_default *)gbuf_rptr(m2);
1547:
1548: /*
1549: * The at_snd_req library routine multiplies seconds by 100.
1550: * We need to divide by 100 in order to obtain the timer.
1551: */
1552: if ((timer = (sdb->def_rate * HZ)/100) == 0)
1553: timer = HZ;
1554: iocbp->ioc_count -= sizeof(struct atp_set_default);
1555: gbuf_rinc(m2,sizeof(struct atp_set_default));
1556:
1557: /*
1558: * allocate and set up the transaction record
1559: */
1560: while ((trp = atp_trans_alloc(atp)) == 0) {
1561: ATDISABLE(s, atp->atp_delay_lock);
1562: rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atptrp", 10);
1563: ATENABLE(s, atp->atp_delay_lock);
1564: if (rc != 0) {
1565: gbuf_freem(mioc);
1566: *err = rc;
1567: return -1;
1568: }
1569: }
1570: trp->tr_retry = sdb->def_retries;
1571: trp->tr_timeout = timer;
1572: trp->tr_bdsp = NULL;
1573: trp->tr_tid = atp_tid(atp);
1574: tid = trp->tr_tid;
1575:
1576: /*
1577: * remember the IOCTL packet so we can ack it
1578: * later
1579: */
1580: trp->tr_xmt = mioc;
1581:
1582: /*
1583: * Now fill in the header (and remember the bits
1584: * we need to know)
1585: */
1586: athp = AT_ATP_HDR(m2);
1587: athp->cmd = ATP_CMD_TREQ;
1588: UAS_ASSIGN(athp->tid, trp->tr_tid);
1589: athp->eom = 0;
1590: athp->sts = 0;
1591: trp->tr_xo = athp->xo;
1592: trp->tr_bitmap = athp->bitmap;
1593: ddp = AT_DDP_HDR(m2);
1594: ddp->type = DDP_ATP;
1595: ddp->src_socket = (at_socket)atp->atp_socket_no;
1596: ddp->src_node = 0;
1597: trp->tr_socket.socket = ddp->dst_socket;
1598: trp->tr_socket.node = ddp->dst_node;
1599: trp->tr_socket.net = NET_VALUE(ddp->dst_net);
1600: trp->tr_local_socket = atp->atp_socket_no;
1601:
1602: /*
1603: * Put us in the transaction waiting queue
1604: */
1605: ATDISABLE(s, atp->atp_lock);
1606: ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
1607: ATENABLE(s, atp->atp_lock);
1608:
1609: /*
1610: * Send the message and set the timer
1611: */
1612: if ( !trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo) {
1613: m = (gbuf_t *)gbuf_copym(m2);
1614: atp_x_done(trp); /* no reason to tie up resources */
1615: } else {
1616: m = (gbuf_t *)gbuf_dupm(m2);
1617: atp_timout(atp_req_timeout, trp, trp->tr_timeout);
1618: }
1619: if (m)
1620: DDP_OUTPUT(m);
1621:
1622: if (nowait)
1623: return (int)tid;
1624:
1625: /*
1626: * wait for the transaction to complete
1627: */
1628: ATDISABLE(s, trp->tr_lock);
1629: while ((trp->tr_state != TRANS_DONE) && (trp->tr_state != TRANS_FAILED)) {
1630: trp->tr_rsp_wait = 1;
1631: rc = tsleep(&trp->tr_event, PSOCK | PCATCH, "atpsndreq", 0);
1632: if (rc != 0) {
1633: trp->tr_rsp_wait = 0;
1634: ATENABLE(s, trp->tr_lock);
1635: *err = rc;
1636: return -1;
1637: }
1638: }
1639: trp->tr_rsp_wait = 0;
1640: ATENABLE(s, trp->tr_lock);
1641:
1642: if (trp->tr_state == TRANS_FAILED) {
1643: /*
1644: * transaction timed out, return error
1645: */
1646: atp_free(trp);
1647: *err = ETIMEDOUT;
1648: return -1;
1649: }
1650:
1651: /*
1652: * copy out the recv data
1653: */
1654: atp_pack_bdsp(trp, bds);
1655:
1656: /*
1657: * copyout the result info
1658: */
1659: copyout((caddr_t)bds, (caddr_t)buf, atpBDSsize);
1660:
1661: atp_free(trp);
1662:
1663: return (int)tid;
1664: } /* _ATPsndreq */
1665:
1666: int
1667: _ATPsndrsp(fd, respbuff, resplen, datalen, err, proc)
1668: int fd;
1669: unsigned char *respbuff;
1670: int resplen;
1671: int datalen;
1672: int *err;
1673: void *proc;
1674: {
1675: gref_t *gref;
1676: int s, rc;
1677: long bufaddr;
1678: gbuf_t *m, *mdata;
1679: register short len;
1680: register int size;
1681: register struct atp_state *atp;
1682: register struct atpBDS *bdsp;
1683: register char *buf;
1684:
1685: if ((*err = atalk_getref(0, fd, &gref, proc)) != 0)
1686: return -1;
1687:
1688: if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1689: || (atp->atp_flags & ATP_CLOSING)) {
1690: dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
1691: (u_int) gref, gref->pid));
1692:
1693: *err = EINVAL;
1694: return -1;
1695: }
1696:
1697: /*
1698: * allocate buffer and copy in the response info
1699: */
1700: while ((m = gbuf_alloc(resplen, PRI_MED)) == 0) {
1701: ATDISABLE(s, atp->atp_delay_lock);
1702: rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atprspinfo", 10);
1703: ATENABLE(s, atp->atp_delay_lock);
1704: if (rc != 0) {
1705: *err = rc;
1706: return -1;
1707: }
1708: }
1709: if ((*err = copyin((caddr_t)respbuff, (caddr_t)gbuf_rptr(m), resplen)) != 0) {
1710: gbuf_freeb(m);
1711: return -1;
1712: }
1713: gbuf_wset(m,resplen);
1714: ((at_ddp_t *)gbuf_rptr(m))->src_node = 0;
1715: bdsp = (struct atpBDS *)(gbuf_rptr(m) + TOTAL_ATP_HDR_SIZE);
1716: if ((resplen == TOTAL_ATP_HDR_SIZE) || ((len = UAS_VALUE(bdsp->bdsDataSz)) == 1))
1717: len = 0;
1718: else
1719: len = 16 * sizeof(gbuf_t);
1720:
1721: /*
1722: * allocate buffer and copy in the response data
1723: */
1724: while ((mdata = gbuf_alloc(datalen+len, PRI_MED)) == 0) {
1725: ATDISABLE(s, atp->atp_delay_lock);
1726: rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atprspdata", 10);
1727: ATENABLE(s, atp->atp_delay_lock);
1728: if (rc != 0) {
1729: gbuf_freem(m);
1730: *err = rc;
1731: return -1;
1732: }
1733: }
1734: gbuf_cont(m) = mdata;
1735: for (size=0; bdsp < (struct atpBDS *)gbuf_wptr(m); bdsp++) {
1736: if ((bufaddr = UAL_VALUE(bdsp->bdsBuffAddr)) != 0) {
1737: len = UAS_VALUE(bdsp->bdsBuffSz);
1738: buf = (char *)bufaddr;
1739: if ((*err = copyin((caddr_t)buf,
1740: (caddr_t)&gbuf_rptr(mdata)[size], len)) != 0) {
1741: gbuf_freem(m);
1742: return -1;
1743: }
1744: size += len;
1745: }
1746: }
1747: gbuf_wset(mdata,size);
1748:
1749: atp_send_rsp(gref, m, TRUE);
1750: return 0;
1751: }
1752:
1753: int
1754: _ATPgetreq(fd, buf, buflen, err, proc)
1755: int fd;
1756: unsigned char *buf;
1757: int buflen;
1758: int *err;
1759: void *proc;
1760: {
1761: gref_t *gref;
1762: register struct atp_state *atp;
1763: register struct atp_rcb *rcbp;
1764: register gbuf_t *m, *m_head;
1765: int s, size, len;
1766:
1767: if ((*err = atalk_getref(0, fd, &gref, proc)) != 0)
1768: return -1;
1769:
1770: if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1771: || (atp->atp_flags & ATP_CLOSING)) {
1772: dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
1773: (u_int) gref, gref->pid));
1774: *err = EINVAL;
1775: return -1;
1776: }
1777:
1778: ATDISABLE(s, atp->atp_lock);
1779: if ((rcbp = atp->atp_attached.head) != NULL) {
1780: /*
1781: * Got one, move it to the active response Q
1782: */
1783: m_head = rcbp->rc_ioctl;
1784: rcbp->rc_ioctl = NULL;
1785:
1786: if (rcbp->rc_xo) {
1787: ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
1788: rcbp->rc_state = RCB_NOTIFIED;
1789: ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
1790: } else {
1791: /* detach rcbp from attached queue,
1792: * and free any outstanding resources
1793: */
1794: atp_rcb_free(rcbp);
1795: }
1796: ATENABLE(s, atp->atp_lock);
1797:
1798: /*
1799: * copyout the request data, including the protocol header
1800: */
1801: for (size=0, m=m_head; m; m = gbuf_cont(m)) {
1802: if ((len = gbuf_len(m)) > buflen)
1803: len = buflen;
1804: copyout((caddr_t)gbuf_rptr(m), (caddr_t)&buf[size], len);
1805: size += len;
1806: if ((buflen -= len) == 0)
1807: break;
1808: }
1809: gbuf_freem(m_head);
1810:
1811: return size;
1812: }
1813: ATENABLE(s, atp->atp_lock);
1814:
1815: return -1;
1816: }
1817:
1818: int
1819: _ATPgetrsp(fd, bdsp, err, proc)
1820: int fd;
1821: struct atpBDS *bdsp;
1822: int *err;
1823: void *proc;
1824: {
1825: gref_t *gref;
1826: register struct atp_state *atp;
1827: register struct atp_trans *trp;
1828: int s, tid;
1829: char bds[atpBDSsize];
1830:
1831: if ((*err = atalk_getref(0, fd, &gref, proc)) != 0)
1832: return -1;
1833:
1834: if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1835: || (atp->atp_flags & ATP_CLOSING)) {
1836: dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
1837: (u_int) gref, gref->pid));
1838: *err = EINVAL;
1839: return -1;
1840: }
1841:
1842: ATDISABLE(s, atp->atp_lock);
1843: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
1844: dPrintf(D_M_ATP, D_L_INFO,
1845: ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
1846: (u_int) atp, (u_int) trp, trp->tr_state));
1847:
1848: switch (trp->tr_state) {
1849: case TRANS_DONE:
1850: ATENABLE(s, atp->atp_lock);
1851: if ((*err = copyin((caddr_t)bdsp,
1852: (caddr_t)bds, sizeof(bds))) != 0)
1853: return -1;
1854: atp_pack_bdsp(trp, bds);
1855: tid = (int)trp->tr_tid;
1856: atp_free(trp);
1857: copyout((caddr_t)bds, (caddr_t)bdsp, sizeof(bds));
1858: return tid;
1859:
1860: case TRANS_FAILED:
1861: /*
1862: * transaction timed out, return error
1863: */
1864: ATENABLE(s, atp->atp_lock);
1865: atp_free(trp);
1866: *err = ETIMEDOUT;
1867: return -1;
1868:
1869: default:
1870: continue;
1871: }
1872: }
1873: ATENABLE(s, atp->atp_lock);
1874:
1875: *err = EINVAL;
1876: return -1;
1877: }
1878:
1879: void
1880: atp_drop_req(gref, m)
1881: gref_t *gref;
1882: gbuf_t *m;
1883: {
1884: int s;
1885: struct atp_state *atp;
1886: struct atp_rcb *rcbp;
1887: at_atp_t *athp;
1888: at_ddp_t *ddp;
1889:
1890: atp = (struct atp_state *)gref->info;
1891: if (atp->dflag)
1892: atp = (struct atp_state *)atp->atp_msgq;
1893: ddp = AT_DDP_HDR(m);
1894: athp = AT_ATP_HDR(m);
1895:
1896: /*
1897: * search for the corresponding rcb
1898: */
1899: ATDISABLE(s, atp->atp_lock);
1900: for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
1901: if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) &&
1902: (rcbp->rc_socket.node == ddp->src_node) &&
1903: (rcbp->rc_socket.net == NET_VALUE(ddp->src_net)) &&
1904: (rcbp->rc_socket.socket == ddp->src_socket) )
1905: break;
1906: }
1907:
1908: /*
1909: * drop the request
1910: */
1911: if (rcbp)
1912: atp_rcb_free(rcbp);
1913: ATENABLE(s, atp->atp_lock);
1914:
1915: gbuf_freem(m);
1916: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.