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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  *     Copyright (c) 1996-1998 Apple Computer, Inc.
        !            24:  *     All Rights Reserved.
        !            25:  */
        !            26: 
        !            27: /*    Modified for MP, 1996 by Tuyen Nguyen
        !            28:  *   Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
        !            29:  */
        !            30: #include <sys/errno.h>
        !            31: #include <sys/types.h>
        !            32: #include <sys/param.h>
        !            33: #include <machine/spl.h>
        !            34: #include <sys/systm.h>
        !            35: #include <sys/kernel.h>
        !            36: #include <sys/proc.h>
        !            37: #include <sys/filedesc.h>
        !            38: #include <sys/fcntl.h>
        !            39: #include <sys/mbuf.h>
        !            40: #include <sys/ioctl.h>
        !            41: #include <sys/malloc.h>
        !            42: #include <sys/socket.h>
        !            43: 
        !            44: #include <netat/sysglue.h>
        !            45: #include <netat/appletalk.h>
        !            46: #include <netat/ddp.h>
        !            47: #include <netat/at_pcb.h>
        !            48: #include <netat/atp.h>
        !            49: #include <netat/debug.h>
        !            50: 
        !            51: extern atlock_t atpgen_lock;
        !            52: void atp_free();
        !            53: void atp_send(struct atp_trans *);
        !            54: 
        !            55: /*
        !            56:  *     The request timer retries a request, if all retries are used up
        !            57:  *             it returns a NAK
        !            58:  */
        !            59: 
        !            60: void
        !            61: atp_req_timeout(trp)
        !            62: register struct atp_trans *trp;
        !            63: {
        !            64:        int s;
        !            65:        register gbuf_t *m;
        !            66:        gref_t *gref;
        !            67:        struct atp_state *atp;
        !            68:        struct atp_trans *ctrp;
        !            69: 
        !            70:        if ((atp = trp->tr_queue) == 0)
        !            71:                return;
        !            72:        ATDISABLE(s, atp->atp_lock);
        !            73:        if (atp->atp_flags & ATP_CLOSING) {
        !            74:                ATENABLE(s, atp->atp_lock);
        !            75:                return;
        !            76:        }
        !            77:        for (ctrp = atp->atp_trans_wait.head; ctrp; ctrp = ctrp->tr_list.next) {
        !            78:                if (ctrp == trp)
        !            79:                        break;
        !            80:        }
        !            81:        if (ctrp != trp) {
        !            82:                ATENABLE(s, atp->atp_lock);
        !            83:                return;
        !            84:        }
        !            85: 
        !            86:        if ((m = gbuf_cont(trp->tr_xmt)) == NULL)
        !            87:                m = trp->tr_xmt;               /* issued via the new interface */
        !            88: 
        !            89:        if (trp->tr_retry == 0) {
        !            90:                trp->tr_state = TRANS_FAILED;
        !            91:                if (m == trp->tr_xmt) {
        !            92:                        trp->tr_xmt = NULL;
        !            93: l_notify:
        !            94:                                gbuf_wset(m,1);
        !            95:                                *gbuf_rptr(m) = 99;
        !            96:                                gbuf_set_type(m, MSG_DATA);
        !            97:                                gref = trp->tr_queue->atp_gref;
        !            98:                                ATENABLE(s, atp->atp_lock);
        !            99:                                atalk_putnext(gref, m);
        !           100: 
        !           101:                        return;
        !           102:                }
        !           103:                dPrintf(D_M_ATP_LOW,D_L_INFO, ("atp_req_timeout: skt=%d\n",
        !           104:                        trp->tr_local_socket));
        !           105:                m = trp->tr_xmt;
        !           106:                switch(((ioc_t *)(gbuf_rptr(trp->tr_xmt)))->ioc_cmd) {
        !           107:                case AT_ATP_ISSUE_REQUEST:
        !           108:                        trp->tr_xmt = NULL;
        !           109:                        if (trp->tr_queue->dflag)
        !           110:                                ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_REQUEST_COMPLETE;
        !           111:                        else if (trp->tr_bdsp == NULL) {
        !           112:                                ATENABLE(s, atp->atp_lock);
        !           113:                                gbuf_freem(m);
        !           114:                                if (trp->tr_rsp_wait)
        !           115:                                        thread_wakeup(&trp->tr_event);
        !           116:                                break;
        !           117:                        }
        !           118:                        ATENABLE(s, atp->atp_lock);
        !           119:                        atp_iocnak(trp->tr_queue, m, ETIMEDOUT);
        !           120:                        atp_free(trp);
        !           121:                        return;
        !           122: 
        !           123:                case AT_ATP_ISSUE_REQUEST_NOTE:
        !           124:                case AT_ATP_ISSUE_REQUEST_TICKLE:
        !           125:                        trp->tr_xmt = gbuf_cont(m);
        !           126:                        gbuf_cont(m) = NULL;
        !           127:                        goto l_notify;
        !           128:                }
        !           129:        } else {
        !           130:                (AT_ATP_HDR(m))->bitmap = trp->tr_bitmap;
        !           131: 
        !           132:                if (trp->tr_retry != (unsigned int) ATP_INFINITE_RETRIES)
        !           133:                        trp->tr_retry--;
        !           134:                ATENABLE(s, atp->atp_lock);
        !           135:                atp_send(trp);
        !           136:        }
        !           137: }
        !           138: 
        !           139: 
        !           140: /*
        !           141:  *     atp_free frees up a request, cleaning up the queues and freeing
        !           142:  *             the request packet
        !           143:  *      always called at 'lock'
        !           144:  */
        !           145: 
        !           146: void atp_free(trp)
        !           147: register struct atp_trans *trp;
        !           148: {
        !           149:        register struct atp_state *atp;
        !           150:        register int i;
        !           151:        int s;
        !           152:        
        !           153:        dPrintf(D_M_ATP_LOW, D_L_TRACE,
        !           154:                ("atp_free: freeing trp 0x%x\n", (u_int) trp));
        !           155:        ATDISABLE(s, atpgen_lock);
        !           156:        if (trp->tr_tmo_func)
        !           157:                atp_untimout(atp_req_timeout, trp);
        !           158:        atp = trp->tr_queue;
        !           159: 
        !           160:        ATP_Q_REMOVE(atp->atp_trans_wait, trp, tr_list);
        !           161: 
        !           162:        if (trp->tr_xmt) {
        !           163:                gbuf_freem(trp->tr_xmt);
        !           164:                trp->tr_xmt = NULL;
        !           165:        }
        !           166:        for (i = 0; i < 8; i++) {
        !           167:                if (trp->tr_rcv[i]) {
        !           168:                        gbuf_freem(trp->tr_rcv[i]);
        !           169:                        trp->tr_rcv[i] = NULL;
        !           170:                }
        !           171:        }
        !           172:        if (trp->tr_bdsp) {
        !           173:                gbuf_freem(trp->tr_bdsp);
        !           174:                trp->tr_bdsp = NULL;
        !           175:        }
        !           176: 
        !           177:        ATENABLE(s, atpgen_lock);
        !           178:        atp_trans_free(trp);
        !           179: 
        !           180: } /* atp_free */
        !           181: 
        !           182: 
        !           183: /*
        !           184:  *     atp_send transmits a request packet by queuing it (if it isn't already) and
        !           185:  *             scheduling the queue
        !           186:  */
        !           187: 
        !           188: void atp_send(trp)
        !           189: register struct atp_trans *trp;
        !           190: {
        !           191:        gbuf_t *m;
        !           192:        struct atp_state *atp;
        !           193: 
        !           194:        dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ("atp_send: trp=0x%x, loc=%d\n",
        !           195:                (u_int) trp->tr_queue, trp->tr_local_socket));
        !           196: 
        !           197:        if ((atp = trp->tr_queue) != 0) {
        !           198:          if (trp->tr_state == TRANS_TIMEOUT) {
        !           199:            if ((m = gbuf_cont(trp->tr_xmt)) == NULL)
        !           200:                m = trp->tr_xmt;
        !           201: 
        !           202:            /*
        !           203:             *  Now either release the transaction or start the timer
        !           204:             */
        !           205:            if (!trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo) {
        !           206:                m = (gbuf_t *)gbuf_copym(m);
        !           207:                atp_x_done(trp);
        !           208:            } else {
        !           209:                m = (gbuf_t *)gbuf_dupm(m);
        !           210: 
        !           211:                atp_timout(atp_req_timeout, trp, trp->tr_timeout);
        !           212:            }
        !           213: 
        !           214:            if (m) {    
        !           215:                trace_mbufs(D_M_ATP_LOW, "  m", m);
        !           216:                DDP_OUTPUT(m);
        !           217:            }
        !           218:        }
        !           219:   }
        !           220: }
        !           221: 
        !           222: 
        !           223: /*
        !           224:  *     atp_reply sends all the available messages in the bitmap again
        !           225:  *             by queueing us to the write service routine
        !           226:  */
        !           227: 
        !           228: void atp_reply(rcbp)
        !           229: register struct atp_rcb *rcbp;
        !           230: {
        !           231:        register struct atp_state *atp;
        !           232:        register int i;
        !           233:        int s;
        !           234: 
        !           235:   if ((atp = rcbp->rc_queue) != 0) {
        !           236:        ATDISABLE(s, atp->atp_lock);
        !           237:        for (i = 0; i < rcbp->rc_pktcnt; i++) {
        !           238:                if (rcbp->rc_bitmap&atp_mask[i])
        !           239:                        rcbp->rc_snd[i] = 1;
        !           240:                else
        !           241:                        rcbp->rc_snd[i] = 0;
        !           242:        }
        !           243:         if (rcbp->rc_rep_waiting == 0) {
        !           244:                rcbp->rc_state = RCB_SENDING;
        !           245:                rcbp->rc_rep_waiting = 1;
        !           246:                ATENABLE(s, atp->atp_lock);
        !           247:                atp_send_replies(atp, rcbp);
        !           248:        } else
        !           249:        ATENABLE(s, atp->atp_lock);
        !           250:   }
        !           251: }
        !           252: 
        !           253: 
        !           254: /*
        !           255:  *     The rcb timer just frees the rcb, this happens when we missed a release for XO
        !           256:  */
        !           257: 
        !           258: void atp_rcb_timer()
        !           259: {  
        !           260:        int s;
        !           261:         register struct atp_rcb *rcbp;
        !           262:        register struct atp_rcb *next_rcbp;
        !           263:        extern   struct atp_rcb_qhead atp_need_rel;
        !           264:        extern struct atp_trans *trp_tmo_rcb;
        !           265: 
        !           266: l_again:
        !           267:        ATDISABLE(s, atpgen_lock);
        !           268:        for (rcbp = atp_need_rel.head; rcbp; rcbp = next_rcbp) {
        !           269:                next_rcbp = rcbp->rc_tlist.next;
        !           270: 
        !           271:                if (abs(time.tv_sec - rcbp->rc_timestamp) > 30) {
        !           272:                        ATENABLE(s, atpgen_lock);
        !           273:                        atp_rcb_free(rcbp);
        !           274:                        goto l_again;
        !           275:                }
        !           276:        }
        !           277:        ATENABLE(s, atpgen_lock);
        !           278:        atp_timout(atp_rcb_timer, trp_tmo_rcb, 10 * HZ);
        !           279: }
        !           280: 
        !           281: atp_iocack(atp, m)
        !           282: struct   atp_state *atp;
        !           283: register gbuf_t *m;
        !           284: {
        !           285:        if (gbuf_type(m) == MSG_IOCTL)
        !           286:                gbuf_set_type(m, MSG_IOCACK);
        !           287:        if (gbuf_cont(m))
        !           288:                ((ioc_t *)gbuf_rptr(m))->ioc_count = gbuf_msgsize(gbuf_cont(m));
        !           289:        else
        !           290:                ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
        !           291: 
        !           292:        if (atp->dflag)
        !           293:                asp_ack_reply(atp->atp_gref, m);
        !           294:        else
        !           295:                atalk_putnext(atp->atp_gref, m);
        !           296: }
        !           297: 
        !           298: atp_iocnak(atp, m, err)
        !           299: struct   atp_state *atp;
        !           300: register gbuf_t *m;
        !           301: register int err;
        !           302: {
        !           303:        if (gbuf_type(m) == MSG_IOCTL)
        !           304:                gbuf_set_type(m, MSG_IOCNAK);
        !           305:        ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
        !           306:        ((ioc_t *)gbuf_rptr(m))->ioc_error = err ? err : ENXIO;
        !           307:        ((ioc_t *)gbuf_rptr(m))->ioc_rval = -1;
        !           308:        if (gbuf_cont(m)) {
        !           309:                gbuf_freem(gbuf_cont(m));
        !           310:                gbuf_cont(m) = NULL;
        !           311:        }
        !           312: 
        !           313:        if (atp->dflag)
        !           314:                asp_nak_reply(atp->atp_gref, m);
        !           315:        else
        !           316:                atalk_putnext(atp->atp_gref, m);
        !           317: }
        !           318: 
        !           319: /*
        !           320:  *     Generate a transaction id for a socket
        !           321:  */
        !           322: static int lasttid;
        !           323: atp_tid(atp)
        !           324: register struct atp_state *atp;
        !           325: {
        !           326:        register int i;
        !           327:        register struct atp_trans *trp;
        !           328:        int s;
        !           329: 
        !           330:        ATDISABLE(s, atpgen_lock);
        !           331:        for (i = lasttid;;) {
        !           332:                i = (i+1)&0xffff;
        !           333: 
        !           334:                for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
        !           335:                        if (trp->tr_tid == i)
        !           336:                                break;
        !           337:                }
        !           338:                if (trp == NULL) {
        !           339:                        lasttid = i;
        !           340:                        ATENABLE(s, atpgen_lock);
        !           341:                        return(i);
        !           342:                }
        !           343:        }
        !           344: }

unix.superglobalmegacorp.com

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