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

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

unix.superglobalmegacorp.com

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