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

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

unix.superglobalmegacorp.com

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