Annotation of kernel/bsd/netat/atp_write.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.