Annotation of XNU/bsd/netat/atp_write.c, revision 1.1.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.