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